"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Background, BackgroundVariant, Controls, Panel, ReactFlow, ReactFlowProvider,
  useReactFlow, type Node,
} from "@xyflow/react";
import {
  AlertTriangle, CheckCircle2, Focus, GitBranch, Layers3, LoaderCircle,
  RefreshCw, Search, Sparkles, Workflow, X,
} from "lucide-react";
import { FlowCard } from "@/components/FlowCard";
import { Inspector } from "@/components/Inspector";
import { PhaseFrameNode } from "@/components/PhaseFrameNode";
import { fetchGraph, fetchRuns } from "@/lib/api";
import { buildCanvas, PHASE_LABELS, type CanvasData } from "@/lib/flow";
import type { FlowNodeRecord, Phase, RunGraph, RunSummary } from "@/lib/types";

const nodeTypes = { flowCard: FlowCard, phaseFrame: PhaseFrameNode };
const ALL_PHASES: Phase[] = ["phase-1", "phase-2", "phase-3", "delivery"];

function LoadingState() {
  return <main className="centerState"><LoaderCircle className="spin" /><h1>正在装载 fake mission graph</h1><p>连接本地 FastAPI :8788</p></main>;
}

function ErrorState({ message, retry }: { message: string; retry: () => void }) {
  return <main className="centerState error"><AlertTriangle /><h1>可视化后端未就绪</h1><p>{message}</p><button onClick={retry}><RefreshCw size={16} />重新连接</button></main>;
}

function Canvas({ graph, selected, onSelect }: {
  graph: RunGraph;
  selected: FlowNodeRecord | null;
  onSelect: (node: FlowNodeRecord | null) => void;
}) {
  const [query, setQuery] = useState("");
  const [phases, setPhases] = useState<Set<Phase>>(new Set(ALL_PHASES));
  const { fitView } = useReactFlow();
  const canvas = useMemo(() => buildCanvas(graph, phases, query), [graph, phases, query]);
  const togglePhase = (phase: Phase) => setPhases((current) => {
    const next = new Set(current);
    if (next.has(phase)) next.delete(phase); else next.add(phase);
    return next.size ? next : new Set([phase]);
  });
  const selectNode = useCallback((_: React.MouseEvent, node: Node<CanvasData>) => {
    if (node.data.kind === "card") onSelect(node.data.item);
  }, [onSelect]);
  const matched = graph.nodes.filter((item) => {
    const node = canvas.nodes.find((candidate) => candidate.id === item.id);
    return node?.data.kind === "card" && !node.data.dimmed && !node.hidden;
  }).length;
  return <>
    <header className={`topShell ${selected ? "withInspector" : ""}`}>
      <div className="brand"><span><Workflow size={22} /></span><div><strong>Mission Control</strong><small>智能创作构建系统</small></div></div>
      <div className="runTitle"><span>BUILD #{graph.run.script_build_id}</span><strong>{graph.run.title}</strong></div>
      <div className="topStats">
        <span className="fakeBadge"><Sparkles size={13} /> FAKE DATA</span>
        <span><CheckCircle2 size={14} /> {graph.run.status}</span>
        <span><GitBranch size={14} /> {graph.run.node_count} nodes</span>
      </div>
    </header>
    <aside className="phaseRail">
      <div className="railTitle"><Layers3 size={16} /><span>流程阶段</span></div>
      {ALL_PHASES.map((phase) => <button key={phase} className={phases.has(phase) ? "active" : ""} onClick={() => togglePhase(phase)}>
        <span className={`phaseDot phase-${phase}`} />
        <span>{PHASE_LABELS[phase]}</span>
        <small>{graph.nodes.filter((item) => item.phase === phase).length}</small>
      </button>)}
      <div className="railDivider" />
      <button onClick={() => void fitView({ padding: 0.06, duration: 320 })}><Focus size={15} /><span>适应全图</span></button>
      <div className="checkpoint"><small>CURRENT CHECKPOINT</small><code>{graph.run.checkpoint}</code></div>
    </aside>
    <section className={`canvasShell ${selected ? "withInspector" : ""}`}>
      <ReactFlow
        nodes={canvas.nodes.map((node) => ({ ...node, selected: node.id === selected?.id }))}
        edges={canvas.edges}
        nodeTypes={nodeTypes}
        onNodeClick={selectNode}
        onPaneClick={() => onSelect(null)}
        onInit={(instance) => void instance.fitView({ padding: 0.06, duration: 0 })}
        minZoom={0.06}
        maxZoom={1.4}
        nodesConnectable={false}
        zoomOnDoubleClick={false}
        panOnScroll
        zoomOnPinch
        proOptions={{ hideAttribution: true }}
      >
        <Background variant={BackgroundVariant.Dots} gap={24} size={1.15} color="#383b44" />
        <Controls position="bottom-left" showInteractive={false} />
        <Panel position="top-left" className="canvasToolbar">
          <label><Search size={16} /><input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="搜索节点、模型、Task kind…" />{query ? <button onClick={() => setQuery("")}><X size={14} /></button> : null}</label>
          <span>{query ? `${matched} / ${graph.nodes.length}` : `${graph.nodes.length} nodes · ${graph.edges.length} edges`}</span>
        </Panel>
        <Panel position="bottom-right" className="legend">
          <span><i className="legend-control" />控制流</span>
          <span><i className="legend-artifact" />Artifact</span>
          <span><i className="legend-validation" />Validation</span>
          <span><i className="legend-publication" />Publication</span>
        </Panel>
      </ReactFlow>
    </section>
    {selected ? <Inspector item={selected} graph={graph} onClose={() => onSelect(null)} /> : null}
  </>;
}

function MissionControlInner() {
  const [runs, setRuns] = useState<RunSummary[]>([]);
  const [graph, setGraph] = useState<RunGraph | null>(null);
  const [selected, setSelected] = useState<FlowNodeRecord | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [nonce, setNonce] = useState(0);
  useEffect(() => {
    const controller = new AbortController();
    setError(null);
    Promise.all([fetchRuns(controller.signal), fetchGraph(10001, controller.signal)])
      .then(([nextRuns, nextGraph]) => { setRuns(nextRuns); setGraph(nextGraph); })
      .catch((reason: unknown) => {
        if (!controller.signal.aborted) setError(reason instanceof Error ? reason.message : "未知错误");
      });
    return () => controller.abort();
  }, [nonce]);
  if (error) return <ErrorState message={error} retry={() => setNonce((value) => value + 1)} />;
  if (!graph || !runs.length) return <LoadingState />;
  return <main className="appFrame"><Canvas graph={graph} selected={selected} onSelect={setSelected} /></main>;
}

export function MissionControl() {
  return <ReactFlowProvider><MissionControlInner /></ReactFlowProvider>;
}

