import React, { useState, useCallback } from 'react';
import { Upload, Progress, message, Tag, Space, Typography, Button } from 'antd';
import { UploadOutlined, CloseOutlined, CheckCircleOutlined, SyncOutlined } from '@ant-design/icons';
import { App } from 'antd';
import type { UploadFile, UploadProps } from 'antd';
import type { RcFile } from 'rc-upload/lib/interface';
import type { UploadFileStatus } from 'antd/es/upload/interface';
import type { UploadRequestOption } from 'rc-upload/lib/interface';
import { uploadMinIOWithPolicy, MinioProgressEvent } from '@/client/utils/minio';

interface MinioUploaderProps {
  /** 上传路径 */
  uploadPath: string;
  /** 允许的文件类型，如['image/*', '.pdf'] */
  accept?: string;
  /** 最大文件大小(MB) */
  maxSize?: number;
  /** 是否允许多文件上传 */
  multiple?: boolean;
  /** 上传成功回调 */
  onUploadSuccess?: (fileKey: string, fileUrl: string, file: File) => void;
  /** 上传失败回调 */
  onUploadError?: (error: Error, file: File) => void;
  /** 自定义上传按钮文本 */
  buttonText?: string;
  /** 自定义提示文本 */
  tipText?: string;
}


const MinioUploader: React.FC<MinioUploaderProps> = ({
  uploadPath = '/',
  accept,
  maxSize = 500, // 默认最大500MB
  multiple = false,
  onUploadSuccess,
  onUploadError,
  buttonText = '点击或拖拽上传文件',
  tipText = '支持单文件或多文件上传，单个文件大小不超过500MB'
}) => {
  const { message: antdMessage } = App.useApp();
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const [uploadingFiles, setUploadingFiles] = useState<Set<string>>(new Set());

  // 处理上传进度
  const handleProgress = useCallback((uid: string, event: MinioProgressEvent) => {
    setFileList(prev => 
      prev.map(item => {
        if (item.uid === uid) {
          return {
            ...item,
            status: event.stage === 'error' ? ('error' as UploadFileStatus) : ('uploading' as UploadFileStatus),
            percent: event.progress,
            error: event.stage === 'error' ? event.message : undefined
          };
        }
        return item;
      })
    );
  }, []);

  // 处理上传成功
  const handleComplete = useCallback((uid: string, result: { fileKey: string; fileUrl: string }, file: File) => {
    setFileList(prev => 
      prev.map(item => {
        if (item.uid === uid) {
          return {
            ...item,
            status: 'success' as UploadFileStatus,
            percent: 100,
            response: { fileKey: result.fileKey },
            url: result.fileUrl,
          };
        }
        return item;
      })
    );
    
    setUploadingFiles(prev => {
      const newSet = new Set(prev);
      newSet.delete(uid);
      return newSet;
    });
    
    antdMessage.success(`文件 "${file.name}" 上传成功`);
    onUploadSuccess?.(result.fileKey, result.fileUrl, file);
  }, [antdMessage, onUploadSuccess]);

  // 处理上传失败
  const handleError = useCallback((uid: string, error: Error, file: File) => {
    setFileList(prev => 
      prev.map(item => {
        if (item.uid === uid) {
          return {
            ...item,
            status: 'error' as UploadFileStatus,
            percent: 0,
            error: error.message || '上传失败'
          };
        }
        return item;
      })
    );
    
    setUploadingFiles(prev => {
      const newSet = new Set(prev);
      newSet.delete(uid);
      return newSet;
    });
    
    antdMessage.error(`文件 "${file.name}" 上传失败: ${error.message}`);
    onUploadError?.(error, file);
  }, [antdMessage, onUploadError]);

  // 自定义上传逻辑
  const customRequest = async (options: UploadRequestOption) => {
    const { file, onSuccess, onError } = options;
    const rcFile = file as RcFile;
    const uid = rcFile.uid;
    
    // 添加到文件列表
    setFileList(prev => [
      ...prev.filter(item => item.uid !== uid),
      {
        uid,
        name: rcFile.name,
        size: rcFile.size,
        type: rcFile.type,
        lastModified: rcFile.lastModified,
        lastModifiedDate: new Date(rcFile.lastModified),
        status: 'uploading' as UploadFileStatus,
        percent: 0,
      }
    ]);
    
    // 添加到上传中集合
    setUploadingFiles(prev => new Set(prev).add(uid));
    
    try {
      // 调用minio上传方法
      const result = await uploadMinIOWithPolicy(
        uploadPath,
        options.file as unknown as File,
        rcFile.name,
        {
          onProgress: (event) => handleProgress(uid, event),
          signal: new AbortController().signal
        }
      );
      
      handleComplete(uid, result, rcFile as unknown as File);
      onSuccess?.({}, rcFile);
    } catch (error) {
      handleError(uid, error instanceof Error ? error : new Error('未知错误'), rcFile as unknown as File);
      onError?.(error instanceof Error ? error : new Error('未知错误'));
    }
  };

  // 处理文件移除
  const handleRemove = (uid: string) => {
    setFileList(prev => prev.filter(item => item.uid !== uid));
  };

  // 验证文件大小
  const beforeUpload = (file: File) => {
    const fileSizeMB = file.size / (1024 * 1024);
    if (fileSizeMB > maxSize!) {
      message.error(`文件 "${file.name}" 大小超过 ${maxSize}MB 限制`);
      return false;
    }
    return true;
  };

  // 渲染上传状态
  const renderUploadStatus = (item: UploadFile) => {
    switch (item.status) {
      case 'uploading':
        return (
          <Space>
            <SyncOutlined spin size={12} />
            <span>{item.percent}%</span>
          </Space>
        );
      case 'done':
        return (
          <Space>
            <CheckCircleOutlined style={{ color: '#52c41a' }} size={12} />
            <Tag color="success">上传成功</Tag>
          </Space>
        );
      case 'error':
        return (
          <Space>
            <CloseOutlined style={{ color: '#ff4d4f' }} size={12} />
            <Tag color="error">{item.error || '上传失败'}</Tag>
          </Space>
        );
      default:
        return null;
    }
  };

  return (
    <div className="minio-uploader">
      <Upload.Dragger
        name="files"
        accept={accept}
        multiple={multiple}
        customRequest={customRequest}
        beforeUpload={beforeUpload}
        showUploadList={false}
        disabled={uploadingFiles.size > 0 && !multiple}
      >
        <div className="flex flex-col items-center justify-center p-6 border-2 border-dashed border-gray-300 rounded-md transition-all hover:border-primary">
          <UploadOutlined style={{ fontSize: 24, color: '#1890ff' }} />
          <Typography.Text className="mt-2">{buttonText}</Typography.Text>
          <Typography.Text type="secondary" className="mt-1">
            {tipText}
          </Typography.Text>
        </div>
      </Upload.Dragger>

      {/* 上传进度列表 */}
      {fileList.length > 0 && (
        <div className="mt-4 space-y-3">
          {fileList.map(item => (
            <div key={item.uid} className="flex items-center p-3 border rounded-md">
              <div className="flex-1 min-w-0">
                <div className="flex justify-between items-center mb-1">
                  <Typography.Text ellipsis className="max-w-xs">
                    {item.name}
                  </Typography.Text>
                  <div className="flex items-center space-x-2">
                    {renderUploadStatus(item)}
                    <Button
                      type="text"
                      size="small"
                      icon={<CloseOutlined />}
                      onClick={() => handleRemove(item.uid)}
                      disabled={item.status === 'uploading'}
                    />
                  </div>
                </div>
                {item.status === 'uploading' && (
                  <Progress 
                    percent={item.percent}
                    size="small" 
                    status={item.percent === 100 ? 'success' : undefined}
                  />
                )}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

export default MinioUploader;