"use client";

import Link from "next/link";
import { useEffect, useState } from "react";

import {
  ArticleInputForm,
  type ArticleInputPayload,
} from "../components/article-input-form";
import { FactCardEditor } from "../components/fact-card-editor";
import { OptimizedPreview } from "../components/optimized-preview";
import { PerformanceCalibrationPanel } from "../components/performance-calibration-panel";
import { ProgressPanel } from "../components/progress-panel";
import { QaReportPanel } from "../components/qa-report-panel";
import { RenweiCopyOptimizerPanel } from "../components/renwei-copy-optimizer-panel";
import type {
  OptimizationFactCard,
  OptimizedArticle,
  QaReport,
} from "../lib/domain/types";
import type { ProgressAction } from "../lib/progress/progress";
import {
  parseOptimizationStreamChunk,
  type OptimizationStreamEvent,
} from "../lib/workflow/stream-events";

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

interface ApiErrorResponse {
  error?: string;
}

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

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

export default function Home() {
  const [activeTab, setActiveTab] = useState<"geo" | "copy">("geo");
  const [input, setInput] = useState(initialInput);
  const [jobId, setJobId] = useState<string | null>(null);
  const [factCard, setFactCard] = useState<OptimizationFactCard | null>(null);
  const [draftArticle, setDraftArticle] = useState<OptimizedArticle | 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 [streamActivity, setStreamActivity] = useState("");

  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]);

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

  async function optimize() {
    startBusyAction("optimize");
    setMessage("");
    setLastTiming(null);
    setDraftArticle(null);
    setOptimizedArticle(null);
    setQaReport(null);
    setStreamActivity("正在创建任务");

    try {
      const payload: ArticleInputPayload & {
        fact_card?: OptimizationFactCard;
      } = {
        ...input,
        title: "",
      };
      if (factCard) {
        payload.fact_card = factCard;
      }

      const response = await fetch("/api/jobs/optimize-stream", {
        method: "POST",
        headers: apiHeaders(apiAccessKey),
        body: JSON.stringify(payload),
      });

      if (!response.ok) {
        const body = (await response.json()) as ApiErrorResponse;
        throw new Error(body.error ?? "优化失败");
      }

      await readOptimizationStream(response, handleStreamEvent);
    } catch (error) {
      setMessage(error instanceof Error ? error.message : "优化失败");
    } finally {
      setBusyAction(null);
    }
  }

  function handleStreamEvent(event: OptimizationStreamEvent) {
    switch (event.type) {
      case "job_created":
        setJobId(event.job.id);
        setStreamActivity("任务已创建");
        break;
      case "fact_card_ready":
        setFactCard(event.fact_card);
        setStreamActivity("事实卡已就绪");
        break;
      case "draft_started":
        setStreamActivity(event.message);
        break;
      case "draft_ready":
        setDraftArticle(event.article);
        setStreamActivity("草稿已生成");
        break;
      case "qa_started":
        setStreamActivity(event.message);
        break;
      case "qa_ready":
        setQaReport(event.qa_report);
        setStreamActivity("质量检查完成");
        break;
      case "rewrite_started":
        setStreamActivity(`正在修复第 ${event.round} 轮`);
        break;
      case "rewrite_ready":
        setDraftArticle(event.article);
        setStreamActivity(`第 ${event.round} 轮修复完成`);
        break;
      case "final_ready":
        setOptimizedArticle(event.optimized_article);
        setDraftArticle(null);
        setQaReport(event.qa_report);
        setStreamActivity("终稿已生成");
        setMessage(
          event.qa_report.overall_status === "fail"
            ? "优化完成，质检发现需要复核的问题。"
            : "优化完成。",
        );
        break;
      case "failed":
        setStreamActivity("优化失败");
        throw new Error(event.error);
    }
  }

  return (
    <main className="app-shell">
      <header className="topbar">
        <div>
          <h1>GEO 智能文章优化器</h1>
          {message && <p>{message}</p>}
        </div>
        <div className="topbar-actions">
          <Link className="text-link" href="/cases">
            案例库
          </Link>
          <label className="api-key-field">
            <span>访问密钥</span>
            <input
              autoComplete="off"
              onChange={(event) => setApiAccessKey(event.target.value)}
              type="password"
              value={apiAccessKey}
            />
          </label>
        </div>
      </header>
      <nav className="app-tabs" aria-label="功能标签">
        <button
          className={activeTab === "geo" ? "active-tab" : undefined}
          onClick={() => setActiveTab("geo")}
          type="button"
        >
          GEO 文章优化
        </button>
        <button
          className={activeTab === "copy" ? "active-tab" : undefined}
          onClick={() => setActiveTab("copy")}
          type="button"
        >
          普通文案优化
        </button>
      </nav>
      {activeTab === "geo" ? (
        <>
          <ProgressPanel
            action={busyAction}
            elapsedSeconds={elapsedSeconds}
            lastTiming={lastTiming}
            liveProgress={null}
          />
          <div className="workflow-grid">
            <ArticleInputForm
              isSubmitting={busyAction === "optimize"}
              value={input}
              onChange={setInput}
              onSubmit={optimize}
            />
            <FactCardEditor
              factCard={factCard}
              isSaving={busyAction === "optimize"}
              onChange={setFactCard}
            />
            <OptimizedPreview
              activityText={streamActivity}
              article={optimizedArticle}
              draftArticle={draftArticle}
              isStreaming={busyAction === "optimize"}
              jobId={jobId}
            />
            <QaReportPanel report={qaReport} />
            <PerformanceCalibrationPanel
              apiAccessKey={apiAccessKey}
              jobId={jobId}
              key={`${jobId ?? "no-job"}-${optimizedArticle?.revision ?? "no-revision"}`}
              optimizedRevision={optimizedArticle?.revision ?? null}
            />
          </div>
        </>
      ) : (
        <RenweiCopyOptimizerPanel
          apiAccessKey={apiAccessKey}
        />
      )}
    </main>
  );
}

async function readOptimizationStream(
  response: Response,
  onEvent: (event: OptimizationStreamEvent) => void,
) {
  if (!response.body) {
    throw new Error("当前浏览器不支持流式响应");
  }

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let remainder = "";

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const parsed = parseOptimizationStreamChunk(
      remainder,
      decoder.decode(value, { stream: true }),
    );
    remainder = parsed.remainder;
    parsed.events.forEach(onEvent);
  }

  const finalText = decoder.decode();
  if (finalText) {
    const parsed = parseOptimizationStreamChunk(remainder, finalText);
    remainder = parsed.remainder;
    parsed.events.forEach(onEvent);
  }

  if (remainder.trim().length > 0) {
    onEvent(JSON.parse(remainder) as OptimizationStreamEvent);
  }
}

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