import { useEffect, useRef, useState } from 'react'
import { AlertTriangle, BrainCircuit, Check, Inbox, Loader2, Wrench } from 'lucide-react'
import { api } from '@/lib/api'

/** The live run record as returned by GET /api/assembler/runs/{id}. */
interface Run {
  id: string
  status: 'Queued' | 'Running' | 'Completed' | 'Failed' | string
  actionType: string | null
  actionRisk: string | null
  output: string | null
  error: string | null
  resultJson: string | null
  latencyMs: number | null
  createdAtUtc: string
  completedAtUtc: string | null
}

interface ToolCall {
  name?: string
  tool?: string
  server?: string
  ok?: boolean
}

const TERMINAL = new Set(['Completed', 'Failed'])

/** Pulls the tool-call list out of the run's result JSON, if the agent used any MCP tools. */
function readToolCalls(run: Run | null): ToolCall[] {
  if (!run?.resultJson) return []
  try {
    const parsed = JSON.parse(run.resultJson) as { toolCalls?: ToolCall[] }
    return Array.isArray(parsed.toolCalls) ? parsed.toolCalls : []
  } catch {
    return []
  }
}

/**
 * Watches one agent run live: polls the run until it reaches a terminal state and renders a
 * step-by-step timeline (Queued → Thinking → Done) with elapsed time, the action the agent took,
 * its risk tag, any tool calls, and where the result landed.
 */
export function RunProgress({
  runId,
  onSettled,
}: {
  runId: string
  /** Fired once when the run reaches Completed/Failed — lets the parent refresh the board + badge. */
  onSettled?: (run: Run) => void
}) {
  const [run, setRun] = useState<Run | null>(null)
  const [elapsed, setElapsed] = useState(0)
  const settledRef = useRef(false)
  const onSettledRef = useRef(onSettled)
  onSettledRef.current = onSettled

  useEffect(() => {
    let active = true
    let pollTimer = 0
    const start = Date.now()

    const tick = window.setInterval(() => {
      if (active && !settledRef.current) setElapsed(Math.round((Date.now() - start) / 1000))
    }, 1000)

    const poll = async () => {
      try {
        const r = await api.get<Run>(`/api/assembler/runs/${runId}`)
        if (!active) return
        setRun(r)
        if (TERMINAL.has(r.status)) {
          settledRef.current = true
          onSettledRef.current?.(r)
          return
        }
      } catch {
        /* transient — keep polling */
      }
      if (active) pollTimer = window.setTimeout(poll, 1200)
    }
    void poll()

    return () => {
      active = false
      window.clearTimeout(pollTimer)
      window.clearInterval(tick)
    }
  }, [runId])

  const status = run?.status ?? 'Queued'
  const failed = status === 'Failed'
  const done = status === 'Completed'
  const running = status === 'Running'
  const tools = readToolCalls(run)
  const seconds = run?.latencyMs != null ? (run.latencyMs / 1000).toFixed(1) : elapsed.toString()

  return (
    <div className="flex flex-col gap-3 rounded-xl border bg-card/60 p-4 backdrop-blur-sm">
      <div className="flex items-center justify-between">
        <span className="text-sm font-semibold">Agent at work</span>
        <span className="text-xs tabular-nums text-muted-foreground">{seconds}s</span>
      </div>

      <ol className="flex flex-col gap-2.5">
        <Step
          state={status === 'Queued' ? 'active' : 'done'}
          icon={Inbox}
          title="Queued"
          detail="Task accepted — waiting for a worker."
        />
        <Step
          state={failed && !done ? (run?.output ? 'done' : 'error') : running ? 'active' : status === 'Queued' ? 'pending' : 'done'}
          icon={BrainCircuit}
          title="Thinking"
          detail="Assembling the prompt and calling the model."
        />
        {tools.length > 0 && (
          <Step
            state="done"
            icon={Wrench}
            title={`Used ${tools.length} tool${tools.length === 1 ? '' : 's'}`}
            detail={tools.map((t) => t.name ?? t.tool).filter(Boolean).join(', ')}
          />
        )}
        <Step
          state={failed ? 'error' : done ? 'done' : 'pending'}
          icon={done ? Check : AlertTriangle}
          title={failed ? 'Failed' : 'Delivered'}
          detail={
            failed
              ? run?.error ?? 'The run failed.'
              : done
                ? `${run?.actionType ?? 'Result'} produced — sent to the review inbox.`
                : 'Result will land in the review inbox.'
          }
        />
      </ol>

      {done && run?.actionType && (
        <div className="flex flex-wrap items-center gap-2 border-t pt-3">
          <span className="rounded-md bg-muted px-2 py-0.5 text-xs font-medium">{run.actionType}</span>
          {run.actionRisk && (
            <span className="rounded-md bg-amber-500/15 px-2 py-0.5 text-xs font-medium text-amber-700 dark:text-amber-400">
              {run.actionRisk} risk
            </span>
          )}
        </div>
      )}

      {done && run?.output && (
        <details className="text-xs">
          <summary className="cursor-pointer text-muted-foreground hover:text-foreground">Show output</summary>
          <div className="mt-2 max-h-48 overflow-auto whitespace-pre-wrap rounded-lg bg-muted p-3 leading-relaxed">
            {run.output}
          </div>
        </details>
      )}
    </div>
  )
}

type StepState = 'pending' | 'active' | 'done' | 'error'

function Step({
  state,
  icon: Icon,
  title,
  detail,
}: {
  state: StepState
  icon: typeof Check
  title: string
  detail?: string
}) {
  const ring =
    state === 'done'
      ? 'border-approved bg-approved/15 text-approved'
      : state === 'active'
        ? 'border-primary bg-primary/15 text-primary'
        : state === 'error'
          ? 'border-destructive bg-destructive/15 text-destructive'
          : 'border-border bg-muted/40 text-muted-foreground'

  return (
    <li className="flex items-start gap-3">
      <span className={`mt-0.5 grid size-7 shrink-0 place-items-center rounded-full border ${ring}`}>
        {state === 'active' ? <Loader2 className="size-3.5 animate-spin" /> : <Icon className="size-3.5" />}
      </span>
      <div className="min-w-0">
        <p className={`text-sm font-medium ${state === 'pending' ? 'text-muted-foreground' : ''}`}>{title}</p>
        {detail && <p className="text-xs text-muted-foreground">{detail}</p>}
      </div>
    </li>
  )
}
