import { mkdirSync, rmSync, writeFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'

const root = resolve(fileURLToPath(new URL('../../../..', import.meta.url)))
const runtime = join(root, 'apps/web/browser-proof/agent-activity-story/runtime')
rmSync(runtime, { recursive: true, force: true })
mkdirSync(join(runtime, 'config'), { recursive: true })
mkdirSync(join(runtime, 'home/.harness'), { recursive: true })
mkdirSync(join(runtime, 'state'), { recursive: true })
const runId = 'story-proof-run'
const taskId = 'story-task'
let phaseId = ''
let attemptId = ''
const now = '2026-08-14T05:00:00.000Z'

const runs = { runs: [{ runId, seq: 1, title: 'Agent activity browser proof', status: 'succeeded', degradedReason: '', state: 'done', currentTask: null, owner: 'proof-runner', tasksTotal: 1, tasksCompleted: 1, pendingDecisions: 0, updatedAt: '2026-08-14T05:01:00.000Z', startedAt: now, repoRoot: root, dag: { nodes: [{ id: taskId, kind: 'task', label: taskId, status: 'succeeded', meta: { wave: 1, state: 'done', deps: [], attempt: 1, seat: 'coder', branch: 'proof/story' } }], edges: [] } }] }
const timeline = { runId, tiles: [], attribution: [], runs: [{ index: 0, startTs: now, endTs: '2026-08-14T05:01:00.000Z', durationMs: 60000, outcome: 'done', landed: 0, quarantined: 0, skipped: 0, gate0Fails: 0, fixerAttempts: 0 }], segments: [{ t0: Date.parse(now), durMs: 60000, cat: 'llm-implement', taskId, agentId: 'story-agent' }] }
const event = (id: string, kind: string, second: number, payload: Record<string, unknown>) => ({ id, seq: second, source: 'proof-recorder', kind, ts: `2026-08-14T05:00:${String(second).padStart(2, '0')}.000Z`, taskId, attemptId, phaseId, payload })
const events = () => [
  event('start', 'attempt.started', 1, { phase: phaseId, summary: 'Started the task.' }),
  event('read-1', 'tool.read', 2, { path: 'src/story.ts', summary: 'Read the existing story.' }),
  event('read-2', 'tool.read', 3, { path: 'src/types.ts', summary: 'Read related types.' }),
  event('edit-1', 'tool.edit', 4, { path: 'src/story.ts', summary: 'Updated the activity story.' }),
  event('test-1', 'gate.result', 5, { summary: 'Focused tests passed.' }),
  event('warn-1', 'warning', 6, { summary: 'One coverage warning was recorded.' }),
  event('done', 'attempt.completed', 7, { phase: phaseId, summary: 'Completed the task.' }),
]

const harness = Bun.serve({ port: 4981, hostname: '127.0.0.1', fetch(req) {
  const path = new URL(req.url).pathname
  if (path.startsWith('/runs')) console.log('fixture harness request', path)
  if (path === '/health') return Response.json({ version: 'proof-v1' })
  if (path === '/runs') return Response.json(runs)
  if (path === '/queue') return Response.json({ queue: [] })
  if (path === `/runs/${runId}/timeline`) return Response.json(timeline)
  if (path === `/runs/${runId}/decisions`) return Response.json({ decisions: [] })
  if (path === `/runs/${runId}/attempts`) return Response.json({ attempts: [] })
  if (path === `/runs/${runId}/events`) return Response.json({ events: events(), nextSince: 'proof:7', hasMore: false, capabilities: { attemptCorrelation: true } })
  return Response.json({ error: 'not-found', path }, { status: 404 })
} })
writeFileSync(join(runtime, 'home/.harness/control-api.port'), '4981')
writeFileSync(join(runtime, 'home/.harness/token'), 'proof-token')

const dbPath = join(runtime, 'factory.sqlite')
const diff = `diff --git a/src/story.ts b/src/story.ts\nindex 1111111..2222222 100644\n--- a/src/story.ts\n+++ b/src/story.ts\n@@ -1,2 +1,2 @@\n-export const story = 'technical'\n+export const story = 'human'\n export const diagnostics = true\n`
const tracerFixture = `
import json
from pathlib import Path
from adw_modules.data_types import ConfigDefaults, ObservabilityConfig, PhaseParams, SSSFConfig
from adw_modules.runner import Run
from adw_modules.tracer import Tracer

tracer = Tracer(Path(${JSON.stringify(dbPath)}), Path(${JSON.stringify(join(runtime, 'factory-events.jsonl'))}))
tracer.session_start(${JSON.stringify(runId)}, "proof-runner", "Agent activity browser proof", repo=Path(${JSON.stringify(root)}), slug_hint="story-proof")
tracer.session_request(${JSON.stringify(runId)}, "Prove agent activity story")
cfg = SSSFConfig(
    defaults=ConfigDefaults(data_dir=${JSON.stringify(join(runtime, 'factory-data'))}),
    observability=ObservabilityConfig(db=${JSON.stringify(dbPath)}),
)
run = Run(cfg, ${JSON.stringify(runId)}, tracer, "proof-runner")
with run.phase(PhaseParams(
    name="implement-story", task_id=${JSON.stringify(taskId)}, kind="agent", owner="story-agent",
    description="Update the human activity story for the recorded task.",
)) as handle:
    phase = handle.phase
    phase.attempt = 1
    attempt_id = tracer.agent_attempt_start(
        ${JSON.stringify(runId)}, phase.phase_id, "story-agent", "story-session", "proof-agent",
        host="proof-host", account="proof-account", model="proof-model",
    )
    assert attempt_id
    tracer.phase_diff_row(phase, {
        "files": [{"path": "src/story.ts", "status": "M", "insertions": 1, "deletions": 1}],
        "insertions": 1, "deletions": 1, "diff_text": ${JSON.stringify(diff)}, "truncated": False,
    })
tracer.session_finish(${JSON.stringify(runId)}, ok=True)
tracer.conn.close()
print(json.dumps({"attemptId": attempt_id, "phaseId": phase.phase_id}))
`
const tracerResult = Bun.spawnSync(['uv', 'run', '--frozen', 'python', '-c', tracerFixture], {
  cwd: join(root, 'modules/harness/factory'),
  env: { ...process.env, PYTHONPATH: join(root, 'modules/harness/factory') },
  stdout: 'pipe',
  stderr: 'pipe',
})
if (tracerResult.exitCode !== 0) {
  throw new Error(`real tracer fixture failed: ${tracerResult.stderr.toString()}`)
}
const tracerOutput = tracerResult.stdout.toString().trim().split('\n').at(-1)
const tracerIdentity = JSON.parse(tracerOutput ?? '{}') as { attemptId?: string; phaseId?: string }
attemptId = tracerIdentity.attemptId ?? ''
phaseId = tracerIdentity.phaseId ?? ''
if (!attemptId.startsWith('att_') || !phaseId || phaseId === taskId || phaseId === 'implement-story') {
  throw new Error(`real Run.phase fixture returned invalid identity: ${JSON.stringify(tracerIdentity)}`)
}
writeFileSync(join(runtime, 'config/config.toml'), `bindHost = "127.0.0.1"\nport = 4980\n[adapters.harness]\nenabled = true\nintervalMs = 100\nbaseUrl = "http://127.0.0.1:4981"\n[adapters.factory]\nenabled = true\nintervalMs = 100\ndbPath = "${dbPath}"\n`)
writeFileSync(join(runtime, 'config/token'), 'collector-proof-token')
const env = { ...process.env, HOME: join(runtime, 'home'), OVERDECK_CONFIG_DIR: join(runtime, 'config'), OVERDECK_STATE_DIR: join(runtime, 'state'), COLLECTOR_URL: 'http://127.0.0.1:4980', PORT: '4331' }
const collector = Bun.spawn(['bun', 'run', 'collector/src/index.ts'], { cwd: root, env, stdout: 'inherit', stderr: 'inherit' })
let lastState: unknown = null
for (let attempt = 0; attempt < 100; attempt += 1) {
  try {
    const response = await fetch('http://127.0.0.1:4980/state', { headers: { authorization: 'Bearer collector-proof-token' } })
    if (response.ok) {
      const state = await response.json() as { panels?: Array<{ id?: string; data?: { runs?: Array<{ runId?: string }> } }> }
      lastState = state
      if (state.panels?.some(panel => panel.id === 'plans' && panel.data?.runs?.some(run => run.runId === runId))) break
    }
  } catch {}
  if (attempt === 99) {
    const state = lastState as { panels?: Array<{ id?: string; data?: unknown }>; adapters?: unknown[] }
    throw new Error(`collector did not publish fixture run: ${JSON.stringify({ panels: state?.panels?.filter(panel => panel.id === 'plans' || panel.id === 'factory-runs'), adapters: state?.adapters })}`)
  }
  await Bun.sleep(100)
}
const web = Bun.spawn(['pnpm', '--filter', 'web', 'exec', 'astro', 'dev', '--host', '127.0.0.1', '--port', '4331'], { cwd: root, env, stdout: 'inherit', stderr: 'inherit' })
const stop = () => { collector.kill(); web.kill(); harness.stop(); process.exit(0) }
process.on('SIGTERM', stop); process.on('SIGINT', stop)
await web.exited
stop()
