import { useCallback, useState } from "react";
import api from "@/shared/api/axios";
import { ApiResponse, unwrap } from "@/shared/api/types";
import { toast } from "sonner";
import { resolveMediaUrl } from "@/shared/lib/media";
import type { Material } from "@/shared/types/material";

/** Probe video duration from a URL using <video> element */
function probeVideoDuration(url: string): Promise<number> {
  return new Promise((resolve) => {
    const video = document.createElement("video");
    video.preload = "metadata";
    video.crossOrigin = "anonymous";
    const cleanup = () => {
      video.removeEventListener("loadedmetadata", onMeta);
      video.removeEventListener("error", onError);
      video.src = "";
    };
    const onMeta = () => {
      const dur = video.duration;
      cleanup();
      resolve(Number.isFinite(dur) ? dur : 0);
    };
    const onError = () => {
      cleanup();
      resolve(0);
    };
    video.addEventListener("loadedmetadata", onMeta);
    video.addEventListener("error", onError);
    video.src = url;
    video.load();
  });
}

interface UseMaterialsOptions {
  selectedMaterials: string[];
  setSelectedMaterials: React.Dispatch<React.SetStateAction<string[]>>;
}

export const useMaterials = ({
  selectedMaterials,
  setSelectedMaterials,
}: UseMaterialsOptions) => {
  const [materials, setMaterials] = useState<Material[]>([]);
  const [fetchError, setFetchError] = useState<string | null>(null);
  const [isFetching, setIsFetching] = useState(false);
  const [lastMaterialCount, setLastMaterialCount] = useState(0);
  const [isUploading, setIsUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploadError, setUploadError] = useState<string | null>(null);

  const fetchMaterials = useCallback(async () => {
    try {
      setFetchError(null);
      setIsFetching(true);

      const { data: res } = await api.get<ApiResponse<{ materials: Material[] }>>(
        `/api/materials?t=${new Date().getTime()}`
      );
      const payload = unwrap(res);
      const nextMaterials = payload.materials || [];
      setMaterials(nextMaterials);
      setLastMaterialCount(nextMaterials.length);

      // Probe video durations in background
      if (nextMaterials.length > 0) {
        Promise.all(
          nextMaterials.map(async (m) => {
            const url = resolveMediaUrl(m.path);
            if (!url) return m;
            const dur = await probeVideoDuration(url);
            return { ...m, duration_sec: dur };
          })
        ).then((enriched) => setMaterials(enriched));
      }

      setSelectedMaterials((prev) => {
        // 保留已选中且仍存在的
        const existingIds = new Set(nextMaterials.map((m) => m.id));
        const kept = prev.filter((id) => existingIds.has(id));
        if (kept.length > 0) return kept;
        // 否则默认选中第一个
        return nextMaterials[0]?.id ? [nextMaterials[0].id] : [];
      });
    } catch (error) {
      console.error("获取素材失败:", error);
      setFetchError(String(error));
    } finally {
      setIsFetching(false);
    }
  }, [setSelectedMaterials]);

  const MAX_MATERIALS = 4;

  const toggleMaterial = useCallback((id: string) => {
    setSelectedMaterials((prev) => {
      if (prev.includes(id)) {
        // 不能取消最后一个
        if (prev.length <= 1) return prev;
        return prev.filter((x) => x !== id);
      }
      if (prev.length >= MAX_MATERIALS) return prev;
      return [...prev, id];
    });
  }, [setSelectedMaterials]);

  const reorderMaterials = useCallback((activeId: string, overId: string) => {
    setSelectedMaterials((prev) => {
      const oldIndex = prev.indexOf(activeId);
      const newIndex = prev.indexOf(overId);
      if (oldIndex === -1 || newIndex === -1) return prev;
      const next = [...prev];
      next.splice(oldIndex, 1);
      next.splice(newIndex, 0, activeId);
      return next;
    });
  }, [setSelectedMaterials]);

  const deleteMaterial = useCallback(async (materialId: string) => {
    if (!confirm("确定要删除这个素材吗？")) return;
    try {
      await api.delete(`/api/materials/${materialId}`);
      fetchMaterials();
      if (selectedMaterials.includes(materialId)) {
        setSelectedMaterials((prev) => {
          const next = prev.filter((id) => id !== materialId);
          return next.length > 0 ? next : [];
        });
      }
    } catch (error) {
      toast.error("删除失败: " + error);
    }
  }, [fetchMaterials, selectedMaterials, setSelectedMaterials]);

  const handleUpload = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    const validTypes = ['.mp4', '.mov', '.avi', '.mkv', '.webm', '.flv', '.wmv', '.m4v', '.ts', '.mts'];
    const ext = file.name.toLowerCase().slice(file.name.lastIndexOf('.'));
    if (!validTypes.includes(ext)) {
      setUploadError('不支持的视频格式');
      return;
    }

    setIsUploading(true);
    setUploadProgress(0);
    setUploadError(null);

    try {
      const formData = new FormData();
      formData.append('file', file);

      await api.post('/api/materials', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
        onUploadProgress: (progressEvent) => {
          if (progressEvent.total) {
            const progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
            setUploadProgress(progress);
          }
        },
      });

      setUploadProgress(100);
      setIsUploading(false);

      // 上传后重新拉列表并自动选中新素材
      const { data: res } = await api.get<ApiResponse<{ materials: Material[] }>>(
        `/api/materials?t=${new Date().getTime()}`
      );
      const payload = unwrap(res);
      const nextMaterials = payload.materials || [];
      setMaterials(nextMaterials);
      setLastMaterialCount(nextMaterials.length);

      // Probe video durations in background
      if (nextMaterials.length > 0) {
        Promise.all(
          nextMaterials.map(async (m) => {
            const url = resolveMediaUrl(m.path);
            if (!url) return m;
            const dur = await probeVideoDuration(url);
            return { ...m, duration_sec: dur };
          })
        ).then((enriched) => setMaterials(enriched));
      }

      // 找出新增素材并默认仅选中新上传项，避免误触发多素材模式
      const oldIds = new Set(materials.map((m) => m.id));
      const newIds = nextMaterials.filter((m) => !oldIds.has(m.id)).map((m) => m.id);
      if (newIds.length > 0) {
        setSelectedMaterials([newIds[0]]);
      } else if (nextMaterials[0]?.id) {
        // 兜底：即使未识别到新增项，也保持单素材默认选择最新一个
        setSelectedMaterials([nextMaterials[0].id]);
      }
    } catch (err: unknown) {
      console.error("Upload failed:", err);
      setIsUploading(false);
      const axiosErr = err as { response?: { data?: { message?: string } }; message?: string };
      const errorMsg = axiosErr.response?.data?.message || axiosErr.message || String(err);
      setUploadError(`上传失败: ${errorMsg}`);
    }

    e.target.value = '';
  }, [materials, setSelectedMaterials]);

  return {
    materials,
    fetchError,
    isFetching,
    lastMaterialCount,
    isUploading,
    uploadProgress,
    uploadError,
    setUploadError,
    fetchMaterials,
    toggleMaterial,
    reorderMaterials,
    deleteMaterial,
    handleUpload,
  };
};
