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

// ---------------------------------------------------------------------------
// ListCard
// ---------------------------------------------------------------------------

describe('ListCard', () => {
  const baseProps = {
    name: 'My Prospect List',
    sourceType: 'static',
    memberCount: 42,
    createdAt: 'Jan 1, 2025',
  }

  it('renders the list name', () => {
    render(<ListCard {...baseProps} />)
    expect(screen.getByText('My Prospect List')).toBeInTheDocument()
  })

  it('renders member count with singular "member"', () => {
    render(<ListCard {...baseProps} memberCount={1} />)
    expect(screen.getByText('1 member')).toBeInTheDocument()
  })

  it('renders member count with plural "members"', () => {
    render(<ListCard {...baseProps} memberCount={42} />)
    expect(screen.getByText('42 members')).toBeInTheDocument()
  })

  it('renders zero members correctly', () => {
    render(<ListCard {...baseProps} memberCount={0} />)
    expect(screen.getByText('0 members')).toBeInTheDocument()
  })

  it('renders large member count with locale formatting', () => {
    render(<ListCard {...baseProps} memberCount={1500} />)
    expect(screen.getByText('1,500 members')).toBeInTheDocument()
  })

  it('renders the source type badge', () => {
    render(<ListCard {...baseProps} />)
    expect(screen.getByText('static')).toBeInTheDocument()
  })

  it('renders the createdAt text', () => {
    render(<ListCard {...baseProps} />)
    expect(screen.getByText('Created Jan 1, 2025')).toBeInTheDocument()
  })

  it('applies blue badge styles for static source type', () => {
    render(<ListCard {...baseProps} sourceType="static" />)
    const badge = screen.getByText('static')
    expect(badge).toHaveClass('bg-blue-100', 'text-blue-700')
  })

  it('applies purple badge styles for funnel source type', () => {
    render(<ListCard {...baseProps} sourceType="funnel" />)
    const badge = screen.getByText('funnel')
    expect(badge).toHaveClass('bg-purple-100', 'text-purple-700')
  })

  it('applies green badge styles for query source type', () => {
    render(<ListCard {...baseProps} sourceType="query" />)
    const badge = screen.getByText('query')
    expect(badge).toHaveClass('bg-green-100', 'text-green-700')
  })

  it('applies gray badge for unknown source type', () => {
    render(<ListCard {...baseProps} sourceType="unknown-type" />)
    const badge = screen.getByText('unknown-type')
    expect(badge).toHaveClass('bg-gray-100', 'text-gray-700')
  })

  it('has role=button when onClick is provided', () => {
    render(<ListCard {...baseProps} onClick={jest.fn()} />)
    expect(screen.getByRole('button')).toBeInTheDocument()
  })

  it('does not have role=button when onClick is not provided', () => {
    render(<ListCard {...baseProps} />)
    expect(screen.queryByRole('button')).not.toBeInTheDocument()
  })

  it('calls onClick when clicked', () => {
    const onClick = jest.fn()
    render(<ListCard {...baseProps} onClick={onClick} />)
    fireEvent.click(screen.getByRole('button'))
    expect(onClick).toHaveBeenCalledTimes(1)
  })

  it('calls onClick when Enter key is pressed', () => {
    const onClick = jest.fn()
    render(<ListCard {...baseProps} onClick={onClick} />)
    fireEvent.keyDown(screen.getByRole('button'), { key: 'Enter' })
    expect(onClick).toHaveBeenCalledTimes(1)
  })

  it('calls onClick when Space key is pressed', () => {
    const onClick = jest.fn()
    render(<ListCard {...baseProps} onClick={onClick} />)
    fireEvent.keyDown(screen.getByRole('button'), { key: ' ' })
    expect(onClick).toHaveBeenCalledTimes(1)
  })

  it('applies custom className', () => {
    const { container } = render(<ListCard {...baseProps} className="custom-card" />)
    expect(container.firstChild).toHaveClass('custom-card')
  })
})

// ---------------------------------------------------------------------------
// CreateListDialog
// ---------------------------------------------------------------------------

describe('CreateListDialog', () => {
  const baseProps = {
    open: true,
    onClose: jest.fn(),
    onSubmit: jest.fn(),
  }

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

  it('renders nothing when open is false', () => {
    render(<CreateListDialog {...baseProps} open={false} />)
    expect(screen.queryByText('Create List')).not.toBeInTheDocument()
  })

  it('renders dialog when open is true', () => {
    render(<CreateListDialog {...baseProps} />)
    expect(screen.getByText('Create List')).toBeInTheDocument()
  })

  it('renders name, description, and source type fields', () => {
    render(<CreateListDialog {...baseProps} />)
    expect(screen.getByLabelText(/name/i)).toBeInTheDocument()
    expect(screen.getByLabelText(/description/i)).toBeInTheDocument()
    expect(screen.getByLabelText(/source type/i)).toBeInTheDocument()
  })

  it('renders default source type options', () => {
    render(<CreateListDialog {...baseProps} />)
    expect(screen.getByRole('option', { name: 'Static' })).toBeInTheDocument()
    expect(screen.getByRole('option', { name: 'Funnel' })).toBeInTheDocument()
    expect(screen.getByRole('option', { name: 'Query' })).toBeInTheDocument()
  })

  it('renders custom source types when provided', () => {
    render(
      <CreateListDialog
        {...baseProps}
        sourceTypes={[{ value: 'csv', label: 'CSV Upload' }]}
      />
    )
    expect(screen.getByRole('option', { name: 'CSV Upload' })).toBeInTheDocument()
    expect(screen.queryByRole('option', { name: 'Static' })).not.toBeInTheDocument()
  })

  it('Create button is disabled when name is empty', () => {
    render(<CreateListDialog {...baseProps} />)
    expect(screen.getByRole('button', { name: /^create$/i })).toBeDisabled()
  })

  it('Create button is enabled after entering a name', () => {
    render(<CreateListDialog {...baseProps} />)
    fireEvent.change(screen.getByLabelText(/name/i), { target: { value: 'New List' } })
    expect(screen.getByRole('button', { name: /^create$/i })).toBeEnabled()
  })

  it('calls onSubmit with correct data', () => {
    const onSubmit = jest.fn()
    render(<CreateListDialog {...baseProps} onSubmit={onSubmit} />)

    fireEvent.change(screen.getByLabelText(/name/i), { target: { value: 'Sales Leads' } })
    fireEvent.change(screen.getByLabelText(/description/i), { target: { value: 'Top prospects' } })

    fireEvent.click(screen.getByRole('button', { name: /^create$/i }))

    expect(onSubmit).toHaveBeenCalledWith({
      name: 'Sales Leads',
      description: 'Top prospects',
      sourceType: 'static',
    })
  })

  it('trims name and description on submit', () => {
    const onSubmit = jest.fn()
    render(<CreateListDialog {...baseProps} onSubmit={onSubmit} />)

    fireEvent.change(screen.getByLabelText(/name/i), { target: { value: '  Trimmed  ' } })
    fireEvent.click(screen.getByRole('button', { name: /^create$/i }))

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({ name: 'Trimmed' })
    )
  })

  it('does not call onSubmit when name is only whitespace', () => {
    const onSubmit = jest.fn()
    render(<CreateListDialog {...baseProps} onSubmit={onSubmit} />)

    fireEvent.change(screen.getByLabelText(/name/i), { target: { value: '   ' } })
    fireEvent.submit(screen.getByLabelText(/name/i).closest('form')!)

    expect(onSubmit).not.toHaveBeenCalled()
  })

  it('calls onClose when Cancel is clicked', () => {
    const onClose = jest.fn()
    render(<CreateListDialog {...baseProps} onClose={onClose} />)
    fireEvent.click(screen.getByRole('button', { name: /cancel/i }))
    expect(onClose).toHaveBeenCalledTimes(1)
  })

  it('calls onClose when backdrop is clicked', () => {
    const onClose = jest.fn()
    const { container } = render(<CreateListDialog {...baseProps} onClose={onClose} />)
    const backdrop = container.querySelector('[aria-hidden="true"]')
    fireEvent.click(backdrop!)
    expect(onClose).toHaveBeenCalledTimes(1)
  })

  it('does not call onClose when backdrop clicked during submit', () => {
    const onClose = jest.fn()
    const { container } = render(
      <CreateListDialog {...baseProps} onClose={onClose} isSubmitting />
    )
    const backdrop = container.querySelector('[aria-hidden="true"]')
    fireEvent.click(backdrop!)
    expect(onClose).not.toHaveBeenCalled()
  })

  it('shows Creating... and disables fields when isSubmitting', () => {
    render(<CreateListDialog {...baseProps} isSubmitting />)
    expect(screen.getByText('Creating...')).toBeInTheDocument()
    expect(screen.getByLabelText(/name/i)).toBeDisabled()
    expect(screen.getByLabelText(/description/i)).toBeDisabled()
  })

  it('resets fields when dialog reopens', () => {
    const { rerender } = render(<CreateListDialog {...baseProps} open={false} />)
    rerender(<CreateListDialog {...baseProps} open />)
    expect(screen.getByLabelText(/name/i)).toHaveValue('')
    expect(screen.getByLabelText(/description/i)).toHaveValue('')
  })

  it('submits the selected source type', () => {
    const onSubmit = jest.fn()
    render(<CreateListDialog {...baseProps} onSubmit={onSubmit} />)

    fireEvent.change(screen.getByLabelText(/name/i), { target: { value: 'My List' } })
    fireEvent.change(screen.getByLabelText(/source type/i), { target: { value: 'funnel' } })
    fireEvent.click(screen.getByRole('button', { name: /^create$/i }))

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({ sourceType: 'funnel' })
    )
  })
})
