/**
 * 剪辑计划编辑器 — V8 原型 1:1 还原
 * 四行布局：顶栏(42px) → 模式栏(48px) → 三栏主体 → 底栏(40px)
 */
import React, { useState, useCallback, useEffect } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";
import { message } from "antd";
import { useQuery } from "@tanstack/react-query";
import type {
  EditingTemplate,
  TemplateCategory,
  TemplateMode,
  SaveTemplatePayload,
} from "@/api/editingPlanner";
import {
  getEditingTemplates,
  getEditingTemplate,
  createEditingTemplate,
  updateEditingTemplate,
  getTemplateCategories,
  generateFromTemplate,
  MODE_LABELS,
} from "@/api/editingPlanner";
import type { EditPlanGeneration, MediaAsset } from "@/api/editPlans";
import {
  getMediaAssets,
  getEditPlanGenerations,
  generateCover,
} from "@/api/editPlans";
import { useUndoRedo } from "./hooks/useUndoRedo";
import type { TaskItem } from "@/api/tasks";
import { createGenerationTask, getTask, retryTask } from "@/api/tasks";
import type { ClipData, ClipType } from "./types";
import {
  ensureDefaultLibrary,
  getAssetsByKind,
  type AssetItem,
} from "@/api/assets";
import { getOrCreateDefaultProject } from "@/api/projects";

import MediaPanel from "./components/MediaPanel";
import PreviewPlayer from "./components/PreviewPlayer";
import TimelinePanel from "./components/TimelinePanel";
import ClipPropertiesPanel from "./components/ClipPropertiesPanel";
import SaveModal from "./components/SaveModal";
import GenerationProgressModal from "./components/GenerationProgressModal";
import type { GenPhase } from "./components/GenerationProgressModal";
import GenerationHistoryModal from "./components/GenerationHistoryModal";
import "./EditingPlanner.css";

/* ──────────── 常量 ──────────── */

const MODE_LIST: { key: TemplateMode; label: string; icon: string }[] = [
  { key: "pip", label: "画中画", icon: "🖼️" },
  { key: "voice_over", label: "人物口播", icon: "🎙️" },
  { key: "one_take", label: "一镜到底", icon: "🎥" },
  { key: "voice_pip", label: "口播+画中画", icon: "🎭" },
];

const COVER_SCHEMES = [
  { key: "ai_frame", label: "AI选帧" },
  { key: "manual", label: "手动选" },
  { key: "upload", label: "上传" },
  { key: "ai_reselect", label: "AI重选" },
];

const FILTER_CATEGORIES = ["全部", "种草", "知识", "日常", "推荐"];

/* ──────────── 组件 ──────────── */

const EditingPlanner: React.FC = () => {
  const [searchParams] = useSearchParams();
  const navigate = useNavigate();
  const urlTemplateId = searchParams.get("templateId") || "";

  /* ── 模板列表 ── */
  const [templates, setTemplates] = useState<EditingTemplate[]>([]);
  const [categories, setCategories] = useState<TemplateCategory[]>([]);
  const [loadingTemplates, setLoadingTemplates] = useState(false);
  const [loadedTemplateId, setLoadedTemplateId] = useState<string | null>(
    urlTemplateId || null,
  );
  const [currentMode, setCurrentMode] = useState<TemplateMode>("pip");

  /* ── 片段（撤销/重做） ── */
  const {
    state: clips,
    set: setClips,
    undo,
    redo,
    canUndo,
    canRedo,
    reset: resetClips,
  } = useUndoRedo<ClipData[]>([]);
  const [selectedClipId, setSelectedClipId] = useState<string | null>(null);

  /* ── AI 操作状态 ── */

  const [aiCoverLoading, setAiCoverLoading] = useState(false);

  /* ── 封面方案 ── */
  const [currentCoverScheme, setCurrentCoverScheme] =
    useState<string>("ai_frame");

  /* ── 左栏筛选 ── */
  const [currentFilter, setCurrentFilter] = useState("全部");
  const [searchQuery, setSearchQuery] = useState("");

  /* ── 标题/字幕/BGM 设置 ── */
  const [titleSettings, setTitleSettings] = useState({
    aiAutoSelect: false,
    title: "",
    position: "top",
    font: "思源黑体",
    size: 24,
    bold: false,
    italic: false,
    stroke: true,
    shadow: true,
    color: "#ffffff",
  });

  const [subtitleSettings, setSubtitleSettings] = useState({
    enabled: true,
    position: "bottom",
    font: "思源黑体",
    size: 16,
    animation: "none",
  });

  const [bgmSettings, setBgmSettings] = useState({
    music: "none",
  });

  /* ── 保存弹窗 ── */
  const [saveModalOpen, setSaveModalOpen] = useState(false);
  const [draftName, setDraftName] = useState("");
  const [draftCategory, setDraftCategory] = useState("");
  const [draftTags, setDraftTags] = useState("");
  const [saveLoading, setSaveLoading] = useState(false);

  /* ── 生成弹窗 ── */
  const [genModalOpen, setGenModalOpen] = useState(false);
  const [genPhase, setGenPhase] = useState<GenPhase>("setup");
  const [genTask, setGenTask] = useState<TaskItem | null>(null);
  const [genSubmitting, setGenSubmitting] = useState(false);
  const [voiceoverDuration, setVoiceoverDuration] = useState<number | null>(
    null,
  );

  /* ── 素材库 ── */
  const [mediaAssets, setMediaAssets] = useState<MediaAsset[]>([]);
  const [selectedAssetIds, setSelectedAssetIds] = useState<string[]>([]);

  const handleAssetSelect = (ids: string[]) => {
    setSelectedAssetIds(ids);
  };

  /* ── 生成历史 ── */
  const [genHistoryOpen, setGenHistoryOpen] = useState(false);
  const [genHistory, setGenHistory] = useState<EditPlanGeneration[]>([]);
  const [genHistoryLoading, setGenHistoryLoading] = useState(false);

  /* ── 播放 ── */
  const [isPlaying, setIsPlaying] = useState(false);

  /* ── 配音素材（queryKey 与 VoiceMaterialLibrary 共享缓存） ── */
  const voiceMaterialsQuery = useQuery({
    queryKey: ["assets", "voice"],
    queryFn: async () => {
      const project = await getOrCreateDefaultProject();
      await ensureDefaultLibrary({ project_id: project.id, kind: "voice" });
      const assets = await getAssetsByKind("voice");
      return assets;
    },
    staleTime: 30_000,
  });
  const voiceMaterials: AssetItem[] = voiceMaterialsQuery.data ?? [];

  /** 为片段选择配音素材 */
  const handleClipVoiceSelect = useCallback(
    (clipId: string, asset: AssetItem | null) => {
      setClips((prev) =>
        prev.map((c) =>
          c.id === clipId
            ? {
                ...c,
                voice_asset_id: asset?.id ?? undefined,
                voice_file_url: asset?.file_url ?? undefined,
              }
            : c,
        ),
      );
    },
    [setClips],
  );

  /* ──────────── 加载 ──────────── */

  /**
   * 并行加载模板列表、分类、素材库
   * 首次挂载时调用，三个接口无依赖关系，用 Promise.all 并发
   */
  const loadTemplates = useCallback(async () => {
    setLoadingTemplates(true);
    try {
      const [tpls, cats, assets] = await Promise.all([
        getEditingTemplates(),
        getTemplateCategories(),
        getMediaAssets(),
      ]);
      setTemplates(tpls);
      setCategories(cats);
      setMediaAssets(assets);
    } catch {
      message.error("加载模板失败");
    } finally {
      setLoadingTemplates(false);
    }
  }, []);

  useEffect(() => {
    loadTemplates();
  }, [loadTemplates]);

  /**
   * 加载模板详情并初始化片段列表
   * 将后端 segments 映射为前端 ClipData，取 duration_min/max 均值作为默认时长
   * 同时还原标题/字幕/BGM 配置
   */
  useEffect(() => {
    if (!loadedTemplateId) return;
    getEditingTemplate(loadedTemplateId)
      .then((tpl) => {
        if (!tpl) return;
        setCurrentMode(tpl.mode);
        const mapped: ClipData[] = tpl.segments.map((seg, idx) => ({
          id: seg.id || `seg-${idx}`,
          template_segment_id: seg.id || `seg-${idx}`,
          type: (seg.material_type === "voiceover"
            ? "voice"
            : "pip") as ClipType,
          duration: (seg.duration_min + seg.duration_max) / 2,
          startOffset: 0,
          script_text: "",
          order: seg.segment_order,
        }));
        resetClips(mapped);

        setTitleSettings((prev) => ({
          ...prev,
          aiAutoSelect: tpl.title_config.ai_auto_select,
          title: tpl.title_config.content,
          position: tpl.title_config.position,
          font: tpl.title_config.font_preset,
          size: tpl.title_config.font_size,
          color: tpl.title_config.font_color || "#ffffff",
        }));
        setSubtitleSettings({
          enabled: tpl.subtitle_config.enabled,
          position: tpl.subtitle_config.position,
          font: tpl.subtitle_config.font,
          size: tpl.subtitle_config.size,
          animation: tpl.subtitle_config.animation,
        });
        setBgmSettings({
          music: tpl.bgm_config.music_id || "none",
        });
        setDraftName(tpl.name);
        setDraftCategory(tpl.category);
        setDraftTags(tpl.tags.join(", "));
      })
      .catch(() => message.error("加载模板详情失败"));
  }, [loadedTemplateId, resetClips]);

  /* ──────────── 计算 ──────────── */

  const currentTemplate = templates.find((t) => t.id === loadedTemplateId);
  const totalDuration = clips.reduce((sum, c) => sum + c.duration, 0);
  const selectedClip = clips.find((c) => c.id === selectedClipId) || null;

  const filteredTemplates = templates.filter((t) => {
    if (currentFilter !== "全部" && t.category !== currentFilter) return false;
    if (
      searchQuery &&
      !t.name.toLowerCase().includes(searchQuery.toLowerCase())
    )
      return false;
    return true;
  });

  /* ──────────── 事件 ──────────── */

  const handleLoadTemplate = (templateId: string) => {
    setLoadedTemplateId(templateId);
    setSelectedClipId(null);
  };

  const handleModeChange = (mode: TemplateMode) => {
    setCurrentMode(mode);
  };

  const handleClipSelect = (clipId: string) => {
    setSelectedClipId(clipId);
  };

  const handleClipReorder = (fromIdx: number, toIdx: number) => {
    setClips((prev) => {
      const updated = [...prev];
      const [moved] = updated.splice(fromIdx, 1);
      updated.splice(toIdx, 0, moved);
      return updated.map((c, i) => ({ ...c, order: i }));
    });
  };

  const handleClipRemove = (clipId: string) => {
    setClips((prev) => prev.filter((c) => c.id !== clipId));
    if (selectedClipId === clipId) setSelectedClipId(null);
  };

  const handleClipUpdate = (clipId: string, data: Partial<ClipData>) => {
    setClips((prev) =>
      prev.map((c) => (c.id === clipId ? { ...c, ...data } : c)),
    );
  };

  /**
   * 添加片段（不绑定任何素材）
   * 片段 = 时间规划 + 类型标记
   */
  const handleAddClip = useCallback(
    (type: ClipType, duration: number) => {
      const newClip: ClipData = {
        id: `clip-${Date.now()}`,
        type,
        duration,
        startOffset: 0,
        order: clips.length,
      };
      setClips((prev) => [...prev, newClip]);
    },
    [clips.length, setClips],
  );

  /* AI 封面生成 */
  const handleAiGenerateCover = async (
    coverType: "ai_frame" | "ai_regenerate",
  ) => {
    if (!loadedTemplateId) return;
    const assetIds = selectedAssetIds;
    if (assetIds.length === 0) {
      message.warning("请先在素材库中选择素材");
      return;
    }
    setAiCoverLoading(true);
    try {
      await generateCover(loadedTemplateId, {
        asset_ids: assetIds,
        cover_type: coverType,
      });
      setCurrentCoverScheme(
        coverType === "ai_frame" ? "ai_frame" : "ai_reselect",
      );
      message.success("AI 封面生成成功");
    } catch {
      message.error("AI 封面生成失败");
    } finally {
      setAiCoverLoading(false);
    }
  };

  /* 保存 — 无论是否已加载模板，都打开保存弹窗；未加载时创建新模板 */
  const handleOpenSaveModal = () => {
    setSaveModalOpen(true);
  };

  const handleSave = async () => {
    if (!draftName.trim()) {
      message.warning("请输入模板名称");
      return;
    }
    setSaveLoading(true);
    try {
      const payload: SaveTemplatePayload = {
        name: draftName,
        mode: currentMode,
        category: draftCategory,
        tags: draftTags
          .split(",")
          .map((t) => t.trim())
          .filter(Boolean),
        title_config: {
          ai_auto_select: titleSettings.aiAutoSelect,
          content: titleSettings.title,
          font_preset: titleSettings.font,
          font_color: titleSettings.color,
          font_size: titleSettings.size,
          position: titleSettings.position,
        },
        subtitle_config: {
          enabled: subtitleSettings.enabled,
          position: subtitleSettings.position,
          font: subtitleSettings.font,
          color: "#ffffff",
          size: subtitleSettings.size,
          animation: subtitleSettings.animation,
        },
        bgm_config: {
          enabled: bgmSettings.music !== "none",
          music_id: bgmSettings.music,
        },
        estimated_duration: totalDuration,
        segments: clips.map((c, i) => ({
          segment_order: i,
          duration_min: Math.max(1, c.duration - 2),
          duration_max: c.duration + 2,
          material_type: c.type === "voice" ? "voiceover" : "video",
        })),
      };
      if (loadedTemplateId) {
        await updateEditingTemplate(loadedTemplateId, payload);
      } else {
        await createEditingTemplate(payload);
      }
      message.success(loadedTemplateId ? "模板保存成功" : "模板创建成功");
      setSaveModalOpen(false);
      loadTemplates();
    } catch {
      message.error("保存失败");
    } finally {
      setSaveLoading(false);
    }
  };

  /**
   * 跳转到一键生成页面
   * 通过 URL SearchParams 传递 edit_plan_id 和完整 planConfig（JSON 序列化）
   * 一键生成页面从 params 解析配置，无需重复请求接口
   */
  const handleGoToGenerate = () => {
    const planConfig = {
      title_config: {
        ai_auto_select: titleSettings.aiAutoSelect,
        content: titleSettings.title,
        position: titleSettings.position,
        font_preset: titleSettings.font,
        font_color: titleSettings.color,
        font_size: titleSettings.size,
        bold: titleSettings.bold,
        italic: titleSettings.italic,
        stroke: titleSettings.stroke,
        shadow: titleSettings.shadow,
      },
      subtitle_config: {
        enabled: subtitleSettings.enabled,
        position: subtitleSettings.position,
        font: subtitleSettings.font,
        size: subtitleSettings.size,
        animation: subtitleSettings.animation,
      },
      bgm_config: {
        enabled: bgmSettings.music !== "none",
        music_id: bgmSettings.music,
      },
      mode: currentMode,
      total_duration: totalDuration,
      segments: clips.map((c, i) => ({
        order: i,
        material_type: c.type === "voice" ? "voiceover" : "video",
        duration: c.duration,
        template_segment_id: c.template_segment_id,
        script_text: c.script_text,
        voice_asset_id: c.voice_asset_id,
        voice_file_url: c.voice_file_url,
      })),
    };
    const params = new URLSearchParams();
    if (loadedTemplateId) {
      params.set("edit_plan_id", loadedTemplateId);
    }
    params.set("plan_config", JSON.stringify(planConfig));
    navigate(`/app/generate?${params.toString()}`);
  };

  /**
   * 创建生成任务（两步）
   * 1. generateFromTemplate — 通知后端基于模板生成视频
   * 2. createGenerationTask — 创建任务记录，返回精简响应
   *    再用 getTask 查询完整 TaskItem 供轮询使用
   */
  const handleGenerate = async () => {
    if (!loadedTemplateId) return;
    setGenSubmitting(true);
    try {
      await generateFromTemplate(loadedTemplateId, {
        voiceover_duration: voiceoverDuration || totalDuration,
      });
      // 收集所有 voice 类型片段的配音素材 ID
      const voiceIds = clips
        .filter((c) => c.type === "voice" && c.voice_asset_id)
        .map((c) => c.voice_asset_id as string);
      const res = await createGenerationTask({
        template_id: loadedTemplateId,
        asset_ids: [],
        title_ids: [],
        voice_ids: voiceIds,
      });
      /* 创建接口返回的是精简响应，需查询完整 TaskItem 用于轮询 */
      const task = await getTask(res.id);
      setGenTask(task);
      setGenPhase("progress");
      message.info("生成任务已创建");
    } catch {
      message.error("创建生成任务失败");
    } finally {
      setGenSubmitting(false);
    }
  };

  /**
   * 轮询生成任务状态（每 3 秒）
   * 仅在 genPhase === "progress" 且有任务 ID 时启动
   * 任务完成/失败时自动停止轮询
   */
  useEffect(() => {
    if (genPhase !== "progress" || !genTask?.id) return;
    const timer = setInterval(async () => {
      try {
        const t = await getTask(genTask.id);
        setGenTask(t);
        if (t.status === "completed") {
          setGenPhase("completed");
          clearInterval(timer);
        } else if (t.status === "failed") {
          setGenPhase("failed");
          clearInterval(timer);
        }
      } catch {
        /* ignore */
      }
    }, 3000);
    return () => clearInterval(timer);
  }, [genPhase, genTask?.id]);

  const handleRetry = async () => {
    if (!genTask?.id) return;
    setGenSubmitting(true);
    try {
      const t = await retryTask(genTask.id);
      setGenTask(t);
      setGenPhase("progress");
    } catch {
      message.error("重试失败");
    } finally {
      setGenSubmitting(false);
    }
  };

  const handleCancelGen = () => {
    setGenModalOpen(false);
    setGenPhase("setup");
    setGenTask(null);
    setVoiceoverDuration(null);
  };

  /* 查看生成历史 */
  const handleViewGenHistory = async () => {
    if (!loadedTemplateId) {
      message.warning("请先加载一个模板");
      return;
    }
    setGenHistoryOpen(true);
    setGenHistoryLoading(true);
    try {
      const items = await getEditPlanGenerations(loadedTemplateId);
      setGenHistory(items);
    } catch {
      message.error("加载生成历史失败");
    } finally {
      setGenHistoryLoading(false);
    }
  };

  /* ──────────── 渲染 ──────────── */

  return (
    <div className="ep-v8-root">
      {/* ═══ 第1行：顶栏 42px ═══ */}
      <div className="ep-top-bar">
        <div className="ep-top-bar-left">
          <span className="ep-logo">✂️</span>
          <span className="ep-app-title">小虾剪辑编排器</span>
          <span className="ep-divider">|</span>
          <span className="ep-template-name">
            {currentTemplate?.name || "未选择模板"}
          </span>
        </div>
        <div className="ep-top-bar-right">
          <button
            className="ep-btn ep-btn-secondary"
            onClick={undo}
            disabled={!canUndo}
            title="撤销 (Ctrl+Z)"
          >
            ⬅️ 撤销
          </button>
          <button
            className="ep-btn ep-btn-secondary"
            onClick={redo}
            disabled={!canRedo}
            title="重做 (Ctrl+Shift+Z)"
          >
            ➡️ 重做
          </button>
          <button
            className="ep-btn ep-btn-secondary"
            onClick={handleOpenSaveModal}
          >
            💾 保存模板
          </button>
          <button
            className="ep-btn ep-btn-primary"
            onClick={handleGoToGenerate}
          >
            🎬 使用此模板生成
          </button>
        </div>
      </div>

      {/* ═══ 第2行：模式栏 56px（V21风格）═══ */}
      <div className="ep-mode-bar">
        <span className="ep-mode-bar-label">剪辑模式：</span>
        {MODE_LIST.map((m) => (
          <button
            key={m.key}
            className={`ep-mode-btn ${currentMode === m.key ? "active" : ""}`}
            onClick={() => handleModeChange(m.key)}
          >
            <span className="ep-mode-icon">{m.icon}</span>
            <span className="ep-mode-label">{m.label}</span>
          </button>
        ))}
      </div>

      {/* ═══ 第3行：三栏主体 ═══ */}
      <div className="ep-main-body">
        {/* 左栏 220px：模板列表 */}
        <MediaPanel
          templates={filteredTemplates}
          loading={loadingTemplates}
          searchQuery={searchQuery}
          currentFilter={currentFilter}
          filterCategories={FILTER_CATEGORIES}
          loadedTemplateId={loadedTemplateId}
          onLoadTemplate={handleLoadTemplate}
          onSearchChange={setSearchQuery}
          onFilterChange={setCurrentFilter}
          mediaAssets={mediaAssets}
          onAssetSelect={handleAssetSelect}
          selectedAssetIds={selectedAssetIds}
        />

        {/* 中栏 flex-1 */}
        <div className="ep-center-col">
          {/* 上半部：视频预览 + 封面预览 */}
          <PreviewPlayer
            clips={clips}
            selectedClipId={selectedClipId}
            isPlaying={isPlaying}
            currentCoverScheme={currentCoverScheme}
            coverSchemes={COVER_SCHEMES}
            aiCoverLoading={aiCoverLoading}
            titleSettings={titleSettings}
            subtitleSettings={subtitleSettings}
            onClipSelect={handleClipSelect}
            onCoverSchemeChange={setCurrentCoverScheme}
            onPlayPause={() => setIsPlaying(!isPlaying)}
            onAiGenerateCover={handleAiGenerateCover}
          />

          {/* 下半部：水平时间线 */}
          <TimelinePanel
            clips={clips}
            selectedClipId={selectedClipId}
            currentMode={currentMode}
            onClipSelect={handleClipSelect}
            onClipReorder={handleClipReorder}
            onClipRemove={handleClipRemove}
            onAddClip={handleAddClip}
          />
        </div>

        {/* 右栏 260px：设置面板 */}
        <ClipPropertiesPanel
          selectedClip={selectedClip}
          titleSettings={titleSettings}
          subtitleSettings={subtitleSettings}
          bgmSettings={bgmSettings}
          clipsCount={clips.length}
          totalDuration={totalDuration}
          currentMode={currentMode}
          onTitleSettingsChange={(partial) =>
            setTitleSettings((prev) => ({ ...prev, ...partial }))
          }
          onSubtitleSettingsChange={(partial) =>
            setSubtitleSettings((prev) => ({ ...prev, ...partial }))
          }
          onBgmSettingsChange={(partial) =>
            setBgmSettings((prev) => ({ ...prev, ...partial }))
          }
          onClipUpdate={handleClipUpdate}
          voiceMaterials={voiceMaterials}
          voiceMaterialsLoading={voiceMaterialsQuery.isLoading}
          onRefreshVoiceMaterials={() => voiceMaterialsQuery.refetch()}
          onClipVoiceSelect={handleClipVoiceSelect}
        />
      </div>

      {/* ═══ 第4行：底栏 40px ═══ */}
      <div className="ep-status-bar">
        <div className="ep-status-left">
          <span>📋 片段: {clips.length}</span>
          <span className="ep-status-sep">|</span>
          <span>⏱️ 总时长: {totalDuration.toFixed(1)}s</span>
        </div>
        <div className="ep-status-right">
          <span>🎬 {MODE_LABELS[currentMode]}</span>
          <span className="ep-status-sep">|</span>
          <span>📐 模板片段: {currentTemplate?.segments.length || 0}</span>
          <span className="ep-status-sep">|</span>
          <button className="ep-status-link" onClick={handleViewGenHistory}>
            📋 生成历史
          </button>
        </div>
      </div>

      {/* ═══ 弹窗 ═══ */}
      <SaveModal
        open={saveModalOpen}
        loading={saveLoading}
        isUpdate={!!loadedTemplateId}
        draftName={draftName}
        draftCategory={draftCategory}
        draftTags={draftTags}
        categories={categories}
        estimatedDuration={totalDuration}
        onNameChange={setDraftName}
        onCategoryChange={setDraftCategory}
        onTagsChange={setDraftTags}
        onSave={handleSave}
        onCancel={() => setSaveModalOpen(false)}
      />

      <GenerationProgressModal
        open={genModalOpen}
        phase={genPhase}
        voiceoverDuration={voiceoverDuration}
        estimatedDuration={totalDuration}
        onDurationChange={setVoiceoverDuration}
        onGenerate={handleGenerate}
        task={genTask}
        submitting={genSubmitting}
        onCancel={handleCancelGen}
        onRetry={handleRetry}
        onClose={handleCancelGen}
      />

      {/* ═══ 生成历史弹窗 ═══ */}
      <GenerationHistoryModal
        open={genHistoryOpen}
        loading={genHistoryLoading}
        history={genHistory}
        onClose={() => setGenHistoryOpen(false)}
      />
    </div>
  );
};

export default EditingPlanner;
