import { useEffect, useMemo, useState } from "react";
import { useLocation, useNavigate, useParams } from "react-router";
import {
  AlertCircle,
  ArrowRight,
  CheckCircle2,
  FileText,
  Film,
  Loader2,
  MapPin,
  RefreshCw,
  Sparkles,
  Users,
} from "lucide-react";
import { useQueryClient } from "@tanstack/react-query";
import { Progress } from "../components/ui/progress";
import { useGenerateEpisodes, useGenerateOutline, useOutline } from "../../hooks/useAi";
import { projectsApi, type ScriptInfoDTO } from "../../lib/api/projects";

type ProcessingStep = {
  label: string;
  hint: string;
  progress: number;
};

type ProcessingState = {
  title: string;
  description: string;
  steps: ProcessingStep[];
};

type OutlineLocationState = {
  fromNewProject?: boolean;
  projectName?: string;
};

const checkingOutlineState: ProcessingState = {
  title: "正在检查项目状态",
  description: "先确认这个项目是否已经有可用大纲。",
  steps: [
    {
      label: "检查已有大纲",
      hint: "正在确认是否需要重新解析上传的剧本。",
      progress: 12,
    },
  ],
};

const parsingScriptState: ProcessingState = {
  title: "正在解析上传的剧本",
  description: "系统正在读取文档内容，并抽取剧情结构、人物与场景信息。",
  steps: [
    {
      label: "读取剧本文件",
      hint: "正在加载上传的 Word、PDF 或文本内容。",
      progress: 24,
    },
    {
      label: "分析剧情结构",
      hint: "正在识别主线冲突、题材和整体节奏。",
      progress: 52,
    },
    {
      label: "整理角色与场景",
      hint: "正在生成可预览的结构化摘要。",
      progress: 82,
    },
  ],
};

const readingScriptState: ProcessingState = {
  title: "正在准备剧本文本",
  description: "未拿到结构化摘要，正在回退为读取原始剧本文本。",
  steps: [
    {
      label: "读取原始文本",
      hint: "正在提取上传剧本中的正文内容。",
      progress: 36,
    },
    {
      label: "填充编辑器",
      hint: "马上就可以在这里直接生成大纲。",
      progress: 74,
    },
  ],
};

const importingScriptState: ProcessingState = {
  title: "正在导入剧本数据",
  description: "系统会把剧本拆解为大纲、分集、角色、场景和分镜，请稍候。",
  steps: [
    {
      label: "解析整体结构",
      hint: "正在理解故事主线与题材风格。",
      progress: 24,
    },
    {
      label: "生成大纲与分集",
      hint: "正在生成故事梗概和每集节奏。",
      progress: 56,
    },
    {
      label: "写入角色与场景",
      hint: "正在把结果保存到项目工作区。",
      progress: 88,
    },
  ],
};

const generatingOutlineState: ProcessingState = {
  title: "AI 正在生成剧本大纲",
  description: "正在根据剧本文本组织故事主线、题材和概要描述。",
  steps: [
    {
      label: "理解剧本主线",
      hint: "正在提取核心矛盾和人物关系。",
      progress: 30,
    },
    {
      label: "归纳故事结构",
      hint: "正在组织题材、世界观和章节节奏。",
      progress: 62,
    },
    {
      label: "输出大纲结果",
      hint: "正在整理可直接预览的大纲内容。",
      progress: 90,
    },
  ],
};

function formatElapsed(seconds: number) {
  const mins = Math.floor(seconds / 60);
  const secs = seconds % 60;
  return mins > 0 ? `${mins}分 ${secs}秒` : `${secs}秒`;
}

function ProcessingScreen({ state, elapsedSeconds, projectName }: {
  state: ProcessingState;
  elapsedSeconds: number;
  projectName?: string;
}) {
  const [activeStep, setActiveStep] = useState(0);

  useEffect(() => {
    setActiveStep(0);
    if (state.steps.length <= 1) return undefined;

    const timer = window.setInterval(() => {
      setActiveStep((current) => Math.min(current + 1, state.steps.length - 1));
    }, 1800);

    return () => window.clearInterval(timer);
  }, [state]);

  const progressValue = state.steps[Math.min(activeStep, state.steps.length - 1)]?.progress ?? 0;

  return (
    <div className="h-full bg-background flex items-center justify-center p-6">
      <div className="w-full max-w-2xl rounded-3xl border border-border bg-card shadow-xl p-8">
        <div className="flex items-start gap-4 mb-6">
          <div className="w-16 h-16 rounded-2xl bg-gradient-to-br from-[#5b5ff9] to-[#8b5ff9] flex items-center justify-center flex-shrink-0">
            <Loader2 className="w-8 h-8 text-white animate-spin" />
          </div>
          <div className="flex-1">
            <div className="flex items-center justify-between gap-4 mb-2">
              <h1 className="text-2xl font-semibold text-foreground">{state.title}</h1>
              <span className="text-xs text-muted-foreground whitespace-nowrap">已用时 {formatElapsed(elapsedSeconds)}</span>
            </div>
            <p className="text-sm text-muted-foreground leading-relaxed">{state.description}</p>
            {projectName && (
              <p className="text-xs text-primary mt-2">当前项目：{projectName}</p>
            )}
          </div>
        </div>

        <div className="rounded-2xl border border-primary/15 bg-primary/5 p-5 mb-6">
          <div className="flex items-center justify-between text-sm mb-3">
            <span className="text-foreground font-medium">{state.steps[Math.min(activeStep, state.steps.length - 1)]?.label}</span>
            <span className="text-primary">{progressValue}%</span>
          </div>
          <Progress value={progressValue} className="h-2.5 mb-3" />
          <p className="text-sm text-muted-foreground">{state.steps[Math.min(activeStep, state.steps.length - 1)]?.hint}</p>
        </div>

        <div className="space-y-3">
          {state.steps.map((step, index) => {
            const isDone = index < activeStep;
            const isCurrent = index === activeStep;

            return (
              <div key={step.label} className="flex items-start gap-3 rounded-xl border border-border/70 bg-background px-4 py-3">
                <div className="mt-0.5">
                  {isDone ? (
                    <CheckCircle2 className="w-5 h-5 text-green-500" />
                  ) : isCurrent ? (
                    <Loader2 className="w-5 h-5 text-primary animate-spin" />
                  ) : (
                    <div className="w-5 h-5 rounded-full border-2 border-border" />
                  )}
                </div>
                <div>
                  <div className="text-sm font-medium text-foreground">{step.label}</div>
                  <div className="text-xs text-muted-foreground mt-0.5">{step.hint}</div>
                </div>
              </div>
            );
          })}
        </div>

        <p className="text-xs text-muted-foreground mt-5">
          当前为前端阶段性实时反馈。如果后端后续提供解析进度接口，这里可以进一步切成真实百分比。
        </p>
      </div>
    </div>
  );
}

export function OutlineGeneration() {
  const navigate = useNavigate();
  const location = useLocation();
  const { projectId } = useParams<{ projectId: string }>();
  const pid = projectId ?? "";
  const qc = useQueryClient();

  const outlineState = location.state as OutlineLocationState | null;
  const projectNameFromState = outlineState?.projectName;

  const { data: outline, isLoading: loadingOutline } = useOutline(pid);
  const generateOutline = useGenerateOutline(pid);
  const generateEpisodes = useGenerateEpisodes(pid);

  const [scriptInfo, setScriptInfo] = useState<ScriptInfoDTO | null>(null);
  const [script, setScript] = useState("");
  const [showManual, setShowManual] = useState(false);
  const [loadingScript, setLoadingScript] = useState(false);
  const [preparingState, setPreparingState] = useState<"idle" | "parsing" | "reading">("idle");
  const [importing, setImporting] = useState(false);
  const [importError, setImportError] = useState<string | null>(null);
  const [elapsedSeconds, setElapsedSeconds] = useState(0);

  useEffect(() => {
    if (!pid || outline || loadingOutline) return;

    let cancelled = false;
    setPreparingState("parsing");
    setImportError(null);

    projectsApi.parseScript(pid)
      .then((info) => {
        if (cancelled) return;
        setScriptInfo(info);
        setShowManual(false);
      })
      .catch(async () => {
        if (cancelled) return;

        setPreparingState("reading");
        setLoadingScript(true);

        try {
          const text = await projectsApi.readScriptContent(pid);
          if (cancelled) return;
          if (text) {
            setScript(text.slice(0, 8000));
          }
        } catch {
          // Keep manual editor empty so the user can paste script content manually.
        } finally {
          if (!cancelled) {
            setLoadingScript(false);
          }
        }
      })
      .finally(() => {
        if (!cancelled) {
          setPreparingState("idle");
        }
      });

    return () => {
      cancelled = true;
    };
  }, [pid, outline, loadingOutline]);

  const handleImport = async () => {
    if (!pid || importing) return;

    setImporting(true);
    setImportError(null);

    try {
      await projectsApi.importScript(pid);
      await qc.invalidateQueries({ queryKey: ["outline", pid] });
      await qc.invalidateQueries({ queryKey: ["episodes", pid] });
      await qc.invalidateQueries({ queryKey: ["characters", pid] });
      await qc.invalidateQueries({ queryKey: ["scenes", pid] });
      navigate(`/project/${projectId}/episodes`);
    } catch (error) {
      setImportError((error as Error)?.message ?? "导入失败，请重试");
    } finally {
      setImporting(false);
    }
  };

  const handleGenerate = async () => {
    if (!script.trim()) return;

    setImportError(null);
    await generateOutline.mutateAsync(script);
    setShowManual(false);
  };

  const handleContinue = async () => {
    if (!outline) return;

    await generateEpisodes.mutateAsync();
    navigate(`/project/${projectId}/episodes`);
  };

  const processingState = useMemo<ProcessingState | null>(() => {
    if (!outline && loadingOutline) return checkingOutlineState;
    if (importing) return importingScriptState;
    if (generateOutline.isPending) return generatingOutlineState;
    if (preparingState === "parsing") return parsingScriptState;
    if (preparingState === "reading") return readingScriptState;
    return null;
  }, [generateOutline.isPending, importing, loadingOutline, outline, preparingState]);

  useEffect(() => {
    if (!processingState || outline) {
      setElapsedSeconds(0);
      return undefined;
    }

    setElapsedSeconds(0);
    const timer = window.setInterval(() => {
      setElapsedSeconds((current) => current + 1);
    }, 1000);

    return () => window.clearInterval(timer);
  }, [outline, processingState]);

  if (processingState && !outline) {
    return (
      <ProcessingScreen
        state={processingState}
        elapsedSeconds={elapsedSeconds}
        projectName={projectNameFromState}
      />
    );
  }

  if (!outline) {
    return (
      <div className="h-full overflow-auto bg-background p-6">
        <div className="max-w-3xl mx-auto">
          <div className="mb-6 flex items-center gap-3">
            <div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[#5b5ff9] to-[#8b5ff9] flex items-center justify-center">
              <Sparkles className="w-4 h-4 text-white" />
            </div>
            <div>
              <h1 className="text-2xl font-semibold text-foreground">生成剧本大纲</h1>
              <p className="text-sm text-muted-foreground">先预览剧本解析结果，再决定直接导入或手动生成大纲。</p>
            </div>
          </div>

          {(importError || generateOutline.isError) && (
            <div className="mb-4 p-4 rounded-xl border border-red-200 bg-red-50 flex items-start gap-3">
              <AlertCircle className="w-5 h-5 text-red-500 flex-shrink-0 mt-0.5" />
              <p className="text-sm text-red-700">
                {importError ?? (generateOutline.error as Error)?.message}
              </p>
            </div>
          )}

          {scriptInfo && !showManual ? (
            <div className="rounded-xl border border-primary/40 bg-primary/5 p-6 mb-4">
              <div className="flex items-start justify-between mb-4">
                <div className="flex items-center gap-2">
                  <FileText className="w-5 h-5 text-primary" />
                  <span className="text-sm font-medium text-primary">已识别上传剧本</span>
                </div>
                <CheckCircle2 className="w-5 h-5 text-green-500" />
              </div>

              <h2 className="text-xl font-bold text-foreground mb-1">{scriptInfo.title || "未识别标题"}</h2>
              <p className="text-sm text-muted-foreground mb-4">{scriptInfo.genre || "待补充题材"}</p>

              {scriptInfo.synopsis && (
                <p className="text-sm text-foreground/80 bg-background/60 rounded-lg p-3 mb-4 leading-relaxed">
                  {scriptInfo.synopsis.length > 120 ? `${scriptInfo.synopsis.slice(0, 120)}...` : scriptInfo.synopsis}
                </p>
              )}

              <div className="grid grid-cols-4 gap-3 mb-5">
                {[
                  { icon: <Film className="w-4 h-4" />, label: "集数", value: `${scriptInfo.episodeCount} 集` },
                  { icon: <Users className="w-4 h-4" />, label: "角色", value: `${scriptInfo.characterCount} 个` },
                  { icon: <MapPin className="w-4 h-4" />, label: "场景", value: `${scriptInfo.sceneCount} 个` },
                  { icon: <Sparkles className="w-4 h-4" />, label: "分镜脚本", value: `${scriptInfo.storyboardCount} 条` },
                ].map(({ icon, label, value }) => (
                  <div key={label} className="rounded-lg bg-background border border-border p-3 text-center">
                    <div className="flex justify-center mb-1 text-primary">{icon}</div>
                    <div className="text-lg font-bold text-foreground">{value}</div>
                    <div className="text-xs text-muted-foreground">{label}</div>
                  </div>
                ))}
              </div>

              <button
                onClick={handleImport}
                disabled={importing}
                className="w-full py-3 rounded-xl bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white flex items-center justify-center gap-2 hover:shadow-md transition-all disabled:opacity-50 disabled:cursor-not-allowed"
              >
                {importing ? (
                  <>
                    <Loader2 className="w-5 h-5 animate-spin" />
                    <span>导入中...</span>
                  </>
                ) : (
                  <>
                    <Sparkles className="w-5 h-5" />
                    <span>一键导入大纲 · 分集 · 角色 · 分镜</span>
                    <ArrowRight className="w-4 h-4" />
                  </>
                )}
              </button>

              <button
                onClick={() => setShowManual(true)}
                className="w-full mt-2 py-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
              >
                手动编辑剧本内容，用 AI 生成大纲
              </button>
            </div>
          ) : (
            <div className="rounded-xl border border-border bg-card p-6">
              <div className="flex items-center justify-between mb-3">
                <label className="block text-sm font-medium text-foreground">剧本内容</label>
                <div className="flex items-center gap-2">
                  {loadingScript && (
                    <span className="text-xs text-muted-foreground flex items-center gap-1">
                      <Loader2 className="w-3 h-3 animate-spin" />
                      正在加载上传剧本...
                    </span>
                  )}
                  {!loadingScript && script && (
                    <span className="text-xs text-green-600">已自动带入上传剧本文本</span>
                  )}
                  {scriptInfo && (
                    <button
                      onClick={() => setShowManual(false)}
                      className="text-xs text-primary underline"
                    >
                      返回文档预览
                    </button>
                  )}
                </div>
              </div>

              <textarea
                className="w-full h-64 p-4 rounded-lg border border-border bg-background text-sm text-foreground resize-none focus:outline-none focus:ring-2 focus:ring-primary"
                placeholder="将您的剧本文本粘贴到此处，AI 将自动生成大纲..."
                value={script}
                onChange={(e) => setScript(e.target.value)}
              />
              <p className="text-xs text-muted-foreground mt-2">支持中英文剧本，建议正文长度 500 到 5000 字。</p>

              <button
                onClick={handleGenerate}
                disabled={!script.trim() || generateOutline.isPending}
                className="w-full mt-4 py-3 rounded-xl bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white flex items-center justify-center gap-2 hover:shadow-md transition-all disabled:opacity-50 disabled:cursor-not-allowed"
              >
                {generateOutline.isPending ? (
                  <>
                    <Loader2 className="w-5 h-5 animate-spin" />
                    <span>生成中...</span>
                  </>
                ) : (
                  <>
                    <Sparkles className="w-5 h-5" />
                    <span>AI 生成大纲</span>
                  </>
                )}
              </button>
            </div>
          )}
        </div>
      </div>
    );
  }

  return (
    <div className="h-full overflow-auto bg-background p-6">
      <div className="max-w-5xl mx-auto">
        <div className="mb-6 flex items-start justify-between">
          <div>
            <div className="flex items-center gap-3 mb-2">
              <div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[#5b5ff9] to-[#8b5ff9] flex items-center justify-center">
                <Sparkles className="w-4 h-4 text-white" />
              </div>
              <h1 className="text-2xl font-semibold text-foreground">剧本大纲</h1>
            </div>
            <p className="text-sm text-muted-foreground">AI 已为您生成当前项目的大纲结果。</p>
          </div>
          <button
            onClick={() => setShowManual(true)}
            className="px-4 py-2 rounded-lg border border-border bg-card text-foreground flex items-center gap-2 hover:bg-muted transition-colors text-sm"
          >
            <RefreshCw className="w-4 h-4" />
            重新生成
          </button>
        </div>

        {showManual && (
          <div className="mb-6 rounded-xl border border-border bg-card p-6">
            <label className="block text-sm font-medium text-foreground mb-3">输入新的剧本内容</label>
            <textarea
              className="w-full h-40 p-3 rounded-lg border border-border bg-background text-sm resize-none focus:outline-none focus:ring-2 focus:ring-primary"
              value={script}
              onChange={(e) => setScript(e.target.value)}
            />
            <div className="flex gap-2 mt-3">
              <button
                onClick={handleGenerate}
                disabled={!script.trim() || generateOutline.isPending}
                className="px-4 py-2 rounded-lg bg-primary text-white text-sm disabled:opacity-50 flex items-center gap-2"
              >
                {generateOutline.isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : null}
                {generateOutline.isPending ? "生成中..." : "确认生成"}
              </button>
              <button
                onClick={() => setShowManual(false)}
                className="px-4 py-2 rounded-lg border border-border text-sm"
              >
                取消
              </button>
            </div>
          </div>
        )}

        {generateEpisodes.isError && (
          <div className="mb-4 p-4 rounded-xl border border-red-200 bg-red-50 flex items-start gap-3">
            <AlertCircle className="w-5 h-5 text-red-500 flex-shrink-0 mt-0.5" />
            <p className="text-sm text-red-700">{(generateEpisodes.error as Error)?.message}</p>
          </div>
        )}

        <div className="rounded-xl border border-border bg-card p-6 mb-4">
          <div className="grid grid-cols-2 gap-6 mb-6">
            <div>
              <label className="block text-xs text-muted-foreground mb-2">剧名</label>
              <div className="text-xl font-semibold text-foreground">{outline.title}</div>
            </div>
            <div>
              <label className="block text-xs text-muted-foreground mb-2">类型</label>
              <div className="text-xl font-semibold text-foreground">{outline.genre}</div>
            </div>
          </div>
          <div className="mb-4">
            <label className="block text-xs text-muted-foreground mb-2">故事梗概</label>
            <p className="text-sm text-foreground leading-relaxed">{outline.synopsis}</p>
          </div>
          <div>
            <label className="block text-xs text-muted-foreground mb-2">集数</label>
            <span className="px-3 py-1 rounded-lg bg-accent text-primary text-sm">{outline.episodeCount} 集</span>
          </div>
        </div>

        <button
          onClick={handleContinue}
          disabled={generateEpisodes.isPending}
          className="w-full py-3 rounded-xl bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white flex items-center justify-center gap-2 hover:shadow-md transition-all disabled:opacity-50"
        >
          {generateEpisodes.isPending ? (
            <>
              <Loader2 className="w-5 h-5 animate-spin" />
              <span>生成分集中...</span>
            </>
          ) : (
            <>
              <span>生成分集内容</span>
              <ArrowRight className="w-5 h-5" />
            </>
          )}
        </button>
      </div>
    </div>
  );
}
