import React, { useState, useCallback } from 'react';
import { Button } from '@d8d/shared-ui-components/components/ui/button';
import { Card, CardContent } from '@d8d/shared-ui-components/components/ui/card';
import { Progress } from '@d8d/shared-ui-components/components/ui/progress';
import { Badge } from '@d8d/shared-ui-components/components/ui/badge';
import { toast } from 'sonner';
import { Upload, X, CheckCircle, Loader2, FileText } from 'lucide-react';
import { uploadMinIOWithPolicy, MinioProgressEvent } from '../utils/minio';

export 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;
  /** 上传模式：拖放模式或传统模式 */
  uploadMode?: 'dragdrop' | 'traditional';
  /** 是否显示已上传文件列表 */
  showUploadList?: boolean;
  /** 已上传文件列表标题 */
  uploadListTitle?: string;
  /** 组件尺寸模式 */
  size?: 'default' | 'compact' | 'minimal';
  /** 显示模式：卡片模式或完整模式 */
  displayMode?: 'full' | 'card';
}

// 定义上传文件状态
interface UploadFile {
  uid: string;
  name: string;
  size: number;
  type?: string;
  status: 'uploading' | 'success' | 'error';
  percent: number;
  error?: string;
  url?: string;
}

const MinioUploader: React.FC<MinioUploaderProps> = ({
  uploadPath = '/',
  accept,
  maxSize = 1000, // 默认最大1000MB (1GB)
  multiple = false,
  onUploadSuccess,
  onUploadError,
  buttonText = '点击或拖拽上传文件',
  tipText = '支持单文件或多文件上传，单个文件大小不超过1000MB',
  uploadMode = 'dragdrop',
  showUploadList = true,
  uploadListTitle = '上传进度',
  size = 'default',
  displayMode = 'full'
}) => {
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const [dragActive, setDragActive] = useState(false);

  // 根据尺寸模式获取样式配置
  const getSizeConfig = () => {
    switch (size) {
      case 'minimal':
        return {
          container: 'p-3',
          icon: 'h-8 w-8',
          title: 'text-sm',
          description: 'text-xs',
          button: 'h-8 px-3 text-xs',
          spacing: 'space-y-2',
          fileList: 'space-y-2',
          cardPadding: 'p-3',
          progressHeight: 'h-1'
        };
      case 'compact':
        return {
          container: 'p-4',
          icon: 'h-10 w-10',
          title: 'text-base',
          description: 'text-sm',
          button: 'h-9 px-4 text-sm',
          spacing: 'space-y-3',
          fileList: 'space-y-3',
          cardPadding: 'p-4',
          progressHeight: 'h-2'
        };
      default:
        return {
          container: 'p-6',
          icon: 'h-12 w-12',
          title: 'text-lg',
          description: 'text-sm',
          button: 'h-10 px-4',
          spacing: 'space-y-4',
          fileList: 'space-y-4',
          cardPadding: 'p-6',
          progressHeight: 'h-2'
        };
    }
  };

  // 处理上传进度
  const handleProgress = useCallback((uid: string, event: MinioProgressEvent) => {
    setFileList(prev =>
      prev.map(item => {
        if (item.uid === uid) {
          return {
            ...item,
            status: event.stage === 'error' ? 'error' : 'uploading',
            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',
            percent: 100,
            url: result.fileUrl,
          };
        }
        return item;
      })
    );

    // toast.success(`文件 "${file.name}" 上传成功`);
    onUploadSuccess?.(result.fileKey, result.fileUrl, file);
  }, [onUploadSuccess]);

  // 处理上传失败
  const handleError = useCallback((uid: string, error: Error, file: File) => {
    setFileList(prev =>
      prev.map(item => {
        if (item.uid === uid) {
          return {
            ...item,
            status: 'error',
            percent: 0,
            error: error.message || '上传失败'
          };
        }
        return item;
      })
    );

    // toast.error(`文件 "${file.name}" 上传失败: ${error.message}`);
    onUploadError?.(error, file);
  }, [onUploadError]);

  // 自定义上传逻辑
  const handleUpload = async (file: File) => {
    const uid = Date.now().toString() + Math.random().toString(36).substring(2, 11);

    // 添加到文件列表
    setFileList(prev => [
      ...prev,
      {
        uid,
        name: file.name,
        size: file.size,
        type: file.type,
        status: 'uploading',
        percent: 0,
      }
    ]);

    try {
      // 验证文件大小
      const fileSizeMB = file.size / (1024 * 1024);
      if (fileSizeMB > maxSize) {
        throw new Error(`文件大小超过 ${maxSize}MB 限制`);
      }

      // 调用minio上传方法
      const result = await uploadMinIOWithPolicy(
        uploadPath,
        file,
        file.name,
        {
          onProgress: (event) => handleProgress(uid, event),
          signal: new AbortController().signal
        }
      );

      handleComplete(uid, result, file);
    } catch (error) {
      handleError(uid, error instanceof Error ? error : new Error('未知错误'), file);
    }
  };

  // 处理文件选择
  const handleFileSelect = (files: FileList) => {
    if (!files || files.length === 0) return;

    const fileArray = Array.from(files);

    if (!multiple && fileArray.length > 1) {
      toast.error('不支持多文件上传');
      return;
    }

    fileArray.forEach(file => handleUpload(file));
  };

  // 处理拖拽
  const handleDrag = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();

    if (e.type === 'dragenter' || e.type === 'dragover') {
      setDragActive(true);
    } else if (e.type === 'dragleave') {
      setDragActive(false);
    }
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);

    const files = e.dataTransfer.files;
    handleFileSelect(files);
  };

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

  // 渲染上传状态
  const renderUploadStatus = (item: UploadFile) => {
    switch (item.status) {
      case 'uploading':
        return (
          <div className="flex items-center gap-2">
            <Loader2 className="h-4 w-4 animate-spin" />
            <span className="text-sm">{Math.round(item.percent)}%</span>
          </div>
        );
      case 'success':
        return (
          <div className="flex items-center gap-2">
            <CheckCircle className="h-4 w-4 text-green-500" />
            <Badge variant="outline" className="bg-green-50 text-green-700 border-green-200">
              上传成功
            </Badge>
          </div>
        );
      case 'error':
        return (
          <div className="flex items-center gap-2">
            <div className="h-4 w-4 text-red-500">×</div>
            <Badge variant="outline" className="bg-red-50 text-red-700 border-red-200">
              {item.error || '上传失败'}
            </Badge>
          </div>
        );
      default:
        return null;
    }
  };

  // 渲染文件图标
  const renderFileIcon = (type?: string, iconSize: 'small' | 'normal' = 'normal') => {
    const sizeClass = iconSize === 'small' ? 'h-4 w-4' : 'h-8 w-8';

    if (type?.startsWith('image/')) {
      return <FileText className={`${sizeClass} text-blue-500`} />;
    } else if (type?.startsWith('video/')) {
      return <FileText className={`${sizeClass} text-red-500`} />;
    } else if (type?.startsWith('audio/')) {
      return <FileText className={`${sizeClass} text-purple-500`} />;
    } else if (type?.includes('pdf')) {
      return <FileText className={`${sizeClass} text-red-500`} />;
    } else if (type?.includes('word')) {
      return <FileText className={`${sizeClass} text-blue-600`} />;
    } else if (type?.includes('excel') || type?.includes('sheet')) {
      return <FileText className={`${sizeClass} text-green-500`} />;
    } else {
      return <FileText className={`${sizeClass} text-gray-500`} />;
    }
  };

  const sizeConfig = getSizeConfig();

  // 卡片模式渲染
  if (displayMode === 'card') {
    return (
      <div className="h-full flex items-center justify-center">
        <button
          type="button"
          className={`flex flex-col items-center justify-center w-full h-full text-muted-foreground hover:text-primary transition-colors cursor-pointer
            ${size === 'minimal' ? 'text-xs' : 'text-sm'}`}
          onClick={() => {
            const input = document.createElement('input');
            input.type = 'file';
            input.accept = accept || '';
            input.multiple = multiple;
            input.onchange = (e) => {
              const files = (e.target as HTMLInputElement).files;
              if (files) handleFileSelect(files);
            };
            input.click();
          }}
        >
          <Upload className={`${size === 'minimal' ? 'h-6 w-6 mb-1' : 'h-8 w-8 mb-2'}`} />
          <span>{buttonText}</span>
        </button>
      </div>
    );
  }

  return (
    <div className={sizeConfig.spacing}>
      {/* 上传区域 - 根据模式显示不同界面 */}
      {uploadMode === 'dragdrop' ? (
        <div
          className={`relative border-2 border-dashed rounded-lg transition-all ${
            dragActive
              ? 'border-primary bg-primary/5'
              : 'border-gray-300 hover:border-primary/50'
          } ${sizeConfig.container}`}
          onDragEnter={handleDrag}
          onDragLeave={handleDrag}
          onDragOver={handleDrag}
          onDrop={handleDrop}
        >
          <div className={`flex flex-col items-center justify-center ${sizeConfig.spacing}`}>
            <Upload className={`${sizeConfig.icon} ${dragActive ? 'text-primary' : 'text-gray-400'}`} />
            <div className="text-center">
              <p className={`${sizeConfig.title} font-medium`}>{buttonText}</p>
              {size !== 'minimal' && (
                <p className={`${sizeConfig.description} text-gray-500 mt-1`}>{tipText}</p>
              )}
            </div>
            <Button
              type="button"
              variant="outline"
              size={size === 'minimal' ? 'sm' : size === 'compact' ? 'sm' : 'default'}
              onClick={() => {
                const input = document.createElement('input');
                input.type = 'file';
                input.accept = accept || '';
                input.multiple = multiple;
                input.onchange = (e) => {
                  const files = (e.target as HTMLInputElement).files;
                  if (files) handleFileSelect(files);
                };
                input.click();
              }}
            >
              <Upload className="h-4 w-4 mr-2" />
              选择文件
            </Button>
          </div>
        </div>
      ) : (
        <Card>
          <CardContent className={sizeConfig.cardPadding}>
            <div className={`flex flex-col items-center justify-center ${sizeConfig.spacing}`}>
              <Upload className={`${sizeConfig.icon} text-gray-400`} />
              <div className="text-center">
                <p className={`${sizeConfig.title} font-medium`}>{buttonText}</p>
                {size !== 'minimal' && (
                  <p className={`${sizeConfig.description} text-gray-500 mt-1`}>{tipText}</p>
                )}
              </div>
              <Button
                type="button"
                variant="outline"
                size={size === 'minimal' ? 'sm' : size === 'compact' ? 'sm' : 'default'}
                onClick={() => {
                  const input = document.createElement('input');
                  input.type = 'file';
                  input.accept = accept || '';
                  input.multiple = multiple;
                  input.onchange = (e) => {
                    const files = (e.target as HTMLInputElement).files;
                    if (files) handleFileSelect(files);
                  };
                  input.click();
                }}
              >
                <Upload className="h-4 w-4 mr-2" />
                选择文件
              </Button>
            </div>
          </CardContent>
        </Card>
      )}

      {/* 上传进度列表 */}
      {showUploadList && fileList.length > 0 && (
        <Card>
          <CardContent className={sizeConfig.cardPadding}>
            <h3 className={`${sizeConfig.title} font-semibold mb-3`}>{uploadListTitle}</h3>
            <div className={sizeConfig.fileList}>
              {fileList.map(item => (
                <div key={item.uid} className={`flex items-center space-x-3 p-3 border rounded-lg ${size === 'minimal' ? 'text-sm' : ''}`}>
                  <div className="flex-shrink-0">
                    {renderFileIcon(item.type, size === 'minimal' ? 'small' : 'normal')}
                  </div>
                  <div className="flex-1 min-w-0">
                    <div className="flex justify-between items-center mb-1">
                      <p className={`${size === 'minimal' ? 'text-xs' : 'text-sm'} font-medium truncate`}>{item.name}</p>
                      <div className="flex items-center space-x-1">
                        {renderUploadStatus(item)}
                        <Button
                          variant="ghost"
                          size={size === 'minimal' ? 'icon' : 'sm'}
                          onClick={() => handleRemove(item.uid)}
                          disabled={item.status === 'uploading'}
                          className={size === 'minimal' ? 'h-6 w-6' : ''}
                        >
                          <X className={size === 'minimal' ? 'h-3 w-3' : 'h-4 w-4'} />
                        </Button>
                      </div>
                    </div>
                    {item.status === 'uploading' && (
                      <div className="space-y-1">
                        <Progress value={item.percent} className={sizeConfig.progressHeight} />
                        {size !== 'minimal' && (
                          <p className={`${sizeConfig.description} text-gray-500`}>
                            {Math.round(item.percent)}% - {formatFileSize(item.size * (item.percent / 100))} / {formatFileSize(item.size)}
                          </p>
                        )}
                      </div>
                    )}
                  </div>
                </div>
              ))}
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
};

// 辅助函数：格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 Bytes';
  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

export default MinioUploader;