import { describe, test, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import { BasemapsUI } from './basemaps'
import type { BasemapOption } from './types'

// Mock the child components
vi.mock('./header', () => ({
  Header: ({ onChangeCollapsed }: { onChangeCollapsed: () => void }) => (
    <div data-testid='mock-header'>
      <button data-testid='close-button' onClick={onChangeCollapsed}>
        Close
      </button>
    </div>
  ),
}))

vi.mock('./group', () => ({
  Group: ({
    values,
    selected,
    onChange,
  }: {
    values: BasemapOption[]
    selected: string | null
    onChange: (id: string) => void
  }) => (
    <div data-testid='mock-group'>
      {values.map((option) => (
        <button
          key={option.id}
          data-testid={`basemap-option-${option.id}`}
          data-selected={option.id === selected}
          onClick={() => onChange(option.id)}
        >
          {option.label}
        </button>
      ))}
    </div>
  ),
}))

vi.mock('./group-wrapper', () => ({
  GroupWrapper: ({
    title,
    children,
  }: {
    title: string
    children: React.ReactNode
  }) => (
    <div data-testid='mock-group-wrapper' data-title={title}>
      {children}
    </div>
  ),
}))

vi.mock('../responsive-drawer/responsive-drawer', () => ({
  ResponsiveDrawer: ({
    children,
    collapsed,
  }: {
    children: React.ReactNode
    collapsed: boolean
  }) => (
    <div data-testid='mock-drawer' data-collapsed={collapsed}>
      {children}
    </div>
  ),
}))

describe('BasemapsUI', () => {
  const mockOptions: BasemapOption[] = [
    { id: 'basemap1', label: 'Basemap 1', icon: 'icon1.png', group: 'Group 1' },
    { id: 'basemap2', label: 'Basemap 2', icon: 'icon2.png', group: 'Group 1' },
    { id: 'basemap3', label: 'Basemap 3', icon: 'icon3.png', group: 'Group 2' },
  ]

  const mockOnChange = vi.fn()

  beforeEach(() => {
    mockOnChange.mockReset()
  })

  test('should render with toggle button initially', () => {
    render(
      <BasemapsUI
        options={mockOptions}
        selected='basemap1'
        onChange={mockOnChange}
      />,
    )

    // Drawer should be collapsed initially
    const drawer = screen.getByTestId('mock-drawer')
    expect(drawer.getAttribute('data-collapsed')).toBe('true')

    // Toggle button should be visible
    expect(screen.getAllByRole('button')[0]).toBeDefined()
  })

  test('should show drawer when toggle button is clicked', () => {
    render(
      <BasemapsUI
        options={mockOptions}
        selected='basemap1'
        onChange={mockOnChange}
      />,
    )

    // Click toggle button
    const toggleButton = screen.getAllByRole('button')[0]!
    fireEvent.click(toggleButton)

    // Drawer should not be collapsed after toggle
    const drawer = screen.getByTestId('mock-drawer')
    expect(drawer.getAttribute('data-collapsed')).toBe('false')
  })

  test('should pass correct props to Group component', () => {
    render(
      <BasemapsUI
        options={mockOptions}
        selected='basemap1'
        onChange={mockOnChange}
      />,
    )

    // Click toggle button to show drawer
    const toggleButton = screen.getAllByRole('button')[0]!
    fireEvent.click(toggleButton)

    // Group wrappers should be rendered with correct titles
    const groupWrappers = screen.getAllByTestId('mock-group-wrapper')
    expect(groupWrappers.length).toBe(2) // Two groups
    expect(groupWrappers[0]?.getAttribute('data-title')).toContain('Group 1')
    expect(groupWrappers[1]?.getAttribute('data-title')).toContain('Group 2')

    // Check basemap options are rendered
    expect(screen.getByTestId('basemap-option-basemap1')).toBeDefined()
    expect(screen.getByTestId('basemap-option-basemap2')).toBeDefined()
    expect(screen.getByTestId('basemap-option-basemap3')).toBeDefined()
  })

  test('should call onChange when a basemap is selected', () => {
    render(
      <BasemapsUI
        options={mockOptions}
        selected='basemap1'
        onChange={mockOnChange}
      />,
    )

    // Click toggle button to show drawer
    const toggleButton = screen.getAllByRole('button')[0]!
    fireEvent.click(toggleButton)

    // Click a basemap option
    const basemapOption = screen.getByTestId('basemap-option-basemap2')
    fireEvent.click(basemapOption)

    // onChange should be called with correct ID
    expect(mockOnChange).toHaveBeenCalledWith('basemap2')
  })

  test('should handle small devices correctly using media query', () => {
    // Mock matchMedia for small devices
    window.matchMedia = vi.fn().mockImplementation((query: string) => ({
      matches: query.includes('max-width'),
      media: query,
      onchange: null,
      addListener: vi.fn(),
      removeListener: vi.fn(),
      addEventListener: vi.fn(),
      removeEventListener: vi.fn(),
      dispatchEvent: vi.fn(),
    }))

    render(
      <BasemapsUI
        options={mockOptions}
        selected='basemap1'
        onChange={mockOnChange}
        position='bottom-right'
      />,
    )

    // Check if drawer behavior is appropriate for small devices
    const drawer = screen.getByTestId('mock-drawer')

    // Toggle button should still be visible on small devices
    const toggleButton = screen.getAllByRole('button')[0]
    expect(toggleButton).toBeDefined()

    // Drawer should be collapsed initially even on small devices
    expect(drawer.getAttribute('data-collapsed')).toBe('true')
  })
})
