import { describe, expect, it, vi } from 'vitest'
import { fireEvent, render, waitFor } from '@testing-library/react'

import { Sidebar, SidebarCollapseButton, type SidebarSection } from './sidebar'

const sidebarSections: SidebarSection[] = [
  {
    id: 'dashboards',
    label: 'Dashboards',
    items: [
      { id: 'library', label: 'Library', href: '/app', icon: 'library' },
      { id: 'jobs', label: 'Jobs', icon: 'jobs' },
    ],
  },
]

const routeSections: SidebarSection[] = [
  {
    id: 'main',
    label: 'Dashboards',
    items: [
      { id: 'library', label: 'Library', href: '/app', end: true },
      { id: 'jobs', label: 'Jobs', href: '/app/jobs' },
    ],
  },
]

describe('Sidebar', () => {
  it('mounts the vanilla SidebarComponent and syncs controlled state', async () => {
    const onNavigate = vi.fn()
    const { container, rerender } = render(
      <Sidebar
        className="react-host"
        variant="cm"
        sections={sidebarSections}
        activeItemId="library"
        open
        onNavigate={onNavigate}
      />
    )

    await waitFor(() => {
      expect(container.querySelector('.sidebar')).toBeTruthy()
    })

    const host = container.querySelector<HTMLElement>('[data-slot="sidebar"]')
    const aside = container.querySelector<HTMLElement>('.sidebar')
    const library = container.querySelector<HTMLElement>('[data-item-id="library"]')

    expect(host?.classList.contains('react-host')).toBe(true)
    expect(aside?.classList.contains('sidebar--product')).toBe(true)
    expect(aside?.getAttribute('data-sidebar')).toBe('cm')
    expect(aside?.getAttribute('data-open')).toBe('true')
    expect(library?.getAttribute('aria-current')).toBe('page')
    expect(container.querySelectorAll('.sidebar')).toHaveLength(1)

    rerender(
      <Sidebar
        className="react-host"
        variant="cm"
        sections={sidebarSections}
        activeItemId="jobs"
        open={false}
        onNavigate={onNavigate}
      />
    )

    await waitFor(() => {
      expect(container.querySelector('[data-item-id="jobs"]')?.getAttribute('aria-current')).toBe(
        'page'
      )
      expect(container.querySelector('.sidebar')?.getAttribute('data-open')).toBe('false')
    })

    fireEvent.click(container.querySelector<HTMLElement>('[data-item-id="jobs"]')!)

    expect(onNavigate).toHaveBeenCalledWith(expect.objectContaining({ id: 'jobs' }))
    expect(container.querySelectorAll('.sidebar')).toHaveLength(1)
  })

  it('keeps route-derived active state in the vanilla component when pathname changes', async () => {
    const { container, rerender } = render(
      <Sidebar variant="cm" sections={routeSections} pathname="/app" />
    )

    await waitFor(() => {
      expect(
        container.querySelector('[data-item-id="library"]')?.getAttribute('aria-current')
      ).toBe('page')
    })

    rerender(<Sidebar variant="cm" sections={routeSections} pathname="/app/jobs" />)

    await waitFor(() => {
      expect(
        container.querySelector('[data-item-id="library"]')?.getAttribute('aria-current')
      ).toBe(null)
      expect(container.querySelector('[data-item-id="jobs"]')?.getAttribute('aria-current')).toBe(
        'page'
      )
    })

    expect(container.querySelectorAll('.sidebar')).toHaveLength(1)
  })
})

describe('SidebarCollapseButton', () => {
  it('renders the shared edge-docked collapse control', () => {
    const { container } = render(<SidebarCollapseButton edge />)
    const button = container.querySelector('button')

    expect(button).toBeTruthy()
    expect(button?.getAttribute('aria-label')).toBe('Collapse sidebar')
    expect(button?.getAttribute('aria-expanded')).toBe('true')
    expect(button?.getAttribute('title')).toBe('Collapse sidebar')
    expect(button?.classList.contains('sidebar__collapse-btn')).toBe(true)
    expect(button?.classList.contains('sidebar__collapse-btn--edge')).toBe(true)
    expect(button?.querySelector('path')?.getAttribute('d')).toBe('m15 18-6-6 6-6')
  })

  it('switches affordance metadata for collapsed sidebars', () => {
    const { container } = render(<SidebarCollapseButton collapsed edge visible />)
    const button = container.querySelector('button')

    expect(button?.getAttribute('aria-label')).toBe('Expand sidebar')
    expect(button?.getAttribute('aria-expanded')).toBe('false')
    expect(button?.getAttribute('data-collapsed')).toBe('true')
    expect(button?.getAttribute('data-visible')).toBe('true')
    expect(button?.querySelector('path')?.getAttribute('d')).toBe('m9 18 6-6-6-6')
  })
})
