/** @vitest-environment jsdom */
import { fireEvent, render, screen } from '@testing-library/react'
import '@testing-library/jest-dom/vitest'
import { describe, expect, it, vi } from 'vitest'
import { AttemptTimeline } from './AttemptTimeline'
import type { AttemptRecord } from './attempt-record'

const NOW_MS = Date.parse('2026-08-04T03:00:00.000Z')

function attempt(overrides: Partial<AttemptRecord> = {}): AttemptRecord {
  return {
    attemptId: 'attempt-done',
    task: 't1',
    phase: 'coder',
    seat: 'coder',
    model: 'gpt-test',
    wrapper: '/tmp/agent.sh',
    timeoutSecs: 120,
    promptPath: '/run/attempts/attempt-done.prompt.md',
    promptSha: 'a'.repeat(64),
    causalInput: 't1:initial',
    valid: true,
    replyPath: '/run/attempts/attempt-done.reply.json',
    usage: { inputTokens: 11, outputTokens: 7, model: 'gpt-test' },
    liveness: null,
    activity: {
      toolCalls: 6,
      filesTouched: ['src/app.js'],
      repeatedCommands: [['bash', 'npm test']],
      failureFingerprint: 'coder:coder:gpt-test',
    },
    ...overrides,
  }
}

describe('AttemptTimeline', () => {
  it('renders one entry per attempt in journal order', () => {
    const attempts = [
      attempt({ attemptId: 'attempt-first' }),
      attempt({ attemptId: 'attempt-second', model: 'gpt-alt' }),
      attempt({ attemptId: 'attempt-third', model: 'gpt-review' }),
    ]

    render(<AttemptTimeline attempts={attempts} nowMs={NOW_MS} />)

    const entries = screen.getAllByRole('button')
    expect(entries).toHaveLength(3)
    expect(entries[0]).toHaveAttribute('data-attempt-index', '0')
    expect(entries[1]).toHaveAttribute('data-attempt-index', '1')
    expect(entries[2]).toHaveAttribute('data-attempt-index', '2')
    expect(screen.getByTestId('attempt-entry-attempt-first')).toBeInTheDocument()
    expect(screen.getByTestId('attempt-entry-attempt-second')).toBeInTheDocument()
    expect(screen.getByTestId('attempt-entry-attempt-third')).toBeInTheDocument()
  })

  it('visually distinguishes stalled attempts from healthy in-progress ones', () => {
    const healthy = attempt({
      attemptId: 'attempt-healthy',
      timeoutSecs: 120,
      liveness: {
        elapsedSecs: 30,
        lastActivity: 'thinking',
        lastSignalAt: '2026-08-04T02:59:30.000Z',
      },
    })
    const stalled = attempt({
      attemptId: 'attempt-stalled',
      timeoutSecs: 60,
      liveness: {
        elapsedSecs: 200,
        lastActivity: 'tool_call:bash',
        lastSignalAt: '2026-08-04T02:50:00.000Z',
      },
    })

    render(<AttemptTimeline attempts={[healthy, stalled]} nowMs={NOW_MS} />)

    expect(screen.getByTestId('attempt-entry-attempt-healthy')).toHaveAttribute('data-alarmed', 'false')
    expect(screen.getByTestId('attempt-entry-attempt-stalled')).toHaveAttribute('data-alarmed', 'true')
    expect(screen.getByTestId('attempt-stalled-attempt-stalled')).toHaveTextContent('stale')
    expect(screen.queryByTestId('attempt-stalled-attempt-healthy')).not.toBeInTheDocument()
  })

  it('forwards selection clicks', () => {
    const onAttemptClick = vi.fn()
    render(
      <AttemptTimeline
        attempts={[attempt({ attemptId: 'attempt-pick' })]}
        nowMs={NOW_MS}
        onAttemptClick={onAttemptClick}
      />,
    )

    fireEvent.click(screen.getByTestId('attempt-entry-attempt-pick'))
    expect(onAttemptClick).toHaveBeenCalledWith('attempt-pick')
  })
})
