import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import NavbarClient from '@/components/layout/NavbarClient'
import type { Category } from '@/lib/types'

const mockPush = vi.fn()

vi.mock('next/navigation', () => ({
  usePathname: vi.fn(() => '/'),
  useRouter: vi.fn(() => ({ push: mockPush })),
}))

const categories: Category[] = [
  { id: '1', name: 'Anime', slug: 'anime', description: 'Anime news' },
  { id: '2', name: 'Games', slug: 'games', description: null },
  { id: '3', name: 'Music', slug: 'music', description: 'Music coverage' },
]

describe('NavbarClient', () => {
  beforeEach(() => {
    mockPush.mockReset()
    document.body.style.overflow = ''
  })

  it('renders all category links', () => {
    render(<NavbarClient categories={categories} />)
    expect(screen.getByText('Anime')).toBeInTheDocument()
    expect(screen.getByText('Games')).toBeInTheDocument()
    expect(screen.getByText('Music')).toBeInTheDocument()
  })

  it('renders the site logo', () => {
    render(<NavbarClient categories={categories} />)
    expect(screen.getByText('言羽')).toBeInTheDocument()
  })

  it('renders a search button', () => {
    render(<NavbarClient categories={categories} />)
    expect(screen.getByLabelText('Open search')).toBeInTheDocument()
  })

  it('dispatches custom event when search button is clicked', () => {
    const dispatchSpy = vi.fn()
    window.dispatchEvent = dispatchSpy

    render(<NavbarClient categories={categories} />)
    fireEvent.click(screen.getByLabelText('Open search'))

    expect(dispatchSpy).toHaveBeenCalledWith(
      expect.objectContaining({ type: 'kotobane:open-search' })
    )
  })

  it('shows mobile hamburger menu button', () => {
    render(<NavbarClient categories={categories} />)
    expect(screen.getByLabelText('Open menu')).toBeInTheDocument()
  })

  it('opens mobile overlay when hamburger is clicked', () => {
    render(<NavbarClient categories={categories} />)
    fireEvent.click(screen.getByLabelText('Open menu'))
    expect(screen.getByLabelText('Close menu')).toBeInTheDocument()
  })

  it('closes mobile overlay when close button is clicked', () => {
    render(<NavbarClient categories={categories} />)
    fireEvent.click(screen.getByLabelText('Open menu'))
    expect(screen.getByLabelText('Close menu')).toBeInTheDocument()

    fireEvent.click(screen.getByLabelText('Close menu'))
    expect(screen.queryByLabelText('Close menu')).not.toBeInTheDocument()
  })

  it('closes mobile overlay when backdrop is clicked', () => {
    render(<NavbarClient categories={categories} />)
    fireEvent.click(screen.getByLabelText('Open menu'))
    const backdrop = document.querySelector('.bg-black\\/60')
    expect(backdrop).toBeInTheDocument()
    if (backdrop) fireEvent.click(backdrop)
    expect(screen.queryByLabelText('Close menu')).not.toBeInTheDocument()
  })

  it('locks body scroll when menu is open, unlocks when closed', () => {
    render(<NavbarClient categories={categories} />)
    fireEvent.click(screen.getByLabelText('Open menu'))
    expect(document.body.style.overflow).toBe('hidden')

    fireEvent.click(screen.getByLabelText('Close menu'))
    expect(document.body.style.overflow).toBe('')
  })

  it('marks the current path category as active', async () => {
    const { usePathname } = await import('next/navigation')
    vi.mocked(usePathname).mockReturnValue('/anime')

    render(<NavbarClient categories={categories} />)
    const animeLink = screen.getByText('Anime').closest('a')
    expect(animeLink).toHaveClass('text-accent')
  })
})
