import { describe, it, expect, beforeEach, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { setActivePinia, createPinia } from 'pinia'
import { createRouter, createMemoryHistory } from 'vue-router'
import FolderTreeItem from '../FolderTreeItem.vue'

const mockListFolders = vi.fn()

vi.mock('../../../api/client.js', () => ({
  listFolders: (...a) => mockListFolders(...a),
}))

// Minimal router so router-link renders correctly
function makeRouter(currentPath = '/') {
  return createRouter({
    history: createMemoryHistory(),
    routes: [
      { path: '/', component: { template: '<div/>' } },
      { path: '/folders/:folderId', component: { template: '<div/>' } },
    ],
  })
}

function makeFolder(overrides = {}) {
  return {
    id: overrides.id ?? 'f1',
    name: overrides.name ?? 'Test',
    parent_id: overrides.parent_id ?? null,
    has_children: overrides.has_children ?? false,
    created_at: '2026-01-01T00:00:00Z',
    ...overrides,
  }
}

async function mountItem(folderOverrides = {}, routerPath = '/') {
  setActivePinia(createPinia())
  const router = makeRouter(routerPath)
  await router.push(routerPath)
  await router.isReady()
  return mount(FolderTreeItem, {
    props: { folder: makeFolder(folderOverrides), depth: 1 },
    global: { plugins: [router] },
  })
}

describe('FolderTreeItem', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockListFolders.mockResolvedValue({ items: [] })
  })

  // ── Expand arrow visibility ───────────────────────────────────────────────

  it('hides expand arrow when has_children is false', async () => {
    const w = await mountItem({ has_children: false })
    // The expand button should not be rendered
    const expandBtn = w.find('button')
    expect(expandBtn.exists()).toBe(false)
  })

  it('shows expand arrow when has_children is true', async () => {
    const w = await mountItem({ has_children: true })
    const expandBtn = w.find('button')
    expect(expandBtn.exists()).toBe(true)
  })

  it('shows expand arrow when has_children is undefined (unknown)', async () => {
    // Newly created folders from optimistic push lack has_children
    const folder = { id: 'f1', name: 'New', parent_id: null, created_at: '2026-01-01T00:00:00Z' }
    setActivePinia(createPinia())
    const router = makeRouter('/')
    await router.push('/')
    await router.isReady()
    const w = mount(FolderTreeItem, {
      props: { folder, depth: 1 },
      global: { plugins: [router] },
    })
    // has_children undefined → arrow shown (conservative: assume could have children)
    const expandBtn = w.find('button')
    expect(expandBtn.exists()).toBe(true)
  })

  // ── Router-link href ──────────────────────────────────────────────────────

  it('router-link points to /folders/<id>', async () => {
    const w = await mountItem({ id: 'abc-123' })
    const link = w.find('a')
    expect(link.attributes('href')).toBe('/folders/abc-123')
  })

  // ── Active state ─────────────────────────────────────────────────────────

  it('router-link has active class when route matches folder id', async () => {
    setActivePinia(createPinia())
    const router = makeRouter()
    await router.push('/folders/f1')
    await router.isReady()

    const w = mount(FolderTreeItem, {
      props: { folder: makeFolder({ id: 'f1' }), depth: 1 },
      global: { plugins: [router] },
    })

    const link = w.find('a')
    expect(link.classes()).toContain('bg-indigo-50')
  })

  it('router-link does NOT have active class when route does not match', async () => {
    setActivePinia(createPinia())
    const router = makeRouter()
    await router.push('/folders/other-folder')
    await router.isReady()

    const w = mount(FolderTreeItem, {
      props: { folder: makeFolder({ id: 'f1' }), depth: 1 },
      global: { plugins: [router] },
    })

    const link = w.find('a')
    expect(link.classes()).not.toContain('bg-indigo-50')
  })

  // ── Expand / collapse children ────────────────────────────────────────────

  it('clicking expand arrow loads children from API', async () => {
    const children = [makeFolder({ id: 'child-1', name: 'Child', parent_id: 'f1' })]
    mockListFolders.mockResolvedValue({ items: children })

    const w = await mountItem({ id: 'f1', has_children: true })
    const btn = w.find('button')
    await btn.trigger('click')
    await w.vm.$nextTick()

    expect(mockListFolders).toHaveBeenCalledWith('f1')
  })

  it('children are rendered after expand', async () => {
    const children = [makeFolder({ id: 'child-1', name: 'ChildFolder', parent_id: 'f1' })]
    mockListFolders.mockResolvedValue({ items: children })

    const w = await mountItem({ id: 'f1', has_children: true })
    await w.find('button').trigger('click')
    await w.vm.$nextTick()

    expect(w.text()).toContain('ChildFolder')
  })

  it('expand arrow disappears after loading empty children', async () => {
    mockListFolders.mockResolvedValue({ items: [] })

    const w = await mountItem({ id: 'f1', has_children: true })
    await w.find('button').trigger('click')
    await w.vm.$nextTick()

    // After loading empty children, button should be gone
    expect(w.find('button').exists()).toBe(false)
  })

  // ── Depth indentation ────────────────────────────────────────────────────

  it('applies correct left padding based on depth', async () => {
    setActivePinia(createPinia())
    const router = makeRouter('/')
    await router.push('/')
    await router.isReady()

    const w = mount(FolderTreeItem, {
      props: { folder: makeFolder(), depth: 3 },
      global: { plugins: [router] },
    })

    const row = w.find('.flex.items-center')
    expect(row.attributes('style')).toContain('padding-left: 36px')
  })
})
