"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { AlertTriangle, RefreshCw } from "lucide-react";

import { fetchJourney, fetchRuns } from "@/lib/api";
import { statusLabel } from "@/lib/journey";
import type { JourneyStep, JourneyView, RunSummary, ZoomLevel } from "@/lib/types";

import { EvidencePanel } from "@/components/EvidencePanel";
import { JourneyCanvas } from "@/components/JourneyCanvas";

const ZOOM_OPTIONS: Array<{ value: ZoomLevel; label: string; hint: string }> = [
  { value: "journey", label: "全局", hint: "看创作回合" },
  { value: "steps", label: "步骤", hint: "看规划与返工" },
  { value: "evidence", label: "证据", hint: "看原始记录" },
];
const TERMINAL_STATUSES = new Set(["completed", "stopped", "failed", "published"]);

export function JourneyApp() {
  const [runs, setRuns] = useState<RunSummary[]>([]);
  const [selectedRunId, setSelectedRunId] = useState<number | null>(null);
  const [journey, setJourney] = useState<JourneyView | null>(null);
  const [zoom, setZoom] = useState<ZoomLevel>("journey");
  const [selectedStepId, setSelectedStepId] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [refreshTick, setRefreshTick] = useState(0);

  useEffect(() => {
    const controller = new AbortController();
    fetchRuns(controller.signal)
      .then((values) => {
        setRuns(values);
        setSelectedRunId((current) => current ?? values[0]?.script_build_id ?? null);
      })
      .catch((reason: Error) => setError(reason.message))
      .finally(() => setLoading(false));
    return () => controller.abort();
  }, []);

  const loadJourney = useCallback(
    async (signal?: AbortSignal) => {
      if (selectedRunId === null) return null;
      setError(null);
      try {
        const value = await fetchJourney(selectedRunId, signal);
        setJourney(value);
        setSelectedStepId((current) =>
          current && value.steps.some((step) => step.step_id === current)
            ? current
            : value.steps[0]?.step_id ?? null,
        );
        return value;
      } catch (reason) {
        if (!(reason instanceof DOMException && reason.name === "AbortError")) {
          setError(reason instanceof Error ? reason.message : "无法读取创作旅程");
        }
        return null;
      }
    },
    [selectedRunId],
  );

  useEffect(() => {
    const controller = new AbortController();
    let timer: number | null = null;

    async function refresh() {
      const value = await loadJourney(controller.signal);
      if (
        !controller.signal.aborted &&
        value &&
        !TERMINAL_STATUSES.has(value.status.toLowerCase())
      ) {
        timer = window.setTimeout(refresh, 12_000);
      }
    }

    setLoading(true);
    refresh().finally(() => setLoading(false));
    return () => {
      controller.abort();
      if (timer !== null) window.clearTimeout(timer);
    };
  }, [loadJourney, refreshTick]);

  const selectedStep = useMemo<JourneyStep | null>(
    () => journey?.steps.find((step) => step.step_id === selectedStepId) ?? null,
    [journey, selectedStepId],
  );
  const selectedRun = useMemo(
    () => runs.find((run) => run.script_build_id === selectedRunId) ?? null,
    [runs, selectedRunId],
  );

  if (!loading && runs.length === 0 && !error) {
    return (
      <main className="empty-state">
        <h1>还没有可展示的创作记录</h1>
        <p>完成一次 Script Build 后，这里会按真实执行顺序展示它的规划、执行、验收和返工。</p>
      </main>
    );
  }

  return (
    <main className={`journey-app zoom-${zoom}`}>
      <header className="app-bar">
        <div className="brand-lockup">
          <span className="brand-mark" aria-hidden="true" />
          <div>
            <strong>智能创作旅程</strong>
            <span>每一步都回到真实记录</span>
          </div>
        </div>

        <label className="run-picker">
          <span>本次创作</span>
          <select
            value={selectedRunId ?? ""}
            onChange={(event) => setSelectedRunId(Number(event.target.value))}
          >
            {runs.map((run) => (
              <option key={run.script_build_id} value={run.script_build_id}>
                #{run.script_build_id} · {run.summary}
              </option>
            ))}
          </select>
        </label>

        <div className="zoom-switch" aria-label="查看层级">
          {ZOOM_OPTIONS.map((option) => (
            <button
              key={option.value}
              type="button"
              className={zoom === option.value ? "active" : ""}
              aria-pressed={zoom === option.value}
              onClick={() => setZoom(option.value)}
              title={option.hint}
            >
              {option.label}
            </button>
          ))}
        </div>

        <button
          className="icon-button"
          type="button"
          onClick={() => setRefreshTick((value) => value + 1)}
          aria-label="刷新创作旅程"
        >
          <RefreshCw size={17} className={loading ? "is-spinning" : ""} />
        </button>
      </header>

      {error ? (
        <div className="error-banner" role="alert">
          <AlertTriangle size={16} />
          <span>{error}</span>
          <button type="button" onClick={() => setRefreshTick((value) => value + 1)}>
            重试
          </button>
        </div>
      ) : null}

      {journey ? (
        <>
          <section className="mission-strip">
            <div className="mission-copy">
              <span className={`run-status status-${journey.status}`}>{statusLabel(journey.status)}</span>
              <h1>{journey.objective}</h1>
            </div>
            <div className="input-ribbon" aria-label="本次创作输入">
              <span className="ribbon-label">DATA IN</span>
              <strong>{journey.input_summary.topic}</strong>
              <span>{journey.input_summary.account_name ?? "未指定账号"}</span>
              <span>{journey.input_summary.persona_point_count} 条人设信息</span>
              <span>
                {journey.input_summary.strategy_names.length
                  ? journey.input_summary.strategy_names.join("、")
                  : "无额外策略"}
              </span>
            </div>
          </section>

          <div className="workspace">
            <JourneyCanvas
              journey={journey}
              zoom={zoom}
              selectedStepId={selectedStepId}
              onSelectStep={(stepId) => {
                setSelectedStepId(stepId);
                if (zoom === "journey") setZoom("steps");
              }}
            />
            {zoom === "evidence" ? (
              <EvidencePanel
                journey={journey}
                run={selectedRun}
                step={selectedStep}
                onClose={() => setZoom("steps")}
              />
            ) : null}
          </div>
        </>
      ) : (
        <div className="journey-skeleton" aria-label="正在读取创作旅程">
          <span />
          <span />
          <span />
        </div>
      )}
    </main>
  );
}
