"use client";

import { useQuery } from "@tanstack/react-query";
import {
  ArrowLeft,
  Brain,
  ChevronRight,
  GitBranch,
  Gavel,
  Radio,
  Shuffle,
  Terminal,
  Zap,
} from "lucide-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { useState } from "react";
import { PageHeader } from "@/components/page-header";
import { StatusPill } from "@/components/status";
import { Badge, Mono, Panel } from "@/components/ui";
import { api } from "@/lib/api";
import type { Step } from "@/lib/types";
import { useRunStream } from "@/lib/use-run-stream";
import { cn } from "@/lib/utils";

const STEP_ICON: Record<string, typeof Brain> = {
  agent_reason: Brain,
  tool_call: Terminal,
  condition: GitBranch,
  transform: Shuffle,
  approval: Gavel,
  trigger: Zap,
};

function JsonBlock({ value }: { value: unknown }) {
  if (value === null || value === undefined) return null;
  const text = typeof value === "string" ? value : JSON.stringify(value, null, 2);
  if (!text || text === "{}" || text === '""') return null;
  return (
    <pre className="mt-2 max-h-64 overflow-auto rounded-lg border border-line bg-ink/60 p-3 font-mono text-[12px] leading-relaxed text-muted">
      {text}
    </pre>
  );
}

function StepRow({ step, last }: { step: Step; last: boolean }) {
  const [open, setOpen] = useState(false);
  const Icon = STEP_ICON[step.type] ?? Terminal;
  const bad = ["error", "denied", "rejected"].includes(step.status);
  return (
    <div className="relative pl-10">
      {!last && <span className="absolute left-[15px] top-8 bottom-0 w-px bg-line" />}
      <span
        className={cn(
          "absolute left-0 top-1.5 flex h-8 w-8 items-center justify-center rounded-full border bg-surface",
          bad ? "border-danger/40 text-danger" : "border-line text-muted",
          step.status === "waiting_approval" && "border-warning/50 text-warning"
        )}
      >
        <Icon className="h-4 w-4" />
      </span>
      <button
        onClick={() => setOpen((v) => !v)}
        className="flex w-full items-center gap-3 py-2 text-left"
      >
        <ChevronRight
          className={cn("h-4 w-4 text-faint transition-transform", open && "rotate-90")}
        />
        <span className="font-mono text-[13px] text-fg">{step.name}</span>
        <Badge>{step.type}</Badge>
        {step.tokens > 0 && <Mono className="text-faint">{step.tokens} tok</Mono>}
        <div className="flex-1" />
        {bad ? (
          <StatusPill status="error" />
        ) : (
          <span className="font-mono text-[11px] text-faint">{step.status}</span>
        )}
      </button>
      {open && (
        <div className="pb-4 pr-2">
          {step.error && (
            <div className="mt-1 rounded-lg border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">
              {step.error}
            </div>
          )}
          {Object.keys(step.input ?? {}).length > 0 && (
            <>
              <div className="mt-2 eyebrow">Input</div>
              <JsonBlock value={step.input} />
            </>
          )}
          {Object.keys(step.output ?? {}).length > 0 && (
            <>
              <div className="mt-2 eyebrow">Output</div>
              <JsonBlock value={step.output} />
            </>
          )}
        </div>
      )}
    </div>
  );
}

export default function RunViewerPage() {
  const { id } = useParams<{ id: string }>();
  const { steps, status: liveStatus, connected } = useRunStream(id);
  const run = useQuery({
    queryKey: ["run", id],
    queryFn: () => api.getRun(id),
    refetchInterval: (q) =>
      q.state.data && ["succeeded", "failed", "cancelled"].includes(q.state.data.status)
        ? false
        : 2000,
  });

  const status = run.data?.status ?? liveStatus ?? "pending";
  const output = run.data?.output?.output;

  return (
    <div>
      <Link
        href="/runs"
        className="mb-4 inline-flex items-center gap-1.5 text-sm text-muted hover:text-fg"
      >
        <ArrowLeft className="h-4 w-4" /> Runs
      </Link>
      <PageHeader
        eyebrow={
          <span className="flex items-center gap-1.5">
            Run · <Mono>{id.slice(0, 8)}</Mono>
          </span>
        }
        title={run.data?.workflow_id ? "Workflow run" : "Agent run"}
        actions={<StatusPill status={status} />}
      />

      <div className="mb-6 grid grid-cols-2 gap-4 sm:grid-cols-4">
        {[
          { label: "Steps", value: run.data?.total_steps ?? steps.length },
          { label: "Tokens", value: (run.data?.total_tokens ?? 0).toLocaleString() },
          { label: "Started", value: run.data?.started_at ? "yes" : "no" },
          {
            label: "Stream",
            value: connected ? (
              <span className="flex items-center gap-1.5 text-info">
                <Radio className="h-4 w-4 animate-pulse-soft" /> live
              </span>
            ) : (
              "idle"
            ),
          },
        ].map((s) => (
          <Panel key={s.label} className="py-4">
            <div className="eyebrow">{s.label}</div>
            <div className="mt-1.5 font-display text-2xl font-bold text-fg">{s.value}</div>
          </Panel>
        ))}
      </div>

      {status === "waiting_approval" && (
        <Panel className="mb-6 border-warning/30 bg-warning/5">
          <div className="flex items-center gap-3">
            <Gavel className="h-5 w-5 text-warning" />
            <div className="flex-1">
              <div className="font-semibold text-fg">This run is paused for approval</div>
              <div className="text-sm text-muted">A sensitive action needs a human decision.</div>
            </div>
            <Link href="/approvals" className="text-sm font-medium text-accent hover:underline">
              Open inbox →
            </Link>
          </div>
        </Panel>
      )}

      {run.data?.error && (
        <Panel className="mb-6 border-danger/30 bg-danger/5">
          <div className="eyebrow text-danger">Error</div>
          <p className="mt-1 text-sm text-danger">{run.data.error}</p>
        </Panel>
      )}

      {output != null && (
        <Panel className="mb-6 border-success/20">
          <div className="eyebrow text-success">Final output</div>
          <JsonBlock value={output} />
        </Panel>
      )}

      <div className="mb-3 eyebrow">Timeline · {steps.length} steps</div>
      <Panel>
        {steps.length === 0 ? (
          <div className="py-8 text-center text-sm text-muted">Waiting for the first step…</div>
        ) : (
          <div>
            {steps.map((step, i) => (
              <StepRow key={step.id} step={step} last={i === steps.length - 1} />
            ))}
          </div>
        )}
      </Panel>
    </div>
  );
}
