import { render, screen } from '@testing-library/react'
import type { ReactNode } from 'react'
import { describe, expect, it, vi } from 'vitest'
import type { TranscriptStep } from './factory-run-view-helpers'
import { FactoryStepDrawer } from './FactoryStepDrawer'

vi.mock('@astryxdesign/core/CodeBlock', () => ({ CodeBlock: ({ code }: { code: string }) => <pre>{code}</pre> }))
vi.mock('@astryxdesign/core/Collapsible', () => ({ Collapsible: ({ trigger, children }: { trigger: string; children: ReactNode }) => <section><button type="button">{trigger}</button>{children}</section> }))
vi.mock('@astryxdesign/core/Markdown', () => ({ Markdown: ({ children }: { children: ReactNode }) => <div>{children}</div> }))
vi.mock('@astryxdesign/lab', () => ({ Drawer: ({ children }: { children: ReactNode }) => <div>{children}</div>, LogStream: ({ label, entries }: { label: string; entries: Array<{ message: string }> }) => <section aria-label={label}>{entries.map(entry => <pre key={entry.message}>{entry.message}</pre>)}</section> }))
const DIFF_ONE = `diff --git a/src/a.ts b/src/a.ts
--- a/src/a.ts
+++ b/src/a.ts
@@ -1,1 +1,1 @@
-const a = 1
+const a = 2
diff --git a/src/b.ts b/src/b.ts
--- /dev/null
+++ b/src/b.ts
@@ -0,0 +1,1 @@
+const b = 1`

const DIFF_TWO = `diff --git a/src/c.ts b/src/c.ts
--- a/src/c.ts
+++ b/src/c.ts
@@ -1,1 +1,1 @@
-const c = 1
+const c = 2`

const step: TranscriptStep = {
  type: 'attempt', id: 'attempt-55', summary: '', isStreaming: false, diffs: [{ phaseId: 'phase-55', attempt: 1, files: [{ path: 'src/a.ts', status: 'modified', insertions: 1, deletions: 1 }, { path: 'src/b.ts', status: 'added', insertions: 2, deletions: 0 }], insertions: 3, deletions: 1, diffText: DIFF_ONE, truncated: false, createdAt: null }, { phaseId: 'phase-55', attempt: 2, files: [{ path: 'src/c.ts', status: 'modified', insertions: 0, deletions: 0 }], insertions: 0, deletions: 0, diffText: DIFF_TWO, truncated: false, createdAt: null }],
  phase: { phaseId: 'phase-55', seq: 1, name: 'build', kind: 'agent', owner: 'owner', description: null, status: null, attempt: 1, retries: null, error: null, startedAt: '2026-08-09T10:00:00.000Z', endedAt: '2026-08-09T10:03:00.000Z', durationMs: 180000, tokens: 0, spend: 0 },
  attempt: { attemptId: 'attempt-55', phaseId: 'phase-55', agent: 'agent', sessionId: null, command: 'pi -p build', systemPrompt: 'system', userPrompt: 'user', returncode: 7, signal: null, timedOut: false, tokens: null, error: null, stderrPath: null, host: null, account: null, model: null, startedAt: '2026-08-09T10:01:00.000Z', lastOutputAt: null, endedAt: '2026-08-09T10:02:00.000Z', durationMs: 60000, idleMs: null, usage: null, providerFailure: null, toolCalls: [{ toolCallId: 'read-1', seq: 1, toolName: 'read', args: { path: 'src/a.ts' }, startedAt: null, endedAt: null, durationMs: null, ok: true, resultExcerpt: 'source excerpt' }] },
}

describe('FactoryStepDrawer', () => {
  it('renders phase identity, independently addressed prompts, collapsed read target, all diffs, and terminal gate evidence', () => {
    render(<FactoryStepDrawer step={step} gates={[{ adwId: 'adw-55', phaseId: 'phase-55', attempt: 1, gate: 'quality', passed: false, checks: [{ command: 'pnpm test', returncode: 7, ok: false }], violations: ['test output tail'] }]} runAttempts={[step.attempt]} onClose={vi.fn()} />)
    expect(screen.getByText('2026-08-09T10:01:00.000Z')).toBeInTheDocument()
    expect(screen.getByText('2026-08-09T10:02:00.000Z')).toBeInTheDocument()
    expect(screen.getByText('Task instructions')).toBeInTheDocument()
    expect(screen.getByText('The stable task or inherited context could not be separated from this message.')).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'System message' })).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'User message' })).toBeInTheDocument()
    expect(screen.getByText('Attachment accounting was not recorded for this attempt.')).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'read · src/a.ts' })).toBeInTheDocument()
    expect(screen.getByText('const a = 2')).toBeInTheDocument()
    expect(screen.getByText('const b = 1')).toBeInTheDocument()
    expect(screen.getByText('const c = 2')).toBeInTheDocument()
    expect(screen.getAllByText('pnpm test')).not.toHaveLength(0)
    expect(screen.getByText('Return code')).toBeInTheDocument()
    expect(screen.getByText('Command')).toBeInTheDocument()
    expect(screen.getByText('pi -p build')).toBeInTheDocument()
    expect(screen.getByText('7')).toBeInTheDocument()
    expect(screen.getByRole('region', { name: 'Failure output' })).toHaveTextContent('test output tail')
  })

  it('opens a phase-only artifact in the drawer', () => {
    const phaseOnly: TranscriptStep = { type: 'phase', id: 'phase-55', phase: step.phase, attempts: [], diffs: step.diffs, summary: '', isStreaming: false }
    render(<FactoryStepDrawer step={phaseOnly} gates={[]} runAttempts={[]} onClose={vi.fn()} />)
    expect(screen.getByText('2026-08-09T10:00:00.000Z')).toBeInTheDocument()
    expect(screen.getByText('2026-08-09T10:03:00.000Z')).toBeInTheDocument()
  })
})
