"use client";

import { useEffect, useState } from "react";

import {
  ArticleInputForm,
  type ArticleInputPayload,
} from "../components/article-input-form";
import {
  FactCardEditor,
  toConfirmedFactCard,
} from "../components/fact-card-editor";
import { OptimizedPreview } from "../components/optimized-preview";
import { ProgressPanel } from "../components/progress-panel";
import { QaReportPanel } from "../components/qa-report-panel";
import type {
  CandidateFactCard,
  OptimizedArticle,
  QaReport,
} from "../lib/domain/types";
import type { ProgressAction } from "../lib/progress/progress";

const initialInput: ArticleInputPayload = {
  title: "",
  body: "",
  image_lines: "",
  platform: "official_site",
  user_instructions: "",
};

interface ApiErrorResponse {
  error?: string;
  timing?: TimingSummary;
}

interface TimingStep {
  label: string;
  duration_ms: number;
}

interface TimingSummary {
  total_ms: number;
  steps: TimingStep[];
}

interface ProgressStep {
  label: string;
  status: "running" | "completed" | "failed";
  duration_ms?: number;
}

interface WorkflowProgress {
  current_step: string | null;
  status: "idle" | "running" | "completed" | "failed";
  steps: ProgressStep[];
}

interface ProgressResponse extends ApiErrorResponse {
  progress: WorkflowProgress;
}

interface CreateJobResponse extends ApiErrorResponse {
  job: { id: string };
  candidateFactCard: CandidateFactCard;
  timing?: TimingSummary;
}

interface ConfirmFactCardResponse extends ApiErrorResponse {
  factCard: CandidateFactCard;
}

interface OptimizeJobResponse extends ApiErrorResponse {
  optimizedArticle: OptimizedArticle;
  qaReport: QaReport;
  timing?: TimingSummary;
}

export default function Home() {
  const [input, setInput] = useState(initialInput);
  const [jobId, setJobId] = useState<string | null>(null);
  const [factCard, setFactCard] = useState<CandidateFactCard | null>(null);
  const [optimizedArticle, setOptimizedArticle] =
    useState<OptimizedArticle | null>(null);
  const [qaReport, setQaReport] = useState<QaReport | null>(null);
  const [busyAction, setBusyAction] = useState<ProgressAction | null>(null);
  const [message, setMessage] = useState<string>("");
  const [apiAccessKey, setApiAccessKey] = useState("");
  const [elapsedSeconds, setElapsedSeconds] = useState(0);
  const [lastTiming, setLastTiming] = useState<TimingSummary | null>(null);
  const [liveProgress, setLiveProgress] = useState<WorkflowProgress | null>(null);

  const canOptimize =
    Boolean(jobId) && Boolean(factCard) && factCard?.uncertain_items.length === 0;

  useEffect(() => {
    if (!busyAction) return;
    const startedAt = Date.now();
    const timer = window.setInterval(() => {
      setElapsedSeconds(Math.floor((Date.now() - startedAt) / 1000));
    }, 1000);
    return () => window.clearInterval(timer);
  }, [busyAction]);

  useEffect(() => {
    if (busyAction !== "optimize" || !jobId) return;
    let cancelled = false;

    async function pollProgress() {
      try {
        const response = await fetch(`/api/jobs/${jobId}/progress`, {
          headers: apiHeaders(apiAccessKey),
        });
        const body = (await response.json()) as ProgressResponse;
        if (!cancelled && response.ok) {
          setLiveProgress(body.progress);
        }
      } catch {
        // The main optimization request still owns user-facing errors.
      }
    }

    void pollProgress();
    const timer = window.setInterval(pollProgress, 2000);
    return () => {
      cancelled = true;
      window.clearInterval(timer);
    };
  }, [apiAccessKey, busyAction, jobId]);

  function startBusyAction(action: ProgressAction) {
    setElapsedSeconds(0);
    setBusyAction(action);
  }

  async function analyze() {
    startBusyAction("analyze");
    setMessage("");
    setLastTiming(null);
    setLiveProgress(null);
    setOptimizedArticle(null);
    setQaReport(null);
    try {
      const response = await fetch("/api/jobs", {
        method: "POST",
        headers: apiHeaders(apiAccessKey),
        body: JSON.stringify(input),
      });
      const body = (await response.json()) as CreateJobResponse;
      if (!response.ok) throw new ApiResponseError(body.error ?? "分析失败", body.timing);
      setJobId(body.job.id);
      setFactCard(body.candidateFactCard);
      setLastTiming(body.timing ?? null);
      setMessage(
        body.timing
          ? `候选事实卡已生成，用时 ${formatTiming(body.timing.total_ms)}。`
          : "候选事实卡已生成。",
      );
    } catch (error) {
      if (error instanceof ApiResponseError) {
        setLastTiming(error.timing ?? null);
      }
      setMessage(error instanceof Error ? error.message : "分析失败");
    } finally {
      setBusyAction(null);
    }
  }

  async function confirmFactCard() {
    if (!jobId || !factCard) return;
    startBusyAction("confirm");
    setMessage("");
    setLastTiming(null);
    try {
      const response = await fetch(`/api/jobs/${jobId}/confirm-fact-card`, {
        method: "POST",
        headers: apiHeaders(apiAccessKey),
        body: JSON.stringify(toConfirmedFactCard(factCard)),
      });
      const body = (await response.json()) as ConfirmFactCardResponse;
      if (!response.ok) throw new Error(body.error ?? "确认失败");
      setFactCard(body.factCard);
      setMessage("事实卡已确认。");
    } catch (error) {
      setMessage(error instanceof Error ? error.message : "确认失败");
    } finally {
      setBusyAction(null);
    }
  }

  async function optimize() {
    if (!jobId) return;
    startBusyAction("optimize");
    setMessage("");
    setLastTiming(null);
    setLiveProgress(null);
    try {
      const response = await fetch(`/api/jobs/${jobId}/optimize`, {
        method: "POST",
        headers: apiHeaders(apiAccessKey),
      });
      const body = (await response.json()) as OptimizeJobResponse;
      if (!response.ok) throw new ApiResponseError(body.error ?? "优化失败", body.timing);
      setOptimizedArticle(body.optimizedArticle);
      setQaReport(body.qaReport);
      setLastTiming(body.timing ?? null);
      setLiveProgress(null);
      const timingText = body.timing
        ? `用时 ${formatTiming(body.timing.total_ms)}。`
        : "";
      setMessage(
        body.qaReport.overall_status === "fail"
          ? `质检发现需要复核的问题，已保留导出文件。${timingText}`
          : `优化完成。${timingText}`,
      );
    } catch (error) {
      if (error instanceof ApiResponseError) {
        setLastTiming(error.timing ?? null);
      }
      setMessage(error instanceof Error ? error.message : "优化失败");
    } finally {
      setBusyAction(null);
    }
  }

  return (
    <main className="app-shell">
      <header className="topbar">
        <div>
          <h1>GEO 智能文章优化器</h1>
          {message && <p>{message}</p>}
        </div>
        <label className="api-key-field">
          <span>访问密钥</span>
          <input
            autoComplete="off"
            onChange={(event) => setApiAccessKey(event.target.value)}
            type="password"
            value={apiAccessKey}
          />
        </label>
        <button
          disabled={!canOptimize || busyAction === "optimize"}
          onClick={optimize}
          type="button"
        >
          {busyAction === "optimize" ? "优化中..." : "开始优化"}
        </button>
      </header>
      <ProgressPanel
        action={busyAction}
        elapsedSeconds={elapsedSeconds}
        lastTiming={lastTiming}
        liveProgress={liveProgress}
      />
      <div className="workflow-grid">
        <ArticleInputForm
          isSubmitting={busyAction === "analyze"}
          value={input}
          onChange={setInput}
          onSubmit={analyze}
        />
        <FactCardEditor
          factCard={factCard}
          isSaving={busyAction === "confirm"}
          onChange={setFactCard}
          onConfirm={confirmFactCard}
        />
        <OptimizedPreview
          article={optimizedArticle}
          jobId={jobId}
        />
        <QaReportPanel report={qaReport} />
      </div>
    </main>
  );
}

function apiHeaders(apiAccessKey: string) {
  const headers: Record<string, string> = { "content-type": "application/json" };
  if (apiAccessKey) {
    headers["x-api-key"] = apiAccessKey;
  }
  return headers;
}

function formatTiming(milliseconds: number) {
  const seconds = Math.round(milliseconds / 1000);
  if (seconds < 60) return `${seconds} 秒`;
  const minutes = Math.floor(seconds / 60);
  const remainingSeconds = seconds % 60;
  return `${minutes} 分 ${remainingSeconds} 秒`;
}

class ApiResponseError extends Error {
  constructor(
    message: string,
    public readonly timing?: TimingSummary,
  ) {
    super(message);
    this.name = "ApiResponseError";
  }
}
