import { fetchApi } from "@/lib/server-api-util";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { v4 as uuidv4 } from 'uuid';

// 导入子组件
import { ConfirmUpload } from "@/types/upload";
import { View } from "react-native";
import MultiFileUploader from "./multi-file-uploader";
import SingleFileUploader from "./single-file-uploader";
import UploadDropzone from "./upload-dropzone";
import { extractVideoFirstFrame, getVideoDuration } from "./utils/videoUtils";

// 默认允许的文件类型
export const DEFAULT_ALLOWED_FILE_TYPES = ["video/mp4", "video/quicktime", "video/x-msvideo", "video/x-matroska"];
export const DEFAULT_MAX_FILE_SIZE = 500 * 1024 * 1024; // 500MB

// 上传URL响应接口
export interface UploadUrlResponse {
  upload_url: string;
  file_id: string;
}

// 文件状态接口
export interface FileStatus {
  file: File;
  id?: string;
  progress: number;
  error?: string;
  status: 'pending' | 'uploading' | 'success' | 'error';
  url?: string;
  thumbnailUrl?: string; // 添加缩略图URL
}

interface FileUploaderProps {
  onFilesUploaded?: (files: FileStatus[]) => void;
  maxFiles?: number;
  allowMultiple?: boolean;
  disabled?: boolean;
  className?: string;
  allowedFileTypes?: string[]; // 外部传入的允许文件类型
  maxFileSize?: number; // 外部传入的最大文件大小
  thumbnailPropsUrl?: string; // 注册后返回ai处理展示缩略图
}

export default function FileUploader({
  onFilesUploaded,
  maxFiles = 1,
  allowMultiple = false,
  disabled = false,
  className = "",
  allowedFileTypes = DEFAULT_ALLOWED_FILE_TYPES,
  maxFileSize = DEFAULT_MAX_FILE_SIZE,
  thumbnailPropsUrl = ""
}: FileUploaderProps) {
  const { t } = useTranslation();
  const [files, setFiles] = useState<FileStatus[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  // 图片的最小值
  const MIN_IMAGE_SIZE = 300;

  // 校验图片尺寸（异步）
  function validateImageDimensions(file: File): Promise<string | null> {
    return new Promise((resolve) => {
      const img = new window.Image();
      img.onload = () => {
        if (img.width < MIN_IMAGE_SIZE || img.height < MIN_IMAGE_SIZE) {
          resolve(`图片尺寸不能小于${MIN_IMAGE_SIZE}px，当前为${img.width}x${img.height}`);
        } else {
          resolve(null);
        }
      };
      img.onerror = () => resolve("无法读取图片尺寸");
      img.src = URL.createObjectURL(file);
    });
  }
  // 格式化文件大小
  const formatFileSize = (bytes: number): string => {
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
    return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
  };

  // 验证文件
  const validateFile = (file: File): string | null => {
    // 验证文件类型
    if (!allowedFileTypes.includes(file.type)) {
      const errorMsg = t('validation.file.invalidType');
      // addToast({
      //   title: t('fileUploader.invalidFileTitle'),
      //   description: errorMsg,
      //   color: "danger",
      // });
      return errorMsg;
    }

    // 验证文件大小
    // if (file.size > maxFileSize) {
    //   const errorMsg = t('validation.file.tooLarge');
    //   addToast({
    //     title: t('fileUploader.fileTooLargeTitle'),
    //     description: `${errorMsg} ${formatFileSize(maxFileSize)}`,
    //     color: "danger",
    //   });
    //   return errorMsg;
    // }

    return null;
  };

  // 创建缩略图
  const createThumbnail = (file: File): Promise<string> => {
    return new Promise((resolve, reject) => {
      // 如果是图片文件，直接使用图片作为缩略图
      if (file.type.startsWith('image/')) {
        const reader = new FileReader();
        reader.onload = (e) => {
          if (e.target && typeof e.target.result === 'string') {
            resolve(e.target.result);
          } else {
            reject(new Error('图片加载失败'));
          }
        };
        reader.onerror = () => {
          reject(new Error('图片读取失败'));
        };
        reader.readAsDataURL(file);
        return;
      }

      // 如果是视频文件，创建视频缩略图
      const videoUrl = URL.createObjectURL(file);
      const video = document.createElement('video');
      video.src = videoUrl;
      video.crossOrigin = 'anonymous';
      video.muted = true;
      video.preload = 'metadata';

      video.onloadeddata = () => {
        try {
          // 设置视频时间到第一帧
          video.currentTime = 0.1;
        } catch (e) {
          URL.revokeObjectURL(videoUrl);
          reject(e);
        }
      };

      video.onseeked = () => {
        try {
          // 创建canvas并绘制视频帧
          const canvas = document.createElement('canvas');
          canvas.width = video.videoWidth;
          canvas.height = video.videoHeight;
          const ctx = canvas.getContext('2d');

          if (ctx) {
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
            const thumbnailUrl = canvas.toDataURL('image/jpeg', 0.7);
            URL.revokeObjectURL(videoUrl);
            resolve(thumbnailUrl);
          } else {
            reject(new Error('无法创建canvas上下文'));
          }
        } catch (e) {
          URL.revokeObjectURL(videoUrl);
          reject(e);
        }
      };

      video.onerror = () => {
        URL.revokeObjectURL(videoUrl);
        reject(new Error('视频加载失败'));
      };
    });
  };
  // 压缩图片函数
  async function compressImageToFile(
    file: File,
    maxWidth = 600,
    quality = 0.7,
    outputType = 'image/png'
  ): Promise<File> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (event: ProgressEvent<FileReader>) => {
        const target = event.target as FileReader;
        if (!target || !target.result) {
          reject(new Error('Failed to read file'));
          return;
        }
        const img = new Image();
        img.onload = () => {
          // 计算压缩尺寸
          const canvas = document.createElement('canvas');
          let width = img.width;
          let height = img.height;

          if (width > maxWidth) {
            height = Math.round((height * maxWidth) / width);
            width = maxWidth;
          }

          canvas.width = width;
          canvas.height = height;

          // 绘制压缩图片
          const ctx = canvas.getContext('2d');
          if (!ctx) {
            throw new Error('Could not get 2D context from canvas');
          }
          ctx.drawImage(img, 0, 0, width, height);

          // 转为 Blob 并生成 File 对象
          canvas.toBlob(
            (blob: Blob | null) => {
              if (!blob) {
                reject(new Error('Failed to create blob from canvas'));
                return;
              }
              let file_name = uuidv4() + ".png"
              const compressedFile = new File([blob], file_name, {
                type: outputType,
                lastModified: Date.now()
              });
              resolve(compressedFile);
            },
            outputType,
            quality
          );
        };
        img.onerror = reject;
        img.src = target.result as string;
      };
      reader.onerror = reject;
      reader.readAsDataURL(file);
    });
  }
  // 新增素材
  const addMaterial = async (file: string, compressFile: string) => {
    await fetchApi('/material', {
      method: 'POST',
      body: JSON.stringify([{
        "file_id": file,
        "preview_file_id": compressFile
      }])
    }).catch((error) => {
      console.log(error);
    })
  }

  // 上传单个文件
  const uploadFile = async (fileStatus: FileStatus, fileIndex: number, compressedFile: File) => {
    // 创建新的文件状态对象，而不是修改原来的数组
    // 这样可以避免多个异步操作对同一个数组的并发修改
    let currentFileStatus: FileStatus = {
      ...fileStatus,
      status: 'uploading' as const,
      progress: 0
    };

    // 使用函数更新文件状态，确保每次更新都是原子的
    const updateFileStatus = (updates: Partial<FileStatus>) => {
      currentFileStatus = { ...currentFileStatus, ...updates };
      setFiles(prevFiles => {
        const newFiles = [...prevFiles];
        newFiles[fileIndex] = currentFileStatus;
        return newFiles;
      });
    };

    // 初始化上传状态
    updateFileStatus({ status: 'uploading', progress: 0 });

    // 添加小延迟，确保初始状态能被看到
    await new Promise(resolve => setTimeout(resolve, 300));

    try {
      // 获取视频时长
      let metadata = {};
      if (fileStatus.file.type.startsWith('video/')) {
        metadata = {
          duration: (await getVideoDuration(fileStatus.file)).toString()
        }
      }

      // 获取上传URL
      updateFileStatus({ progress: 10 });
      const uploadUrlData = await getUploadUrl(fileStatus.file, metadata);
      const compressedFileData = await getUploadUrl(compressedFile, {})

      // 确保正确更新文件ID
      updateFileStatus({ id: uploadUrlData.file_id, progress: 20 });

      // 上传文件到URL
      await uploadFileToUrl(
        compressedFile,
        compressedFileData.upload_url,
        (progress) => {
          // 将实际进度映射到 60%-90% 区间
          const mappedProgress = 60 + (progress * 0.3);
          updateFileStatus({ progress: Math.round(mappedProgress) });
        }
      );

      await uploadFileToUrl(
        fileStatus.file,
        uploadUrlData.upload_url,
        (progress) => {
          // 将实际进度映射到 60%-90% 区间
          const mappedProgress = 60 + (progress * 0.3);
          updateFileStatus({ progress: Math.round(mappedProgress) });
        }
      );

      // 向服务端confirm上传
      await fetchApi<ConfirmUpload>('/file/confirm-upload', {
        method: 'POST',
        body: JSON.stringify({
          file_id: uploadUrlData.file_id
        })
      });

      await fetchApi<ConfirmUpload>('/file/confirm-upload', {
        method: 'POST',
        body: JSON.stringify({
          file_id: compressedFileData.file_id
        })
      });

      // 等待一些时间再标记为成功
      await new Promise(resolve => setTimeout(resolve, 300));

      // 更新状态为成功
      updateFileStatus({ status: 'success', progress: 100, id: uploadUrlData.file_id });

      await addMaterial(uploadUrlData.file_id, compressedFileData.file_id)
      // 打印最终状态以进行调试
      // console.log('最终文件状态:', currentFileStatus);
      // 调用回调函数
      if (onFilesUploaded) {
        // 使用当前文件状态创建一个新的数组传递给回调函数
        const updatedFiles = [...files];
        updatedFiles[fileIndex] = {
          ...currentFileStatus,
          id: uploadUrlData.file_id, // 确保 ID 正确传递
        };

        // 延迟调用回调函数，确保状态已更新
        setTimeout(() => {
          // console.log('传递给回调的文件:', updatedFiles);
          onFilesUploaded(updatedFiles);
        }, 100);
      }
    } catch (error) {
      console.error('Upload error:', error);
      // 更新状态为错误
      updateFileStatus({
        status: 'error',
        error: error instanceof Error ? error.message : '上传失败'
      });
    }
  };

  // 处理文件选择
  const handleFileSelect = useCallback(async (selectedFiles: FileList | null) => {
    if (!selectedFiles) return;

    setIsUploading(true);

    const newFiles: FileStatus[] = [];

    for (let i = 0; i < selectedFiles.length; i++) {
      const file = selectedFiles[i];
      const error = validateFile(file);
      let dimensionError: string | null = null;
      if (!error && file.type.startsWith('image/')) {
        dimensionError = await validateImageDimensions(file);
      }

      let thumbnailUrl = '';
      // 只在文件验证通过且尺寸合格时创建缩略图
      if (!error && !dimensionError) {
        try {
          // 创建缩略图，支持图片和视频
          thumbnailUrl = await createThumbnail(file);
          newFiles.push({
            file,
            progress: 0,
            error: error ?? undefined,
            status: error ? 'error' : 'pending',
            thumbnailUrl
          });
        } catch (e) {
          console.error('缩略图创建失败:', e);
        }
      } else {
        // 添加警告
        // addToast({
        //   title: t('fileUploader.fileTooSmallTitle'),
        //   description: t('fileUploader.fileTooSmall'),
        //   color: "warning",
        // });
      }
    }

    // 更新文件列表
    setFiles(prev => {
      // 单文件模式下且已有文件时，替换现有文件
      if (maxFiles === 1 && prev.length > 0 && newFiles.length > 0) {
        return [newFiles[0]]; // 只保留新选择的第一个文件
      } else {
        // 多文件模式，合并并限制数量
        const combinedFiles = [...prev, ...newFiles];
        return combinedFiles.length > maxFiles
          ? combinedFiles.slice(0, maxFiles)
          : combinedFiles;
      }
    });

    // 在状态更新后，使用 useEffect 来处理上传
    setIsUploading(false);
  }, [maxFiles]);


  // 获取上传URL
  const getUploadUrl = async (file: File, metadata: { [key: string]: string }): Promise<UploadUrlResponse> => {
    const body = {
      filename: file.name,
      content_type: file.type,
      file_size: file.size,
      metadata
    }
    return await fetchApi<UploadUrlResponse>("/file/generate-upload-url", {
      method: 'POST',
      body: JSON.stringify(body)
    });
  };

  // 上传文件到URL
  const uploadFileToUrl = async (file: File, uploadUrl: string, onProgress: (progress: number) => void): Promise<void> => {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();

      xhr.open('PUT', uploadUrl);
      xhr.setRequestHeader('Content-Type', file.type);

      // 进度监听
      xhr.upload.onprogress = (event) => {
        if (event.lengthComputable) {
          const progress = Math.round((event.loaded / event.total) * 100);
          onProgress(progress);
        }
      };

      xhr.onload = () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve();
        } else {
          reject(new Error(`Upload failed with status ${xhr.status}`));
        }
      };

      xhr.onerror = () => {
        reject(new Error('Network error during upload'));
      };

      xhr.send(file);
    });
  };

  // 移除文件
  const removeFile = (fileToRemove: File) => {
    setFiles(prev => prev.filter(fileStatus => fileStatus.file !== fileToRemove));
  };

  // 清除所有文件
  const clearFiles = () => {
    setFiles([]);
  };

  // 打开文件选择器
  const openFileSelector = () => {
    if (!disabled) {
      if (fileInputRef.current) {
        fileInputRef.current.click();
      } else {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = allowedFileTypes.join(',');
        input.multiple = allowMultiple;
        input.onchange = (e) => handleFileSelect((e.target as HTMLInputElement).files);
        input.click();
      }
    }
  };

  // 使用 useEffect 监听 files 变化，处理待上传的文件
  useEffect(() => {
    const processFiles = async () => {
      // Only process files that are in 'pending' status
      const pendingFiles = files
        .filter(f => f.status === 'pending')
        .filter((fileStatus, index, self) =>
          index === self.findIndex(f => f.file === fileStatus.file)
        ); // Remove duplicates

      if (pendingFiles.length === 0) return;

      // Create a new array with updated status to prevent infinite loops
      setFiles(prevFiles =>
        prevFiles.map(file =>
          pendingFiles.some(pf => pf.file === file.file)
            ? { ...file, status: 'uploading' as const }
            : file
        )
      );

      // Process each file sequentially to avoid race conditions
      for (const fileStatus of pendingFiles) {
        try {
          const fileIndex = files.findIndex(f => f.file === fileStatus.file);
          if (fileIndex === -1) continue;

          let compressedFile: File;
          if (fileStatus.file.type?.includes('video')) {
            const frameFile = await extractVideoFirstFrame(fileStatus.file);
            compressedFile = await compressImageToFile(frameFile, 600, 0.7);
          } else {
            compressedFile = fileStatus.file;
          }

          await uploadFile(
            { ...fileStatus, status: 'uploading' as const },
            fileIndex,
            compressedFile
          );
        } catch (error) {
          console.error('Error processing file:', error);
          setFiles(prevFiles =>
            prevFiles.map(f =>
              f.file === fileStatus.file
                ? {
                  ...f,
                  status: 'error' as const,
                  error: error instanceof Error ? error.message : '处理文件失败'
                }
                : f
            )
          );
        }
      }
    };

    processFiles();
  }, [files]); // Only run when files array changes

  return (
    <View className={className}
      aria-label="文件上传"
    >
      {/* 隐藏的文件输入 */}
      <input
        ref={fileInputRef}
        type="file"
        accept={allowedFileTypes.join(',')}
        multiple={allowMultiple}
        onChange={(e) => handleFileSelect(e.target.files)}
        className="hidden"
      />

      {/* 文件上传区域 - 始终可见 */}
      <View className="space-y-6 h-full">
        {/* 上传区域 */}
        {maxFiles === 1 && files.length === 1 ? (
          /* 单文件模式且已有文件 - 不添加外层的onClick事件 */
          <SingleFileUploader
            file={files[0]}
            onReplace={openFileSelector}
            disabled={disabled}
          />
        ) : thumbnailPropsUrl ? <img
          src={thumbnailPropsUrl}
          className="w-full h-full object-cover"
        /> : (
          /* 多文件模式或无文件 - 只在组件上添加一个onClick事件 */
          <UploadDropzone
            onClick={openFileSelector}
            disabled={disabled}
            allowedFileTypes={allowedFileTypes}
          // maxFileSize={maxFileSize}
          />
        )}

        {/* 文件列表区域 - 仅在多文件模式下显示 */}
        {maxFiles !== 1 && files.length > 0 && (
          <MultiFileUploader
            files={files}
            onRemove={removeFile}
            onClearAll={clearFiles}
            formatFileSize={formatFileSize}
            disabled={disabled}
          />
        )}
      </View>
    </View>
  );
}