import { useCallback, useEffect, useMemo, useState } from "react";
import {
  ReactFlow,
  Background,
  Controls,
  MiniMap,
  addEdge,
  useNodesState,
  useEdgesState,
  type Connection,
  type Node,
  type Edge,
} from "@xyflow/react";
import "@xyflow/react/dist/style.css";

import { nodeTypes, type NodeStatus } from "./TypedNode";
import { Inspector } from "./Inspector";
import { NODE_KINDS, NODE_ORDER } from "./nodeCatalog";
import { exportDsl, validate, type Issue, type TaskDsl } from "../lib/dsl";
import type { RunPhase } from "../lib/run";

let seq = 0;

// 编排 Studio：左节点面板 · 中画布 · 右检查器 · 顶工具栏。
export function StudioView({
  onRun,
  phase,
}: {
  onRun: (dsl: TaskDsl) => void;
  phase: RunPhase;
}) {
  const [nodes, setNodes, onNodesChange] = useNodesState<Node>([]);
  const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
  const [selId, setSelId] = useState<string | null>(null);
  const [issues, setIssues] = useState<Issue[] | null>(null);

  const onConnect = useCallback((c: Connection) => setEdges((es) => addEdge(c, es)), [setEdges]);

  const addNode = useCallback(
    (kind: string) => {
      const id = `n${++seq}`;
      const k = NODE_KINDS[kind];
      setNodes((ns) => [
        ...ns,
        {
          id,
          type: "typed",
          position: { x: 120 + ((ns.length * 40) % 360), y: 60 + ns.length * 64 },
          data: { kind, label: k.label, config: { ...k.defaults }, status: "idle" as NodeStatus },
        },
      ]);
    },
    [setNodes],
  );

  const patchNode = useCallback(
    (id: string, patch: Record<string, unknown>) =>
      setNodes((ns) => ns.map((n) => (n.id === id ? { ...n, data: { ...n.data, ...patch } } : n))),
    [setNodes],
  );

  const deleteNode = useCallback(
    (id: string) => {
      setNodes((ns) => ns.filter((n) => n.id !== id));
      setEdges((es) => es.filter((e) => e.source !== id && e.target !== id));
      setSelId(null);
    },
    [setNodes, setEdges],
  );

  // 运行状态映射到节点徽标：流式中全部 running，完成 done，空闲清除。
  useEffect(() => {
    const status: NodeStatus =
      phase === "streaming" || phase === "submitting"
        ? "running"
        : phase === "done"
          ? "done"
          : phase === "error"
            ? "error"
            : "idle";
    setNodes((ns) => ns.map((n) => ({ ...n, data: { ...n.data, status } })));
  }, [phase, setNodes]);

  const run = useCallback(() => {
    const found = validate(nodes, edges);
    setIssues(found);
    if (!found.some((i) => i.level === "error")) onRun(exportDsl(nodes, edges));
  }, [nodes, edges, onRun]);

  const selected = useMemo(() => nodes.find((n) => n.id === selId) ?? null, [nodes, selId]);
  const running = phase === "submitting" || phase === "streaming";

  return (
    <div className="flex h-full">
      {/* 左节点面板 */}
      <div className="w-40 shrink-0 overflow-auto border-r bg-gray-50 p-2">
        <div className="mb-1 px-1 text-[11px] font-semibold text-gray-500">节点</div>
        {NODE_ORDER.map((kind) => {
          const k = NODE_KINDS[kind];
          return (
            <button
              key={kind}
              onClick={() => addNode(kind)}
              className={`mb-1 flex w-full items-center gap-2 rounded border border-l-4 bg-white px-2 py-1.5 text-left text-xs hover:bg-gray-50 ${k.accent}`}
              title={k.desc}
            >
              {k.label}
            </button>
          );
        })}
      </div>

      {/* 中画布 */}
      <div className="relative flex-1">
        <div className="absolute left-0 right-0 top-0 z-10 flex items-center gap-2 border-b bg-white/90 px-2 py-1.5">
          <button
            onClick={run}
            disabled={running || nodes.length === 0}
            className="rounded bg-violet-600 px-3 py-1 text-xs font-medium text-white disabled:opacity-40"
          >
            {running ? "运行中…" : "▶ 运行"}
          </button>
          <button
            onClick={() => setIssues(validate(nodes, edges))}
            className="rounded border px-3 py-1 text-xs hover:bg-gray-50"
          >
            校验
          </button>
          <span className="ml-1 text-[11px] text-gray-400">
            {nodes.length} 节点 · {edges.length} 连线
          </span>
          {issues && (
            <span className="ml-auto text-[11px]">
              {issues.length === 0 ? (
                <span className="text-emerald-600">✓ 校验通过</span>
              ) : (
                <span className="text-amber-600">{issues.length} 项提示</span>
              )}
            </span>
          )}
        </div>

        <ReactFlow
          nodes={nodes}
          edges={edges}
          nodeTypes={nodeTypes}
          onNodesChange={onNodesChange}
          onEdgesChange={onEdgesChange}
          onConnect={onConnect}
          onNodeClick={(_, n) => setSelId(n.id)}
          onPaneClick={() => setSelId(null)}
          fitView
        >
          <Background />
          <Controls />
          <MiniMap zoomable pannable className="!bg-white" />
        </ReactFlow>

        {issues && issues.length > 0 && (
          <div className="absolute bottom-2 left-2 max-w-md rounded border bg-white p-2 text-[11px] shadow">
            {issues.map((i, idx) => (
              <div key={idx} className={i.level === "error" ? "text-rose-600" : "text-amber-600"}>
                {i.level === "error" ? "✗" : "⚠"} {i.msg}
              </div>
            ))}
          </div>
        )}
      </div>

      {/* 右检查器 */}
      <div className="w-72 shrink-0 border-l bg-white">
        <Inspector node={selected} onChange={patchNode} onDelete={deleteNode} />
      </div>
    </div>
  );
}
