import { render, screen, fireEvent } from '@testing-library/react'
import { CommandResultItem } from '../CommandResultItem'

// lucide-react icons are SVGs — mock them as simple elements so tests are
// not sensitive to SVG implementation details while still being renderable.
jest.mock('lucide-react', () => ({
  Search: (props: React.SVGProps<SVGSVGElement>) => (
    <svg data-testid="icon-search" {...props} />
  ),
  ArrowRight: (props: React.SVGProps<SVGSVGElement>) => (
    <svg data-testid="icon-arrow-right" {...props} />
  ),
}))

const StarIcon = (props: React.SVGProps<SVGSVGElement>) => (
  <svg data-testid="icon-star" {...props} />
)

describe('CommandResultItem', () => {
  const defaultProps = {
    label: 'Go to Dashboard',
    selected: false,
    onClick: jest.fn(),
  }

  beforeEach(() => {
    jest.clearAllMocks()
  })

  describe('label', () => {
    it('renders the label text', () => {
      render(<CommandResultItem {...defaultProps} />)
      expect(screen.getByText('Go to Dashboard')).toBeInTheDocument()
    })
  })

  describe('detail', () => {
    it('renders detail text when provided', () => {
      render(<CommandResultItem {...defaultProps} detail="Overview of metrics" />)
      expect(screen.getByText('Overview of metrics')).toBeInTheDocument()
    })

    it('does not render detail element when omitted', () => {
      render(<CommandResultItem {...defaultProps} />)
      // Only the label paragraph should be present; no second <p>
      const paragraphs = document.querySelectorAll('p')
      expect(paragraphs).toHaveLength(1)
    })
  })

  describe('shortcut', () => {
    it('renders the shortcut in a kbd element when provided', () => {
      render(<CommandResultItem {...defaultProps} shortcut="⌘K" />)
      const kbd = screen.getByText('⌘K')
      expect(kbd.tagName).toBe('KBD')
    })

    it('does not render a kbd element when shortcut is omitted', () => {
      const { container } = render(<CommandResultItem {...defaultProps} />)
      expect(container.querySelector('kbd')).not.toBeInTheDocument()
    })
  })

  describe('icon', () => {
    it('renders the provided icon', () => {
      render(<CommandResultItem {...defaultProps} icon={StarIcon} />)
      expect(screen.getByTestId('icon-star')).toBeInTheDocument()
    })

    it('falls back to Search icon when no icon prop is given', () => {
      render(<CommandResultItem {...defaultProps} />)
      expect(screen.getByTestId('icon-search')).toBeInTheDocument()
    })
  })

  describe('showArrow', () => {
    it('does not render ArrowRight by default', () => {
      render(<CommandResultItem {...defaultProps} />)
      expect(screen.queryByTestId('icon-arrow-right')).not.toBeInTheDocument()
    })

    it('renders ArrowRight when showArrow is true', () => {
      render(<CommandResultItem {...defaultProps} showArrow />)
      expect(screen.getByTestId('icon-arrow-right')).toBeInTheDocument()
    })
  })

  describe('selected state', () => {
    it('sets aria-selected="true" when selected', () => {
      render(<CommandResultItem {...defaultProps} selected />)
      const item = screen.getByRole('option')
      expect(item).toHaveAttribute('aria-selected', 'true')
    })

    it('sets aria-selected="false" when not selected', () => {
      render(<CommandResultItem {...defaultProps} selected={false} />)
      const item = screen.getByRole('option')
      expect(item).toHaveAttribute('aria-selected', 'false')
    })

    it('applies bg-blue-50 highlight class when selected', () => {
      render(<CommandResultItem {...defaultProps} selected />)
      const item = screen.getByRole('option')
      expect(item.className).toMatch(/bg-blue-50/)
    })

    it('does not apply bg-blue-50 when not selected', () => {
      render(<CommandResultItem {...defaultProps} selected={false} />)
      const item = screen.getByRole('option')
      expect(item.className).not.toMatch(/bg-blue-50/)
    })
  })

  describe('colorClass', () => {
    it('applies the default color class to the icon container', () => {
      const { container } = render(<CommandResultItem {...defaultProps} />)
      const iconContainer = container.querySelector('.w-8.h-8')
      expect(iconContainer?.className).toMatch(/bg-gray-100/)
      expect(iconContainer?.className).toMatch(/text-gray-600/)
    })

    it('applies a custom colorClass to the icon container', () => {
      const { container } = render(
        <CommandResultItem {...defaultProps} colorClass="bg-blue-100 text-blue-600" />
      )
      const iconContainer = container.querySelector('.w-8.h-8')
      expect(iconContainer?.className).toMatch(/bg-blue-100/)
      expect(iconContainer?.className).toMatch(/text-blue-600/)
    })
  })

  describe('onClick', () => {
    it('fires onClick when the item is clicked', () => {
      const onClick = jest.fn()
      render(<CommandResultItem {...defaultProps} onClick={onClick} />)
      fireEvent.click(screen.getByRole('option'))
      expect(onClick).toHaveBeenCalledTimes(1)
    })

    it('does not fire onClick when a different element is clicked', () => {
      const onClick = jest.fn()
      render(
        <div>
          <CommandResultItem {...defaultProps} onClick={onClick} label="Target" />
          <button data-testid="other">Other</button>
        </div>
      )
      fireEvent.click(screen.getByTestId('other'))
      expect(onClick).not.toHaveBeenCalled()
    })
  })

  describe('label typography without detail', () => {
    it('uses text-gray-700 on label when no detail is present', () => {
      render(<CommandResultItem {...defaultProps} />)
      const label = screen.getByText('Go to Dashboard')
      expect(label.className).toMatch(/text-gray-700/)
    })

    it('uses text-gray-900 on label when detail is present', () => {
      render(<CommandResultItem {...defaultProps} detail="some detail" />)
      const label = screen.getByText('Go to Dashboard')
      expect(label.className).toMatch(/text-gray-900/)
    })
  })
})
