import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import type { Game } from '../types'
import { GameGrid } from './GameGrid'

const RED: Game = {
  id: 1,
  name: 'Pokemon Red',
  slug: 'red',
  generation: 1,
  region: 'kanto',
  category: null,
  boxArtUrl: null,
  color: null,
  releaseYear: null,
  versionGroupId: 1,
}

const GOLD: Game = {
  id: 2,
  name: 'Pokemon Gold',
  slug: 'gold',
  generation: 2,
  region: 'johto',
  category: null,
  boxArtUrl: null,
  color: null,
  releaseYear: null,
  versionGroupId: 2,
}

const RUBY: Game = {
  id: 3,
  name: 'Pokemon Ruby',
  slug: 'ruby',
  generation: 3,
  region: 'hoenn',
  category: null,
  boxArtUrl: null,
  color: null,
  releaseYear: null,
  versionGroupId: 3,
}

function setup(overrides: Partial<React.ComponentProps<typeof GameGrid>> = {}) {
  const props = {
    games: [RED, GOLD, RUBY],
    selectedId: null,
    onSelect: vi.fn(),
    ...overrides,
  }
  render(<GameGrid {...props} />)
  return props
}

describe('GameGrid', () => {
  it('renders all game names', () => {
    setup()
    expect(screen.getByText('Pokemon Red')).toBeInTheDocument()
    expect(screen.getByText('Pokemon Gold')).toBeInTheDocument()
    expect(screen.getByText('Pokemon Ruby')).toBeInTheDocument()
  })

  it('renders generation filter pills for each unique generation', () => {
    setup()
    expect(screen.getByRole('button', { name: 'Gen 1' })).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'Gen 2' })).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'Gen 3' })).toBeInTheDocument()
  })

  it('filters games when a generation pill is clicked', async () => {
    setup()
    await userEvent.click(screen.getByRole('button', { name: 'Gen 1' }))
    expect(screen.getByText('Pokemon Red')).toBeInTheDocument()
    expect(screen.queryByText('Pokemon Gold')).not.toBeInTheDocument()
    expect(screen.queryByText('Pokemon Ruby')).not.toBeInTheDocument()
  })

  it('restores all games when "All" generation pill is clicked', async () => {
    setup()
    await userEvent.click(screen.getByRole('button', { name: 'Gen 1' }))
    await userEvent.click(screen.getAllByRole('button', { name: 'All' })[0]!)
    expect(screen.getByText('Pokemon Red')).toBeInTheDocument()
    expect(screen.getByText('Pokemon Gold')).toBeInTheDocument()
    expect(screen.getByText('Pokemon Ruby')).toBeInTheDocument()
  })

  it('filters games when a region pill is clicked', async () => {
    setup()
    await userEvent.click(screen.getByRole('button', { name: 'Johto' }))
    expect(screen.queryByText('Pokemon Red')).not.toBeInTheDocument()
    expect(screen.getByText('Pokemon Gold')).toBeInTheDocument()
    expect(screen.queryByText('Pokemon Ruby')).not.toBeInTheDocument()
  })

  it('calls onSelect with the game when a game card is clicked', async () => {
    const { onSelect } = setup()
    await userEvent.click(screen.getByText('Pokemon Red'))
    expect(onSelect).toHaveBeenCalledWith(RED)
  })

  it('hides games with active runs when the checkbox is ticked', async () => {
    setup({
      runs: [{ id: 10, gameId: 1, status: 'active' } as never],
    })
    await userEvent.click(screen.getByLabelText(/hide games with active run/i))
    expect(screen.queryByText('Pokemon Red')).not.toBeInTheDocument()
    expect(screen.getByText('Pokemon Gold')).toBeInTheDocument()
  })

  it('does not render run-based checkboxes when runs prop is omitted', () => {
    setup({ runs: undefined })
    expect(screen.queryByLabelText(/hide games with active run/i)).not.toBeInTheDocument()
  })
})
