import { fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { CI_REPO_DEFERRED_SUMMARY, CI_REPO_GAP_SUMMARY, CI_REPO_SUMMARY } from './fixtures/ci-trains'
import { RepoCiTile, type RepoCiSummary } from './RepoCiTile'

vi.mock('./DeckTooltip', () => ({
  useDeckTooltip: (tipb: string, tips?: string) => ({
    'data-tipb': tipb,
    'data-tips': tips,
  }),
}))

describe('RepoCiTile', () => {
  it('renders real metrics and scopes to its repository', () => {
    const onScope = vi.fn()
    render(<RepoCiTile summary={CI_REPO_SUMMARY} selected onScope={onScope} />)

    const tile = screen.getByRole('button', { name: /alexcodeplace\/multideal/ })
    expect(tile).toHaveAttribute('aria-pressed', 'true')
    expect(screen.getByText('7')).toBeInTheDocument()
    expect(screen.getByText('3')).toBeInTheDocument()
    expect(screen.getByText('5')).toBeInTheDocument()
    expect(screen.getByText('45m')).toHaveClass('text-danger')

    fireEvent.click(tile)
    expect(onScope).toHaveBeenCalledWith('alexcodeplace/multideal')
  })

  it('does not mark the 30-minute boundary as act-red', () => {
    render(
      <RepoCiTile
        summary={{ ...CI_REPO_SUMMARY, oldestQueuedAgeH: 0.5 }}
        selected={false}
        onScope={() => undefined}
      />,
    )

    expect(screen.getByText('30m')).not.toHaveClass('text-danger')
  })

  it.each([
    ['prsComplete', 'Open PR list truncated'],
    ['queueComplete', 'Actions queue unavailable'],
    ['refsComplete', 'Train branch list truncated'],
    ['trainRunsComplete', 'Train run history truncated'],
  ] as const)('renders the %s gap independently', (flag, label) => {
    const summary: RepoCiSummary = {
      ...CI_REPO_SUMMARY,
      [flag]: false,
      ...(flag === 'trainRunsComplete'
        ? { refsComplete: true, prsComplete: true, trainsComplete: false }
        : flag === 'refsComplete'
          ? { trainsComplete: false }
          : {}),
    }
    render(<RepoCiTile summary={summary} selected={false} onScope={() => undefined} />)
    expect(screen.getByText(label)).toBeInTheDocument()
  })

  it('suppresses operator warnings when poll rotation serves cached data', () => {
    render(<RepoCiTile summary={CI_REPO_DEFERRED_SUMMARY} selected={false} onScope={() => undefined} />)
    expect(screen.queryByText('Refresh deferred this poll cycle')).not.toBeInTheDocument()
    expect(screen.queryByText('Train branch list truncated')).not.toBeInTheDocument()
  })

  it('preserves simultaneous completeness gaps with actionable copy', () => {
    render(<RepoCiTile summary={CI_REPO_GAP_SUMMARY} selected={false} onScope={() => undefined} />)

    for (const label of [
      'Open PR list truncated',
      'Actions queue unavailable',
      'Train branch list truncated',
      'Poll budget exhausted',
      'Train job details truncated',
    ]) {
      expect(screen.getAllByText(label).length).toBeGreaterThan(0)
    }
  })

  it('renders labeled gaps for unknown metrics instead of zeroes', () => {
    render(<RepoCiTile summary={CI_REPO_GAP_SUMMARY} selected={false} onScope={() => undefined} />)

    expect(screen.getByText('PR queue unavailable')).toBeInTheDocument()
    expect(screen.getByText('Lands today unavailable')).toBeInTheDocument()
    expect(screen.getByText('Oldest queued age unavailable')).toBeInTheDocument()
    expect(screen.queryByText('0')).not.toBeInTheDocument()
  })
})
