import { useRef, useState } from "react";
import { Play, FileText, FileType2, Printer, FileCode } from "lucide-react";
import { generateReport, streamTokens, streamExec, reportExportUrl, type Identity, type ExecEvent } from "../lib/api";
import { saveReportAs, printReportHtml, notify } from "../lib/desktop";
import { ExecTrace } from "../components/ExecTrace";
import { Markdown } from "../components/Markdown";
import { Button, Input, Field, Panel, Dot, EmptyState, useToast } from "../ui";

// 安全文件名：去掉路径不安全字符，限长 + 指定后缀。
function reportFilename(topic: string, id: string, ext: string): string {
  const base = topic.replace(/[\\/:*?"<>|]/g, "").trim().slice(0, 40) || id;
  return `${base}.${ext}`;
}

type Phase = "idle" | "running" | "done" | "error";

// 报告生成：输入主题(+可选知识库) → 触发后端专用编排
// （规划大纲 → 各章并行检索+撰写 → 渲染 Word），实时看进度与正文，完成后下载 .docx。
export function ReportView({ identity }: { identity: Identity }) {
  const toast = useToast();
  const [topic, setTopic] = useState("");
  const [kb, setKb] = useState("");
  const [phase, setPhase] = useState<Phase>("idle");
  const [out, setOut] = useState("");
  const [exec, setExec] = useState<ExecEvent[]>([]);
  const [taskId, setTaskId] = useState("");
  const closeRef = useRef<(() => void) | null>(null);
  const execCloseRef = useRef<(() => void) | null>(null);
  const previewRef = useRef<HTMLDivElement>(null);

  const running = phase === "running";

  // 导出 Word / Markdown：后端按需现渲染（导出时再处理），经原生"另存为"或浏览器下载。
  const exportFile = async (format: "docx" | "md") => {
    try {
      const p = await saveReportAs(reportExportUrl(taskId, format), reportFilename(topic, taskId, format));
      if (p) toast.push("success", "已保存到 " + p);
    } catch (e) {
      toast.push("error", (e as Error).message);
    }
  };

  // 导出 PDF：把预览到的 Markdown(已渲染 HTML)送进打印视图出 PDF（CJK 零字体依赖）。
  const exportPdf = () => {
    const html = previewRef.current?.innerHTML;
    if (!html) {
      toast.push("error", "暂无报告正文可导出");
      return;
    }
    if (!printReportHtml(topic.trim() || taskId, html)) {
      toast.push("error", "打印窗口被拦截，请允许弹出窗口后重试");
    }
  };

  const onGenerate = async () => {
    if (!topic.trim() || running) return;
    closeRef.current?.();
    execCloseRef.current?.();
    setPhase("running");
    setOut("");
    setExec([]);
    setTaskId("");
    try {
      const id = await generateReport(identity, topic.trim(), kb.trim() || undefined);
      setTaskId(id);
      execCloseRef.current = streamExec(
        id,
        (ev) => setExec((xs) => [...xs, ev]),
        () => {},
        () => {},
      );
      closeRef.current = streamTokens(
        id,
        (tok) => setOut((o) => o + tok),
        () => {
          setPhase("done");
          toast.push("success", "报告已生成，可保存 Word");
          notify("报告已生成", topic.trim());
        },
        () => {
          setPhase("error");
          toast.push("error", "报告流连接中断");
        },
      );
    } catch (e) {
      setPhase("error");
      toast.push("error", (e as Error).message);
    }
  };

  const tracePhase = running ? "streaming" : phase === "done" ? "done" : phase === "error" ? "error" : "idle";

  return (
    <div className="flex h-full min-h-0 flex-col gap-4 overflow-hidden p-6">
      <header>
        <h1 className="text-lg font-semibold text-slate-100">报告生成</h1>
        <p className="mt-1 text-xs text-slate-500">
          规划大纲 → 各章并行（知识库检索 + LLM 撰写）→ 汇聚 → 渲染真实 Word(.docx)。依赖已配置对话模型；挂知识库则引用其资料。
        </p>
      </header>

      <div className="grid grid-cols-[1fr_220px_auto_auto] items-end gap-3 rounded-lg border border-line bg-ink-900 p-4 shadow-card">
        <Field label="报告主题">
          <Input
            value={topic}
            onChange={(e) => setTopic(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && onGenerate()}
            placeholder="如：2026 年国产大模型产业现状与趋势分析"
          />
        </Field>
        <Field label="知识库（可选）">
          <Input value={kb} onChange={(e) => setKb(e.target.value)} placeholder="如 docs，留空则不挂检索" />
        </Field>
        <Button variant="primary" icon={Play} onClick={onGenerate} disabled={running || !topic.trim()}>
          {running ? "生成中…" : "生成报告"}
        </Button>
        {phase === "done" && taskId ? (
          <div className="flex items-center gap-2">
            <span className="text-[11px] text-slate-500">导出</span>
            <Button icon={FileType2} onClick={() => exportFile("docx")}>
              Word
            </Button>
            <Button icon={Printer} onClick={exportPdf}>
              PDF
            </Button>
            <Button variant="ghost" icon={FileCode} onClick={() => exportFile("md")}>
              Markdown
            </Button>
          </div>
        ) : (
          <span className="h-9" />
        )}
      </div>

      <div className="grid min-h-0 flex-1 grid-cols-[340px_1fr] gap-4">
        <Panel title="执行轨迹" icon={FileText}>
          <ExecTrace events={exec} phase={tracePhase} />
        </Panel>

        <Panel
          title={
            <span className="flex items-center gap-2">
              <Dot tone={running ? "running" : phase === "done" ? "success" : "neutral"} pulse={running} />
              报告正文 · {taskId || "未开始"}
            </span>
          }
        >
          {out ? (
            <div ref={previewRef}>
              <Markdown text={out} className="text-sm" />
            </div>
          ) : (
            <EmptyState icon={FileText} title="尚未生成报告" desc="输入主题并点击「生成报告」，这里将实时显示规划与撰写过程。" />
          )}
        </Panel>
      </div>
    </div>
  );
}
