import {
  CameraOutlined,
  CustomerServiceOutlined,
  DeleteOutlined,
  DownloadOutlined,
  EditOutlined,
  FileImageOutlined,
  FolderAddOutlined,
  FontSizeOutlined,
  HighlightOutlined,
  LinkOutlined,
  SwapOutlined,
  VideoCameraOutlined,
} from "@ant-design/icons";
import { useCallback, useEffect, useRef, useState, type CSSProperties } from "react";
import { aiGenerationClient } from "../../api/aiGenerationClient";
import { waitForTask } from "../../api/taskSubscription";
import { saveToolTaskState, loadToolTaskState, clearToolTaskState } from "../workbench/toolKeepalive";
import { getServerBaseUrl, isServerRequestError } from "../../api/serverConnection";
import { summarizeUrl, formatFileSize, fileToDataUrl } from "../../utils/toolPageUtils";
import TaskStatusBar from "../../components/TaskStatusBar";
import { addToolResultToAssetLibrary, saveToolResultToLocal } from "../workbench/toolResultActions";
import type { WebImageWorkbenchTool, WebViewKey } from "../../types";

interface SubtitleRegionPreset {
  id: string;
  label: string;
  desc: string;
  by: number;
  bh: number;
}

const regionPresets: SubtitleRegionPreset[] = [
  { id: "bottom", label: "底部字幕", desc: "最常见的字幕位置", by: 0.75, bh: 0.25 },
  { id: "bottom-narrow", label: "底部单行", desc: "仅底部一小条区域", by: 0.85, bh: 0.15 },
  { id: "top", label: "顶部字幕", desc: "顶部弹幕或标题区域", by: 0, bh: 0.2 },
  { id: "full", label: "全屏扫描", desc: "去除画面中所有文字", by: 0, bh: 1 },
];

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

function formatCreateTaskError(error: unknown): string {
  if (isServerRequestError(error) && error.status === 404) {
    const baseUrl = getServerBaseUrl() || window.location.origin;
    return `当前连接的服务端 ${baseUrl} 还没有部署 /api/ai/video/erase-subtitles 接口，请更新并重启服务端后再试`;
  }
  return error instanceof Error ? error.message : "字幕去除任务创建失败，请稍后重试";
}

function SubtitleRemovalPage({
  isAuthenticated = false,
  onOpenMore,
  onOpenImageTool,
  onSelectView,
}: SubtitleRemovalPageProps) {
  const fileInputRef = useRef<HTMLInputElement>(null);
  const pollRunRef = useRef(0);
  const cancelRef = useRef(false);
  const [sourceName, setSourceName] = useState("");
  const [sourceFile, setSourceFile] = useState<File | null>(null);
  const [sourceUrl, setSourceUrl] = useState("");
  const [sourcePreview, setSourcePreview] = useState("");
  const [resultUrl, setResultUrl] = useState("");
  const [activePreset, setActivePreset] = useState("bottom");
  const [status, setStatus] = useState("上传视频后点击开始去除字幕");
  const [activeTaskId, setActiveTaskId] = useState("");
  const [taskProgress, setTaskProgress] = useState(0);
  const [isProcessing, setIsProcessing] = useState(false);
  const [isDownloading, setIsDownloading] = useState(false);
  const [isSavingAsset, setIsSavingAsset] = useState(false);
  const activeTaskIdRef = useRef(activeTaskId);
  activeTaskIdRef.current = activeTaskId;
  const keepaliveRestoredRef = useRef(false);

  // Keep-alive: restore saved task on mount
  useEffect(() => {
    if (keepaliveRestoredRef.current) return;
    keepaliveRestoredRef.current = true;
    const saved = loadToolTaskState("subtitle");
    if (!saved || saved.resultUrl) return;
    setSourceName(saved.sourceName || "");
    setSourceUrl(saved.sourceUrl || "");
    setIsProcessing(true);
    cancelRef.current = false;
    pollRunRef.current += 1;
    void waitForTaskResult(saved.taskId).catch(() => {});
  }, []);

  useEffect(() => {
    return () => {
      pollRunRef.current += 1;
      cancelRef.current = true;
    };
  }, []);

  const clearSource = () => {
    if (sourcePreview.startsWith("blob:")) URL.revokeObjectURL(sourcePreview);
    setSourceName("");
    setSourceFile(null);
    setSourceUrl("");
    setSourcePreview("");
    setResultUrl("");
    setActiveTaskId("");
    setTaskProgress(0);
    setStatus("已清空素材");
  };

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;
    if (sourcePreview.startsWith("blob:")) URL.revokeObjectURL(sourcePreview);
    setSourceName(file.name);
    setSourceFile(file);
    setSourceUrl("");
    setSourcePreview(URL.createObjectURL(file));
    setResultUrl("");
    setActiveTaskId("");
    setTaskProgress(0);
    setStatus(`已导入 ${file.name}`);
    event.currentTarget.value = "";
  };

  const handleFileDrop = (event: React.DragEvent) => {
    event.preventDefault();
    const file = Array.from(event.dataTransfer.files).find((f) => f.type.startsWith("video/"));
    if (!file) return;
    if (sourcePreview.startsWith("blob:")) URL.revokeObjectURL(sourcePreview);
    setSourceName(file.name);
    setSourceFile(file);
    setSourceUrl("");
    setSourcePreview(URL.createObjectURL(file));
    setResultUrl("");
    setActiveTaskId("");
    setTaskProgress(0);
    setStatus(`已导入 ${file.name}`);
  };

  const handleImportUrl = () => {
    const normalized = sourceUrl.trim();
    if (!/^https?:\/\//i.test(normalized)) {
      setStatus("请输入可访问的 HTTP/HTTPS 视频 URL");
      return;
    }
    if (sourcePreview.startsWith("blob:")) URL.revokeObjectURL(sourcePreview);
    setSourceFile(null);
    setSourceName(summarizeUrl(normalized));
    setSourcePreview(normalized);
    setResultUrl("");
    setActiveTaskId("");
    setTaskProgress(0);
    setStatus(`已导入 URL：${summarizeUrl(normalized)}`);
  };

  const getSourceGenerationUrl = async () => {
    if (!sourceFile) return sourcePreview;
    setStatus(`正在上传 ${sourceFile.name}，${formatFileSize(sourceFile.size)}`);
    const uploaded = await aiGenerationClient.uploadAsset({
      dataUrl: await fileToDataUrl(sourceFile),
      name: sourceFile.name,
      mimeType: sourceFile.type || "video/mp4",
    });
    return uploaded.signedUrl || uploaded.url;
  };

  const waitForTaskResult = async (taskId: string) => {
    const runId = ++pollRunRef.current;
    setActiveTaskId(taskId);
    setTaskProgress(5);
    saveToolTaskState("subtitle", { taskId, sourceName, sourceUrl, status: `任务 ${taskId}`, progress: 5 });

    await waitForTask(taskId, {
      abortRef: cancelRef,
      onProgress: (e) => {
        if (pollRunRef.current !== runId) return;
        const progress = Math.max(0, Math.min(100, Math.trunc(e.progress || 0)));
        setTaskProgress(progress);
        setStatus(`任务 ${taskId} ${e.status}，进度 ${progress}%`);
        if (e.status === "completed" && e.resultUrl) {
          setResultUrl(e.resultUrl);
          setStatus("字幕去除完成");
          setTaskProgress(100);
          clearToolTaskState("subtitle");
          saveToolTaskState("subtitle", { taskId, resultUrl: e.resultUrl, resultPreview: e.resultUrl, sourceName, sourceUrl, status: "完成", progress: 100 });
        }
      },
    });

    if (cancelRef.current) throw new Error("已取消");
    if (pollRunRef.current !== runId) throw new Error("当前任务已被新任务替换");
  };

  const handleCancel = useCallback(() => {
    cancelRef.current = true;
    if (activeTaskId) {
      aiGenerationClient.cancelTask(activeTaskId).catch(() => {});
    }
    setIsProcessing(false);
    setStatus("已取消");
    clearToolTaskState("subtitle");
  }, [activeTaskId]);

  const handleDownload = async () => {
    if (!resultUrl || isDownloading) return;
    setIsDownloading(true);
    try {
      await saveToolResultToLocal({
        url: resultUrl,
        name: `subtitle-removed-${Date.now()}`,
        type: "video",
        isVideo: true,
        taskId: activeTaskId || undefined,
        tags: ["工具盒", "去字幕", "生成视频"],
      });
      setStatus("下载完成");
    } catch (error) {
      setStatus(error instanceof Error ? error.message : "下载失败");
    } finally {
      setIsDownloading(false);
    }
  };

  const handleSaveToAssets = async () => {
    if (!resultUrl || isSavingAsset) return;
    setIsSavingAsset(true);
    try {
      const status = await addToolResultToAssetLibrary({
        url: resultUrl,
        name: `subtitle-removed-${Date.now()}.mp4`,
        description: "工具盒去字幕生成结果",
        type: "video",
        isVideo: true,
        taskId: activeTaskId || undefined,
        tags: ["工具盒", "去字幕", "生成视频"],
      });
      setStatus(status === "server" ? "已加入资产库" : "已加入本地资产库");
    } catch (error) {
      setStatus(error instanceof Error ? error.message : "加入资产库失败");
    } finally {
      setIsSavingAsset(false);
    }
  };

  const handleStart = async () => {
    if (!isAuthenticated) {
      setStatus("请先登录后再创建字幕去除任务");
      return;
    }
    if (!sourcePreview) {
      setStatus("请先上传需要去除字幕的视频");
      return;
    }
    if (isProcessing) return;

    setIsProcessing(true);
    setResultUrl("");
    setTaskProgress(0);
    cancelRef.current = false;
    try {
      const generationUrl = await getSourceGenerationUrl();
      setStatus(`素材已就绪：${summarizeUrl(generationUrl)}，正在提交任务`);
      const preset = regionPresets.find((p) => p.id === activePreset) || regionPresets[0];
      const result = await aiGenerationClient.createEraseSubtitlesTask({
        videoUrl: generationUrl,
        bx: 0,
        by: preset.by,
        bw: 1,
        bh: preset.bh,
      });
      await waitForTaskResult(result.taskId);
    } catch (error) {
      setStatus(formatCreateTaskError(error));
    } finally {
      setIsProcessing(false);
    }
  };

  return (
    <section className="image-workbench-page subtitle-removal-page">
      <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")}>
            <HighlightOutlined />
            局部重绘
          </button>
          <button type="button" onClick={() => onOpenImageTool?.("camera")}>
            <CameraOutlined />
            镜头实验室
          </button>
          <button type="button" onClick={() => onSelectView?.("digitalHuman")}>
            <CustomerServiceOutlined />
            数字人
          </button>
          <button type="button" onClick={() => onSelectView?.("characterMix")}>
            <SwapOutlined />
            角色迁移
          </button>
          <button type="button" onClick={() => onSelectView?.("resolutionUpscale")}>
            <VideoCameraOutlined />
            分辨率提升
          </button>
          <button type="button" onClick={() => onSelectView?.("watermarkRemoval")}>
            <DeleteOutlined />
            去水印
          </button>
          <button type="button" className="is-active">
            <FontSizeOutlined />
            字幕去除
          </button>
        </div>
      </header>

      <div className="image-workbench-subbar">
        <button type="button" className="image-workbench-icon-btn" aria-label="返回工具盒" onClick={onOpenMore}>
          <FontSizeOutlined />
        </button>
        <strong>字幕去除</strong>
      </div>

      <main className="image-workbench-layout image-workbench-layout--camera subtitle-removal-layout">
        <aside className="image-workbench-panel image-workbench-panel--left">
          <section className="image-workbench-control-card">
            <div className="image-workbench-section-title">
              <h3>视频素材</h3>
              <span>{sourcePreview ? "已上传" : "待上传"}</span>
            </div>
            <input
              ref={fileInputRef}
              type="file"
              accept="video/mp4"
              onChange={handleFileChange}
            />
            <div className="image-workbench-upload-shell" onDragOver={(e) => e.preventDefault()} onDrop={handleFileDrop}>
              <button type="button" className="image-workbench-upload" onClick={() => fileInputRef.current?.click()}>
                <FileImageOutlined />
                <strong>{sourceName || "拖拽或选择视频"}</strong>
                <span>仅支持 MP4，最大 1GB，最高 1080P</span>
              </button>
              {sourcePreview ? (
                <button type="button" className="image-workbench-upload-remove" aria-label="删除素材" onClick={clearSource}>
                  ×
                </button>
              ) : null}
            </div>
            <div className="image-workbench-url-row">
              <label>
                <LinkOutlined />
                <input
                  value={sourceUrl}
                  placeholder="粘贴视频 URL（不含中文字符）"
                  onChange={(event) => setSourceUrl(event.target.value)}
                />
              </label>
              <button type="button" onClick={handleImportUrl}>导入</button>
            </div>
          </section>

          <section className="image-workbench-control-card">
            <h3>字幕位置</h3>
            <div className="subtitle-removal-presets">
              {regionPresets.map((preset) => (
                <button
                  key={preset.id}
                  type="button"
                  className={`subtitle-removal-preset${activePreset === preset.id ? " is-active" : ""}`}
                  onClick={() => setActivePreset(preset.id)}
                >
                  <div className="subtitle-removal-preset__visual">
                    <div
                      className="subtitle-removal-preset__region"
                      style={{ "--region-top": `${preset.by * 100}%`, "--region-height": `${preset.bh * 100}%` } as CSSProperties}
                    />
                  </div>
                  <strong>{preset.label}</strong>
                  <span>{preset.desc}</span>
                </button>
              ))}
            </div>
          </section>

          <div className="image-workbench-actions">
            <button type="button" className="image-workbench-primary" onClick={() => void handleStart()} disabled={isProcessing}>
              <DeleteOutlined />
              {isProcessing ? "处理中" : "开始去除字幕"}
            </button>
            {isProcessing && (
              <button type="button" className="image-workbench-cancel" onClick={handleCancel} style={{ marginTop: 6 }}>
                取消
              </button>
            )}
          </div>
        </aside>

        <section className="image-workbench-canvas image-workbench-canvas--camera subtitle-removal-canvas" aria-label="字幕去除画布">
          {sourcePreview ? (
            <div className="subtitle-removal-preview">
              <div className="subtitle-removal-preview__video-wrap">
                <video src={sourcePreview} controls />
                {!resultUrl && (
                  <div
                    className="subtitle-removal-preview__region-overlay"
                    style={{
                      "--region-top": `${(regionPresets.find((p) => p.id === activePreset) || regionPresets[0]).by * 100}%`,
                      "--region-height": `${(regionPresets.find((p) => p.id === activePreset) || regionPresets[0]).bh * 100}%`,
                    } as CSSProperties}
                  />
                )}
              </div>
              {resultUrl && (
                <div className="subtitle-removal-preview__video-wrap">
                  <h4>去除字幕后</h4>
                  <video src={resultUrl} controls />
                  <div className="subtitle-removal-preview__actions">
                    <button type="button" onClick={() => void handleSaveToAssets()} disabled={isSavingAsset}>
                      <FolderAddOutlined />
                      {isSavingAsset ? "加入中" : "加入资产库"}
                    </button>
                    <button type="button" onClick={() => void handleDownload()} disabled={isDownloading}>
                      <DownloadOutlined />
                      {isDownloading ? "保存中" : "保存本地"}
                    </button>
                  </div>
                </div>
              )}
            </div>
          ) : (
            <div className="image-workbench-empty-canvas">
              <DeleteOutlined style={{ fontSize: 48, opacity: 0.2 }} />
              <p>上传视频后在此预览</p>
            </div>
          )}
        </section>
      </main>

      <TaskStatusBar taskId={activeTaskId} status={status} progress={taskProgress} idleLabel="字幕去除" />
    </section>
  );
}

export default SubtitleRemovalPage;
