import {
  ArrowDown,
  Brain,
  CheckCircle2,
  CircleDot,
  Database,
  GitBranch,
  Play,
  RefreshCcw,
  Route,
  SearchCheck,
  Wrench,
} from "lucide-react";

import { buildTaskCycles, groupParallelSteps, statusLabel } from "@/lib/journey";
import type { JourneyEdge, JourneyStep, JourneyView, StepType, ZoomLevel } from "@/lib/types";

const STEP_META: Record<StepType, { label: string; icon: typeof Brain }> = {
  plan: { label: "规划", icon: Route },
  execute: { label: "执行", icon: Play },
  validate: { label: "验收", icon: SearchCheck },
  decide: { label: "决策", icon: GitBranch },
};

interface JourneyCanvasProps {
  journey: JourneyView;
  zoom: ZoomLevel;
  selectedStepId: string | null;
  onSelectStep: (stepId: string) => void;
}

export function JourneyCanvas({ journey, zoom, selectedStepId, onSelectStep }: JourneyCanvasProps) {
  if (zoom === "journey") {
    return <JourneyOverview journey={journey} onSelectStep={onSelectStep} />;
  }
  const groups = groupParallelSteps(journey.steps);
  const loops = new Map(
    journey.edges.filter((edge) => edge.relation === "loop").map((edge) => [edge.source, edge]),
  );
  return (
    <section className="flow-canvas" aria-label="创作步骤">
      <div className="flow-heading">
        <div>
          <span>按真实发生顺序</span>
          <h2>Planner 如何一步步完成目标</h2>
        </div>
        <p>点击任何步骤后切换到“证据”，可查看对应的合同、工具调用和验收记录。</p>
      </div>
      <div className="causal-spine">
        {groups.map((group, index) => (
          <div className={`flow-unit ${group.kind}`} key={group.id}>
            {group.kind === "parallel" ? (
              <div className="parallel-frame">
                <div className="parallel-heading">
                  <GitBranch size={16} />
                  <span>Host 并行派发 {group.steps.length} 个任务</span>
                </div>
                <div className="parallel-lanes">
                  {group.steps.map((step) => (
                    <StepCard
                      key={step.step_id}
                      step={step}
                      loop={loops.get(step.step_id)}
                      selected={step.step_id === selectedStepId}
                      onSelect={() => onSelectStep(step.step_id)}
                    />
                  ))}
                </div>
              </div>
            ) : (
              <StepCard
                step={group.steps[0]}
                loop={loops.get(group.steps[0].step_id)}
                selected={group.steps[0].step_id === selectedStepId}
                onSelect={() => onSelectStep(group.steps[0].step_id)}
              />
            )}
            {index < groups.length - 1 ? (
              <span className="flow-connector" aria-hidden="true">
                <ArrowDown size={15} />
              </span>
            ) : null}
          </div>
        ))}
      </div>
      {journey.warnings.map((warning) => (
        <p className="projection-note" key={warning}>{warning}</p>
      ))}
    </section>
  );
}

function JourneyOverview({
  journey,
  onSelectStep,
}: {
  journey: JourneyView;
  onSelectStep: (stepId: string) => void;
}) {
  const cycles = buildTaskCycles(journey.steps, journey.edges);
  return (
    <section className="overview-canvas" aria-label="全局创作旅程">
      <div className="overview-heading">
        <h2>这次创作经过了 {cycles.length} 个任务回合</h2>
        <p>默认只看业务因果。点开一个回合，再看 Planner、Worker 和 Validator 如何协作。</p>
      </div>
      <ol className="cycle-line">
        {cycles.map((cycle, index) => (
          <li key={cycle.taskId}>
            <button type="button" onClick={() => onSelectStep(cycle.steps[0].step_id)}>
              <span className="cycle-index">{String(index + 1).padStart(2, "0")}</span>
              <div className="cycle-copy">
                <div className="cycle-title-row">
                  <h3>{cycle.title}</h3>
                  <span className={`status-chip status-${cycle.status}`}>{statusLabel(cycle.status)}</span>
                </div>
                <p>{cycle.steps[0].reasoning}</p>
                <div className="cycle-facts">
                  {cycle.goals.length ? <span>目标 {cycle.goals.join("、")}</span> : null}
                  <span>{cycle.steps.length} 个真实步骤</span>
                  {cycle.parallel ? <span><GitBranch size={12} /> 包含并行</span> : null}
                  {cycle.loopCount ? <span><RefreshCcw size={12} /> 返工 {cycle.loopCount} 次</span> : null}
                </div>
                <div className="cycle-lifecycle" aria-label="回合生命周期">
                  {(["plan", "execute", "validate", "decide"] as StepType[]).map((type) => {
                    const present = cycle.steps.some((step) => step.step_type === type);
                    const Icon = STEP_META[type].icon;
                    return (
                      <span className={present ? "present" : ""} key={type}>
                        <Icon size={13} /> {STEP_META[type].label}
                      </span>
                    );
                  })}
                </div>
              </div>
              <ArrowDown className="cycle-open" size={17} />
            </button>
          </li>
        ))}
      </ol>
    </section>
  );
}

function StepCard({
  step,
  loop,
  selected,
  onSelect,
}: {
  step: JourneyStep;
  loop?: JourneyEdge;
  selected: boolean;
  onSelect: () => void;
}) {
  const meta = STEP_META[step.step_type];
  const Icon = meta.icon;
  return (
    <article className={`step-node type-${step.step_type} ${selected ? "selected" : ""}`}>
      <button type="button" className="step-hit-area" onClick={onSelect} aria-label={`查看${step.title}的原始证据`} />
      <header className="step-header">
        <span className="step-type"><Icon size={15} /> {meta.label}</span>
        <span className={`status-chip status-${step.status}`}>{statusLabel(step.status)}</span>
      </header>
      <h3>{step.title}</h3>

      <div className="step-layer reasoning-layer">
        <span><Brain size={14} /> 思考</span>
        <p>{step.reasoning}</p>
        <small>{step.reasoning_source === "observable" ? "Planner / Agent 主动说明" : "由真实冻结记录转述"}</small>
      </div>

      <div className="step-layer process-layer">
        <span><Wrench size={14} /> 动作</span>
        <p>{step.process.label}</p>
        <small>{step.process.actor}{step.process.tool_name ? ` · ${step.process.tool_name}` : ""}</small>
      </div>

      <div className="data-flow">
        <div>
          <span><Database size={13} /> 输入</span>
          {step.input_data.map((item, index) => <b key={`${item.label}-${index}`}>{item.label}</b>)}
        </div>
        <ArrowDown size={14} aria-hidden="true" />
        <div>
          <span><CircleDot size={13} /> 产出</span>
          {step.output_data.map((item, index) => <b key={`${item.label}-${index}`}>{item.label}</b>)}
        </div>
      </div>

      {step.contract ? (
        <div className="contract-summary">
          <strong>任务合同</strong>
          <span>{step.contract.goals.length ? `覆盖 ${step.contract.goals.join("、")}` : "不限定单一 Goal"}</span>
          <span>产出 {step.contract.output}</span>
          <span>{step.contract.criteria.length} 项验收标准</span>
        </div>
      ) : null}

      {step.parallel_total ? (
        <span className="parallel-badge">并行 {step.parallel_position}/{step.parallel_total}</span>
      ) : null}
      {loop ? (
        <div className="loop-ribbon"><RefreshCcw size={14} /> {loop.label}·回到前面继续</div>
      ) : null}
      <footer className="step-metrics">
        {step.duration_ms !== null ? <span>{formatDuration(step.duration_ms)}</span> : null}
        {step.tokens !== null ? <span>{step.tokens.toLocaleString()} tokens</span> : null}
        {step.cost !== null ? <span>cost {step.cost.toFixed(4)}</span> : null}
        {step.model ? <span>{step.model}</span> : null}
        <span className="evidence-cue"><CheckCircle2 size={13} /> 可追溯</span>
      </footer>
    </article>
  );
}

function formatDuration(value: number): string {
  if (value < 1000) return `${value}ms`;
  if (value < 60_000) return `${(value / 1000).toFixed(1)}s`;
  return `${Math.floor(value / 60_000)}m ${Math.round((value % 60_000) / 1000)}s`;
}
