import {
  ArrowLeftOutlined,
  CameraOutlined,
  ColumnWidthOutlined,
  CustomerServiceOutlined,
  DeleteOutlined,
  DownloadOutlined,
  EditOutlined,
  FontSizeOutlined,
  InboxOutlined,
  LoadingOutlined,
  PlayCircleOutlined,
  RightOutlined,
  ScissorOutlined,
  SwapOutlined,
  VideoCameraOutlined,
} from "@ant-design/icons";
import { useCallback, useEffect, useRef, useState, type DragEvent } from "react";
import "../../styles/pages/more-tools.css";
import "../../styles/pages/image-workbench.css";
import StudioToolLayout from "../../components/StudioToolLayout";
import type { WebImageWorkbenchTool, WebViewKey } from "../../types";
import { aiGenerationClient } from "../../api/aiGenerationClient";
import { uploadAssetWithProgress } from "../../api/uploadWithProgress";
import { waitForTask } from "../../api/taskSubscription";
import { saveToolTaskState, loadToolTaskState, clearToolTaskState } from "../workbench/toolKeepalive";
import { addToolResultToAssetLibrary, saveToolResultToLocal } from "../workbench/toolResultActions";
import { CheckCircleOutlined, InfoCircleOutlined } from "@ant-design/icons";

interface CharacterMixPageProps {
  isAuthenticated: boolean;
  onOpenMore?: () => void;
  onOpenImageTool?: (tool: WebImageWorkbenchTool) => void;
  onSelectView?: (view: WebViewKey) => void;
}

function CharacterMixPage({
  isAuthenticated,
  onOpenMore,
  onOpenImageTool,
  onSelectView,
}: CharacterMixPageProps) {
  const [characterFile, setCharacterFile] = useState("");
  const [characterPreview, setCharacterPreview] = useState("");
  const [characterDataUrl, setCharacterDataUrl] = useState("");
  const [videoFile, setVideoFile] = useState("");
  const [videoPreview, setVideoPreview] = useState("");
  const [videoDataUrl, setVideoDataUrl] = useState("");
  const [promptInput, setPromptInput] = useState("");
  const [watermark, setWatermark] = useState(false);
  const [checkImage, setCheckImage] = useState(true);
  const [faceHint, setFaceHint] = useState<string | null>(null);
  const faceDetectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const [notice, setNotice] = useState("等待上传角色图和参考视频");
  const [isCreating, setIsCreating] = useState(false);
  const [isDownloadingResult, setIsDownloadingResult] = useState(false);
  const [isSavingResultAsset, setIsSavingResultAsset] = useState(false);
  const [progress, setProgress] = useState(0);
  const [resultUrl, setResultUrl] = useState<string | null>(null);
  const abortRef = useRef(false);
  const taskIdRef = useRef<string | null>(null);
  const [isDragging, setIsDragging] = useState(false);
  const [isCanvasDragging, setIsCanvasDragging] = useState(false);
  const characterInputRef = useRef<HTMLInputElement | null>(null);
  const videoInputRef = useRef<HTMLInputElement | null>(null);

  useEffect(() => {
    return () => {
      if (characterPreview) URL.revokeObjectURL(characterPreview);
    };
  }, [characterPreview]);

  useEffect(() => {
    return () => {
      if (videoPreview) URL.revokeObjectURL(videoPreview);
    };
  }, [videoPreview]);

  useEffect(() => {
    if (faceDetectTimerRef.current) clearTimeout(faceDetectTimerRef.current);
    if (!checkImage || !characterPreview) {
      setFaceHint(null);
      return;
    }
    setFaceHint("analyzing");
    faceDetectTimerRef.current = setTimeout(() => {
      setFaceHint("ready");
    }, 800);
    return () => {
      if (faceDetectTimerRef.current) clearTimeout(faceDetectTimerRef.current);
    };
  }, [checkImage, characterPreview]);

  const keepaliveRestoredRef = useRef(false);

  // Keep-alive: restore saved task on mount
  useEffect(() => {
    if (keepaliveRestoredRef.current) return;
    keepaliveRestoredRef.current = true;
    const saved = loadToolTaskState("charactermix");
    if (!saved || saved.resultUrl) return;
    setIsCreating(true);
    abortRef.current = false;
    void pollTaskUntilDone(saved.taskId).then((result) => {
      setResultUrl(result);
      setNotice(result ? "角色迁移完成" : "已取消");
      setIsCreating(false);
      setProgress(0);
      if (result) {
        saveToolTaskState("charactermix", { taskId: saved.taskId, resultUrl: result, status: "完成", progress: 100 });
      } else {
        clearToolTaskState("charactermix");
      }
    });
  }, []);

  useEffect(() => {
    return () => {
      abortRef.current = true;
    };
  }, []);

  const handleCancel = useCallback(() => {
    abortRef.current = true;
    if (taskIdRef.current) {
      aiGenerationClient.cancelTask(taskIdRef.current).catch(() => {});
      taskIdRef.current = null;
    }
    clearToolTaskState("charactermix");
  }, []);

  const pollTaskUntilDone = useCallback(async (taskId: string): Promise<string | null> => {
    return waitForTask(taskId, {
      abortRef,
      onProgress: (e) => setProgress(e.progress || 0),
    });
  }, []);

  const handleCreateTask = async () => {
    if (isCreating) return;
    if (!characterDataUrl) {
      setNotice("请先上传人物图");
      return;
    }
    if (!videoDataUrl) {
      setNotice("请先上传参考视频");
      return;
    }
    if (!isAuthenticated) {
      setNotice("请先登录后再创建角色迁移任务。");
      return;
    }

    abortRef.current = false;
    setIsCreating(true);
    setProgress(0);
    setResultUrl(null);
    setNotice("正在上传素材...");

    try {
      const [imageAsset, videoAsset] = await Promise.all([
        uploadAssetWithProgress(
          { dataUrl: characterDataUrl, scope: "character-mix", mimeType: "image/png" },
          { onProgress: (p) => setNotice(`上传人物图 ${p}%`) },
        ),
        uploadAssetWithProgress(
          { dataUrl: videoDataUrl, scope: "character-mix", mimeType: "video/mp4" },
          { onProgress: (p) => setNotice(`上传参考视频 ${p}%`) },
        ),
      ]);

      const prompt = promptInput.trim() || "保持角色原有服装和面部特征，动作流畅自然";
      setNotice("正在生成角色迁移视频...");
      const { taskId } = await aiGenerationClient.createVideoTask({
        model: "wan2.2-animate-mix",
        prompt,
        imageUrl: imageAsset.url,
        referenceUrls: [videoAsset.url],
        hasReferenceVideo: true,
        muted: !watermark,
      });
      taskIdRef.current = taskId;
      saveToolTaskState("charactermix", { taskId, status: "running", progress: 0 });

      const result = await pollTaskUntilDone(taskId);
      setResultUrl(result);
      setNotice(result ? "角色迁移完成" : "已取消");
      if (result) {
        saveToolTaskState("charactermix", { taskId, resultUrl: result, status: "完成", progress: 100 });
      } else {
        clearToolTaskState("charactermix");
      }
    } catch (error) {
      setNotice(error instanceof Error ? error.message : "任务创建失败，请稍后重试。");
    } finally {
      setIsCreating(false);
      setProgress(0);
    }
  };

  const handleDownloadResult = async () => {
    if (!resultUrl || isDownloadingResult) return;
    setIsDownloadingResult(true);
    try {
      const status = await saveToolResultToLocal({
        url: resultUrl,
        name: `character-mix-${Date.now()}`,
        type: "video",
        isVideo: true,
        taskId: taskIdRef.current || undefined,
      });
      setNotice(status === "saved" ? "已保存到本地" : "已开始保存到本地");
    } catch (error) {
      setNotice(error instanceof Error ? error.message : "保存本地失败");
    } finally {
      setIsDownloadingResult(false);
    }
  };

  const handleAddResultToAssets = async () => {
    if (!resultUrl || isSavingResultAsset) return;
    setIsSavingResultAsset(true);
    try {
      const status = await addToolResultToAssetLibrary({
        url: resultUrl,
        name: `角色迁移-${Date.now()}`,
        type: "video",
        isVideo: true,
        taskId: taskIdRef.current || undefined,
        description: "从工具盒角色迁移生成的视频。",
        tags: ["工具盒", "角色迁移", "生成视频"],
      });
      setNotice(status === "server" ? "已加入资产库" : "已加入本地资产库");
    } catch (error) {
      setNotice(error instanceof Error ? error.message : "加入资产库失败");
    } finally {
      setIsSavingResultAsset(false);
    }
  };

  const handleDragOver = (e: DragEvent) => { e.preventDefault(); if (e.dataTransfer?.types?.includes("Files")) setIsDragging(true); };
  const handleDragLeave = (e: DragEvent) => { e.preventDefault(); if (!e.currentTarget.contains(e.relatedTarget as Node)) setIsDragging(false); };
  const handleDrop = (e: DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
    const file = e.dataTransfer?.files?.[0];
    if (!file) return;
    if (file.type.startsWith("image/")) {
      if (characterPreview) URL.revokeObjectURL(characterPreview);
      setCharacterFile(file.name);
      setCharacterPreview(URL.createObjectURL(file));
      const reader = new FileReader();
      reader.onload = () => { if (typeof reader.result === "string") setCharacterDataUrl(reader.result); };
      reader.readAsDataURL(file);
      setNotice(`已选择人物图 ${file.name}`);
    } else if (file.type.startsWith("video/")) {
      if (videoPreview) URL.revokeObjectURL(videoPreview);
      setVideoFile(file.name);
      setVideoPreview(URL.createObjectURL(file));
      const reader2 = new FileReader();
      reader2.onload = () => { if (typeof reader2.result === "string") setVideoDataUrl(reader2.result); };
      reader2.readAsDataURL(file);
      setNotice(`已选择参考视频 ${file.name}`);
    }
  };

  const handleCanvasDragOver = (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); if (e.dataTransfer.types.includes("Files")) setIsCanvasDragging(true); };
  const handleCanvasDragLeave = (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); if (e.currentTarget === e.target || !e.currentTarget.contains(e.relatedTarget as Node)) setIsCanvasDragging(false); };
  const handleCanvasDrop = (e: DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsCanvasDragging(false);
    handleDrop(e);
  };

  const handleCanvasClick = () => {
    if (!characterPreview) {
      characterInputRef.current?.click();
    } else if (!videoPreview) {
      videoInputRef.current?.click();
    }
  };

  const clearCharacterAsset = () => {
    if (characterPreview) URL.revokeObjectURL(characterPreview);
    setCharacterFile("");
    setCharacterPreview("");
    setCharacterDataUrl("");
    setFaceHint(null);
    if (characterInputRef.current) characterInputRef.current.value = "";
    setNotice("已移除人物图");
  };

  const clearReferenceVideo = () => {
    if (videoPreview) URL.revokeObjectURL(videoPreview);
    setVideoFile("");
    setVideoPreview("");
    setVideoDataUrl("");
    if (videoInputRef.current) videoInputRef.current.value = "";
    setNotice("已移除参考视频");
  };

  const characterMixSettingsPanel = (
    <div className="studio-panel__section character-mix-settings-panel">
      <div className="studio-panel__section-head">
        <span className="studio-panel__section-title">迁移设置</span>
      </div>
      <div className="studio-panel__section-body">
        <div className="character-mix-prompt-field">
          <div className="studio-label">驱动提示词</div>
          <textarea
            value={promptInput}
            onChange={(e) => setPromptInput(e.target.value)}
            placeholder="保持角色原有服装，动作流畅自然"
            rows={3}
            maxLength={1000}
          />
        </div>
        <div className="studio-toggle-row">
          <div className="studio-toggle-row__copy">
            <span className="studio-toggle-row__title">图像检测</span>
            <span className="studio-toggle-row__desc">检测人物朝向</span>
          </div>
          <button type="button" className={`studio-toggle${checkImage ? " is-on" : ""}`} onClick={() => setCheckImage(!checkImage)}>
            <span className="studio-toggle__thumb" />
          </button>
        </div>
        {checkImage && characterPreview && faceHint && (
          <div className={`character-mix-face-hint character-mix-face-hint--${faceHint}`}>
            {faceHint === "analyzing" ? (
              <>
                <InfoCircleOutlined />
                <span>正在分析人物图像...</span>
              </>
            ) : (
              <>
                <CheckCircleOutlined />
                <span>图像已就绪，将自动检测人物面部朝向</span>
              </>
            )}
          </div>
        )}
        <div className="studio-toggle-row">
          <div className="studio-toggle-row__copy">
            <span className="studio-toggle-row__title">水印输出</span>
            <span className="studio-toggle-row__desc">含水印版本</span>
          </div>
          <button type="button" className={`studio-toggle${watermark ? " is-on" : ""}`} onClick={() => setWatermark(!watermark)}>
            <span className="studio-toggle__thumb" />
          </button>
        </div>
        <button type="button" className="studio-generate-btn" onClick={() => void handleCreateTask()} disabled={isCreating || !characterDataUrl || !videoDataUrl}>
          {isCreating ? <LoadingOutlined /> : <PlayCircleOutlined />}
          {isCreating ? "生成中..." : "开始迁移"}
        </button>
        {resultUrl && (
          <div className="studio-result-actions">
            <button type="button" onClick={() => void handleDownloadResult()} disabled={isDownloadingResult}>
              <DownloadOutlined />
              {isDownloadingResult ? "保存中" : "保存本地"}
            </button>
            <button type="button" onClick={() => void handleAddResultToAssets()} disabled={isSavingResultAsset}>
              <InboxOutlined />
              {isSavingResultAsset ? "加入中" : "加入资产库"}
            </button>
          </div>
        )}
      </div>
    </div>
  );

  return (
    <section className="image-workbench-page character-mix-page" aria-label="角色迁移">
      <header className="image-workbench-topbar">
        <button type="button" className="image-workbench-back-to-more" onClick={onOpenMore}>
          工具盒
        </button>
        <div className="image-workbench-tool-strip" aria-label="功能入口">
          <button type="button" onClick={() => onOpenImageTool?.("workbench")}>
            <EditOutlined />
            图片工作台
          </button>
          <button type="button" onClick={() => onOpenImageTool?.("inpaint")}>
            <ScissorOutlined />
            局部重绘
          </button>
          <button type="button" onClick={() => onOpenImageTool?.("camera")}>
            <CameraOutlined />
            镜头实验室
          </button>
          <button type="button" onClick={() => onSelectView?.("digitalHuman")}>
            <CustomerServiceOutlined />
            数字人
          </button>
          <button type="button" className="is-active">
            <SwapOutlined />
            角色迁移
          </button>
          <button type="button" onClick={() => onSelectView?.("resolutionUpscale")}>
            <ColumnWidthOutlined />
            分辨率提升
          </button>
          <button type="button" onClick={() => onSelectView?.("watermarkRemoval")}>
            <DeleteOutlined />
            去水印
          </button>
          <button type="button" onClick={() => onSelectView?.("subtitleRemoval")}>
            <FontSizeOutlined />
            字幕去除
          </button>
        </div>
      </header>

      <div className="image-workbench-subbar">
        <button type="button" className="image-workbench-icon-btn" aria-label="返回工具盒" onClick={onOpenMore}>
          <ArrowLeftOutlined />
        </button>
        <strong>角色迁移</strong>
        <div className="image-workbench-camera-summary" aria-label="角色迁移状态">
          <strong>{characterFile && videoFile ? "素材已就绪" : "迁移预览"}</strong>
          <span>{characterFile || videoFile ? "人物 + 视频" : "待上传"}</span>
        </div>
        <button type="button" className="image-workbench-icon-btn" aria-label="下一项">
          <RightOutlined />
        </button>
      </div>

      <StudioToolLayout
        noTop
        noRight
        leftPanel={
          <div
            className="character-mix-source-panel"
            onDragOver={handleDragOver}
            onDragLeave={handleDragLeave}
            onDrop={handleDrop}
            style={{ position: "relative" }}
          >
            {isDragging ? (
              <div style={{ position: "absolute", inset: 0, zIndex: 100, display: "flex", alignItems: "center", justifyContent: "center", background: "rgba(0,0,0,0.55)", border: "2px dashed var(--primary, #4a9eff)", borderRadius: 12, pointerEvents: "none" }}>
                <span style={{ fontSize: 18, color: "#fff", fontWeight: 600 }}>释放文件以上传</span>
              </div>
            ) : null}
            <div className="studio-panel__section">
              <div className="studio-panel__section-head">
                <span className="studio-panel__section-title">人物图</span>
                <span className={`studio-panel__section-chip studio-panel__section-chip--${characterFile ? "ready" : "waiting"}`}>
                  {characterFile ? "已就绪" : "待上传"}
                </span>
              </div>
              <div className="studio-panel__section-body">
                <label className={characterFile ? "studio-upload-slot--filled" : "studio-upload-slot--empty"}>
                  <input
                    ref={characterInputRef}
                    type="file"
                    accept="image/*"
                    onChange={(event) => {
                      const file = event.target.files?.[0];
                      if (!file) return;
                      if (characterPreview) URL.revokeObjectURL(characterPreview);
                      setCharacterFile(file.name);
                      setCharacterPreview(URL.createObjectURL(file));
                      const reader = new FileReader();
                      reader.onload = () => {
                        if (typeof reader.result === "string") setCharacterDataUrl(reader.result);
                      };
                      reader.readAsDataURL(file);
                      setNotice(`已选择人物图 ${file.name}`);
                    }}
                  />
                  {characterPreview ? (
                    <img src={characterPreview} alt="" className="studio-upload-slot--filled__thumb" />
                  ) : (
                    <span className="studio-upload-slot--empty__icon">
                      <InboxOutlined />
                    </span>
                  )}
                  <span className="studio-upload-slot--filled__info">
                    <strong>{characterFile || "上传人物图"}</strong>
                    <small>单人正面或半身更稳定</small>
                  </span>
                  {characterPreview ? (
                    <button
                      type="button"
                      className="studio-upload-slot__remove"
                      aria-label="移除人物图"
                      onClick={(event) => {
                        event.preventDefault();
                        event.stopPropagation();
                        clearCharacterAsset();
                      }}
                    >
                      <DeleteOutlined />
                    </button>
                  ) : null}
                </label>
              </div>
            </div>

            <div className="studio-panel__section">
              <div className="studio-panel__section-head">
                <span className="studio-panel__section-title">参考视频</span>
                <span className={`studio-panel__section-chip studio-panel__section-chip--${videoFile ? "ready" : "waiting"}`}>
                  {videoFile ? "已就绪" : "待上传"}
                </span>
              </div>
              <div className="studio-panel__section-body">
                <label className={videoFile ? "studio-upload-slot--filled" : "studio-upload-slot--empty"}>
                  <input
                    ref={videoInputRef}
                    type="file"
                    accept="video/*"
                    onChange={(event) => {
                      const file = event.target.files?.[0];
                      if (!file) return;
                      if (videoPreview) URL.revokeObjectURL(videoPreview);
                      setVideoFile(file.name);
                      setVideoPreview(URL.createObjectURL(file));
                      const reader = new FileReader();
                      reader.onload = () => {
                        if (typeof reader.result === "string") setVideoDataUrl(reader.result);
                      };
                      reader.readAsDataURL(file);
                      setNotice(`已选择参考视频 ${file.name}`);
                    }}
                  />
                  <span className="studio-upload-slot--empty__icon">
                    <VideoCameraOutlined />
                  </span>
                  <span className="studio-upload-slot--filled__info">
                    <strong>{videoFile || "上传参考视频"}</strong>
                    <small>MP4 / MOV / AVI</small>
                  </span>
                  {videoPreview ? (
                    <button
                      type="button"
                      className="studio-upload-slot__remove"
                      aria-label="移除参考视频"
                      onClick={(event) => {
                        event.preventDefault();
                        event.stopPropagation();
                        clearReferenceVideo();
                      }}
                    >
                      <DeleteOutlined />
                    </button>
                  ) : null}
                </label>
              </div>
            </div>
            {characterMixSettingsPanel}
          </div>
        }
        canvas={
          isCreating ? (
            <div className="image-workbench-generating">
              <LoadingOutlined style={{ fontSize: 32 }} />
              <strong>角色迁移中...</strong>
              <div className="image-workbench-progress-bar">
                <div className="image-workbench-progress-fill" style={{ width: `${progress}%` }} />
              </div>
              <span>{progress}%</span>
              <button type="button" className="image-workbench-cancel" onClick={handleCancel}>取消</button>
            </div>
          ) : resultUrl ? (
            <div className="studio-canvas-video">
              <video src={resultUrl} controls playsInline style={{ maxHeight: "100%", maxWidth: "100%", borderRadius: 12 }} />
              {characterPreview && (
                <div className="studio-canvas-pip">
                  <img src={characterPreview} alt="人物图" />
                </div>
              )}
            </div>
          ) : videoPreview ? (
            <div className="studio-canvas-video">
              <video src={videoPreview} controls muted playsInline />
              {characterPreview ? (
                <div className="studio-canvas-pip">
                  <img src={characterPreview} alt="人物图" />
                </div>
              ) : null}
            </div>
          ) : (
            <div
              className={`studio-canvas-ghost${isCanvasDragging ? " is-dragging" : ""}`}
              onClick={handleCanvasClick}
              onDragOver={handleCanvasDragOver}
              onDragLeave={handleCanvasDragLeave}
              onDrop={handleCanvasDrop}
              role="button"
              tabIndex={0}
              onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") handleCanvasClick(); }}
            >
              <div className="studio-canvas-ghost__icon">
                <SwapOutlined />
              </div>
              <div className="studio-canvas-ghost__title">上传人物图与参考视频</div>
              <div className="studio-canvas-ghost__hint">点击或拖拽上传；支持人物图片 (PNG/JPG) 和参考视频 (MP4/MOV/AVI)</div>
            </div>
          )
        }
        statusBar={
          <>
            <span className="studio-status-bar__badge studio-status-bar__badge--idle">就绪</span>
            <span className="studio-status-bar__text">{notice}</span>
          </>
        }
      />
    </section>
  );
}

export default CharacterMixPage;
