import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { fileClient } from '@/client/api';
import type { InferResponseType } from 'hono/client';
import { Eye, FileText, Image as ImageIcon } from 'lucide-react';
import { Skeleton } from '@/client/components/ui/skeleton';
import { Card, CardContent } from '@/client/components/ui/card';
import { Badge } from '@/client/components/ui/badge';
import { Button } from '@/client/components/ui/button';
import { toast } from 'sonner';

// 定义文件类型
type FileItem = InferResponseType<typeof fileClient[':id']['$get'], 200>;

interface FilePreviewItemProps {
  file: FileItem;
  size: 'small' | 'medium' | 'large';
  index?: number;
  total?: number;
  onClick?: (file: FileItem) => void;
}

const FilePreviewItem: React.FC<FilePreviewItemProps> = ({ 
  file, 
  size, 
  index, 
  total, 
  onClick 
}) => {
  const getSize = () => {
    switch (size) {
      case 'small':
        return { width: 45, height: 45 };
      case 'medium':
        return { width: 80, height: 80 };
      case 'large':
        return { width: 120, height: 120 };
      default:
        return { width: 80, height: 80 };
    }
  };

  const { width, height } = getSize();
  const isImage = file.type?.startsWith('image/');
  const isVideo = file.type?.startsWith('video/');

  const handlePreview = () => {
    if (onClick) {
      onClick(file);
    } else if (isImage || isVideo) {
      window.open(file.fullUrl, '_blank');
    } else {
      toast.warning('该文件类型不支持预览');
    }
  };

  // 获取文件图标
  const getFileIcon = (type?: string) => {
    if (!type) return <FileText className="h-8 w-8 text-gray-400" />;
    
    if (type.startsWith('image/')) {
      return <ImageIcon className="h-8 w-8 text-blue-500" />;
    } else if (type.startsWith('video/')) {
      return <FileText className="h-8 w-8 text-red-500" />;
    } else if (type.startsWith('audio/')) {
      return <FileText className="h-8 w-8 text-purple-500" />;
    } else if (type.includes('pdf')) {
      return <FileText className="h-8 w-8 text-red-500" />;
    } else if (type.includes('word')) {
      return <FileText className="h-8 w-8 text-blue-600" />;
    } else if (type.includes('excel') || type.includes('sheet')) {
      return <FileText className="h-8 w-8 text-green-500" />;
    } else {
      return <FileText className="h-8 w-8 text-gray-500" />;
    }
  };

  // 获取文件类型标签
  const getFileTypeBadge = (type: string) => {
    if (type.startsWith('image/')) {
      return { text: '图片', color: 'bg-blue-100 text-blue-800' };
    } else if (type.startsWith('video/')) {
      return { text: '视频', color: 'bg-red-100 text-red-800' };
    } else if (type.startsWith('audio/')) {
      return { text: '音频', color: 'bg-purple-100 text-purple-800' };
    } else if (type.includes('pdf')) {
      return { text: 'PDF', color: 'bg-red-100 text-red-800' };
    } else if (type.includes('word')) {
      return { text: '文档', color: 'bg-blue-100 text-blue-800' };
    } else if (type.includes('excel') || type.includes('sheet')) {
      return { text: '表格', color: 'bg-green-100 text-green-800' };
    } else {
      return { text: '文件', color: 'bg-gray-100 text-gray-800' };
    }
  };

  return (
    <div
      className="relative group cursor-pointer"
      style={{ width, height }}
      onClick={handlePreview}
    >
      {/* 文件预览容器 */}
      <div className={`
        relative overflow-hidden rounded-lg border transition-all duration-200
        ${isImage ? 'border-gray-200' : 'border-gray-300 bg-gray-50'}
        group-hover:shadow-md group-hover:border-primary
      `}>
        {isImage ? (
          // 图片预览
          <img
            src={file.fullUrl}
            alt={file.name}
            className="w-full h-full object-cover"
            loading="lazy"
          />
        ) : (
          // 非图片文件预览
          <div className="w-full h-full flex flex-col items-center justify-center">
            {getFileIcon(file.type)}
            <span className="text-xs text-center mt-1 px-1 truncate max-w-full">
              {file.name.length > 8 ? `${file.name.substring(0, 6)}...` : file.name}
            </span>
          </div>
        )}

        {/* 悬停遮罩 */}
        <div className={`
          absolute inset-0 bg-black/60 flex flex-col items-center justify-center
          opacity-0 group-hover:opacity-100 transition-opacity duration-200
          text-white text-xs
        `}>
          <Eye className="h-4 w-4 mb-1" />
          <span>{isImage || isVideo ? '预览' : '查看'}</span>
        </div>

        {/* 序号标记 */}
        {index !== undefined && total !== undefined && total > 1 && (
          <div className={`
            absolute top-1 right-1 bg-black/70 text-white text-xs
            px-1.5 py-0.5 rounded
          `}>
            {index + 1}
          </div>
        )}
      </div>

      {/* 文件类型标签 */}
      <Badge 
        className={`
          absolute bottom-1 left-1 text-xs px-1 py-0
          ${getFileTypeBadge(file.type).color}
        `}
      >
        {getFileTypeBadge(file.type).text}
      </Badge>
    </div>
  );
};

interface FilePreviewProps {
  fileIds?: number[];
  files?: any[];
  maxCount?: number;
  size?: 'small' | 'medium' | 'large';
  showCount?: boolean;
  onFileClick?: (file: FileItem) => void;
  className?: string;
}

const FilePreview: React.FC<FilePreviewProps> = ({
  fileIds = [],
  files = [],
  maxCount = 6,
  size = 'medium',
  showCount = true,
  onFileClick,
  className = '',
}) => {
  // 合并文件ID和文件对象
  const allFileIds = [...fileIds, ...(files?.map(f => f.id) || [])];
  const uniqueFileIds = [...new Set(allFileIds)].filter(Boolean);

  // 使用 React Query 查询文件详情
  const { data: fileDetails, isLoading, error } = useQuery({
    queryKey: ['files', uniqueFileIds],
    queryFn: async () => {
      if (uniqueFileIds.length === 0) return [];
      
      const promises = uniqueFileIds.map(async (id) => {
        try {
          const response = await fileClient[':id']['$get']({ param: { id: id.toString() } });
          if (response.ok) {
            return response.json();
          }
          return null;
        } catch (error) {
          console.error(`获取文件 ${id} 详情失败:`, error);
          return null;
        }
      });
      
      const results = await Promise.all(promises);
      return results.filter(Boolean) as FileItem[];
    },
    enabled: uniqueFileIds.length > 0,
    staleTime: 5 * 60 * 1000, // 5分钟
    gcTime: 10 * 60 * 1000, // 10分钟
  });

  // 加载状态
  if (isLoading) {
    return (
      <div className={`flex justify-center py-8 ${className}`}>
        <div className="space-y-2">
          <div className="flex gap-2 justify-center">
            {[...Array(Math.min(maxCount, 3))].map((_, i) => (
              <Skeleton key={i} className={`rounded-lg ${size === 'small' ? 'w-12 h-12' : size === 'medium' ? 'w-20 h-20' : 'w-24 h-24'}`} />
            ))}
          </div>
          <p className="text-sm text-gray-500 text-center">加载中...</p>
        </div>
      </div>
    );
  }

  // 错误状态
  if (error) {
    return (
      <div className={`flex flex-col items-center justify-center py-8 ${className}`}>
        <FileText className="h-12 w-12 text-gray-400 mb-2" />
        <p className="text-sm text-gray-600">加载图片失败</p>
        <Button 
          variant="outline" 
          size="sm" 
          className="mt-2"
          onClick={() => {
            // 这里可以添加重试逻辑
            toast.info('请刷新页面重试');
          }}
        >
          重试
        </Button>
      </div>
    );
  }

  const displayFiles = fileDetails?.slice(0, maxCount) || [];
  const remainingCount = Math.max(0, (fileDetails?.length || 0) - maxCount);

  // 空状态
  if (displayFiles.length === 0) {
    return (
      <div className={`flex flex-col items-center justify-center py-6 ${className}`}>
        <FileText className="h-12 w-12 text-gray-400 mb-2" />
        <p className="text-sm text-gray-600">暂无图片</p>
      </div>
    );
  }

  return (
    <div className={className}>
      <div className="flex flex-wrap gap-2 items-start">
        {displayFiles.map((file, index) => (
          <FilePreviewItem
            key={file.id}
            file={file}
            size={size}
            index={index}
            total={displayFiles.length}
            onClick={onFileClick}
          />
        ))}
      </div>
      
      {/* 剩余数量提示 */}
      {showCount && remainingCount > 0 && (
        <div className="mt-2 text-sm text-gray-500">
          还有 {remainingCount} 个文件未显示
        </div>
      )}
    </div>
  );
};

// 导出组件和类型
export default FilePreview;
export type { FilePreviewProps };