'use client';

import { useCallback, useState, useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import useEmblaCarousel from 'embla-carousel-react';
import { useGesture } from '@use-gesture/react';
import { motion, useMotionValue, useSpring, animate, useMotionValueEvent } from 'framer-motion';
import {
  X,
  FileText,
  FileArchive,
  FileSpreadsheet,
  Image as ImageIcon,
  Video,
  Music,
  File,
  Download,
  ZoomIn,
  ZoomOut,
  RotateCw,
  ChevronLeft,
  ChevronRight,
  Maximize2,
  HelpCircle,
  ArrowLeft,
  ArrowRight,
  Plus,
  Minus,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Kbd } from '@/components/ui/kbd';
import { cn, downloadFromFile } from '@/lib/utils';
import { formatBytes } from '@/lib/format';

// ==================== 工具函数 ====================

/**
 * 根据文件 MIME 类型返回对应的图标
 */
export const getFileIcon = (type: string | undefined) => {
  if (!!type) {
    if (type.startsWith('image/')) return <ImageIcon className="size-6" />;
    if (type.startsWith('video/')) return <Video className="size-6" />;
    if (type.startsWith('audio/')) return <Music className="size-6" />;
    if (type.includes('pdf')) return <FileText className="size-6" />;
    if (type.includes('word') || type.includes('doc')) return <FileText className="size-6" />;
    if (type.includes('excel') || type.includes('sheet')) return <FileSpreadsheet className="size-6" />;
    if (type.includes('zip') || type.includes('rar') || type.includes('7z')) return <FileArchive className="size-6" />;
  }
  return <File className="size-6" />;
};

// ==================== 类型定义 ====================

/**
 * 文件预览项的基础接口
 */
export interface FilePreviewItem {
  /** 文件唯一标识 */
  id: string;
  /** 文件名称 */
  name: string;
  /** 文件大小（字节） */
  size: number;
  /** 文件 MIME 类型 */
  type?: string;
  /** 预览 URL（用于图片预览） */
  preview?: string;
  /** 上传进度（0-100），undefined 表示未上传或已完成 */
  progress?: number;
  /** 浏览器 File 对象（可选，用于下载功能） */
  file?: File;
}

/**
 * 文件卡片预览组件的属性
 */
export interface FileCardPreviewProps {
  /** 文件列表 */
  files: FilePreviewItem[];
  /** 外层容器的自定义类名 */
  className?: string;
  /** 网格容器的自定义类名 */
  gridClassName?: string;
  /** 是否禁用操作按钮 */
  disabled?: boolean;
  /** 是否显示下载按钮 */
  showDownload?: boolean;
  /** 是否显示删除按钮 */
  showRemove?: boolean;
  /** 是否显示文件信息（文件名和大小） */
  showFileInfo?: boolean;
  /** 删除文件的回调函数 */
  onRemove?: (id: string, file: FilePreviewItem) => void;
  /** 下载文件的回调函数（如果不提供，将使用默认的 downloadFromFile） */
  onDownload?: (id: string, file: FilePreviewItem) => void;
  /** 点击文件卡片的回调函数 */
  onClick?: (id: string, file: FilePreviewItem) => void;
}

// ==================== 文件卡片预览组件 ====================

/**
 * 文件卡片预览组件
 * 
 * 用于以卡片网格形式展示文件列表，支持图片预览、文件信息显示、下载和删除操作。
 * 
 * 特性：
 * - 响应式网格布局（移动端 1 列，平板 2 列，桌面 3 列）
 * - 图片文件显示预览图，其他文件显示对应图标
 * - 支持上传进度显示（圆形进度条）
 * - PC 端悬停显示操作按钮和文件信息
 * - 移动端点击激活显示操作按钮和文件信息
 * - 可自定义是否显示下载、删除按钮和文件信息
 * 
 * @example
 * ```tsx
 * <FileCardPreview
 *   files={files}
 *   showDownload
 *   showRemove
 *   onRemove={(id) => console.log('Remove', id)}
 * />
 * ```
 */
export function FileCardPreview({
  files,
  className,
  gridClassName,
  disabled = false,
  showDownload = true,
  showRemove = true,
  showFileInfo = true,
  onRemove,
  onDownload,
  onClick,
}: FileCardPreviewProps) {
  const [activeFileId, setActiveFileId] = useState<string | null>(null);
  const [carouselOpen, setCarouselOpen] = useState(false);
  const [carouselIndex, setCarouselIndex] = useState(0);

  const handleRemove = useCallback(
    (id: string, e: React.MouseEvent) => {
      e.stopPropagation();
      const fileItem = files.find((f) => f.id === id);
      if (fileItem && onRemove) {
        onRemove(id, fileItem);
      }
      setActiveFileId(null);
    },
    [files, onRemove]
  );

  const handleDownload = useCallback(
    (id: string, e: React.MouseEvent) => {
      e.stopPropagation();
      const fileItem = files.find((f) => f.id === id);
      if (fileItem) {
        if (onDownload) {
          onDownload(id, fileItem);
        } else if (fileItem.file) {
          downloadFromFile(fileItem.file);
        }
      }
    },
    [files, onDownload]
  );

  const handlePreview = useCallback(
    (id: string, e: React.MouseEvent) => {
      e.stopPropagation();
      const index = files.findIndex((f) => f.id === id);
      if (index !== -1) {
        setCarouselIndex(index);
        setCarouselOpen(true);
      }
    },
    [files]
  );

  const handleFileClick = useCallback(
    (id: string) => {
      const fileItem = files.find((f) => f.id === id);
      if (fileItem && onClick) {
        onClick(id, fileItem);
      }
      setActiveFileId((prev) => (prev === id ? null : id));
    },
    [files, onClick]
  );

  if (files.length === 0) {
    return null;
  }

  return (
    <div className={cn('w-full', className)}>
      <div
        className={cn(
          'grid grid-cols-1 gap-1 sm:grid-cols-2 lg:grid-cols-3',
          gridClassName
        )}
      >
        {files.map((fileItem) => (
          <div
            key={fileItem.id}
            className="group relative aspect-square cursor-pointer p-1"
            onClick={() => handleFileClick(fileItem.id)}
          >
            <div
              className={cn(
                'relative h-full overflow-hidden rounded-lg border bg-card transition-all',
                activeFileId === fileItem.id
                  ? 'border-primary ring-2 ring-primary ring-offset-2 shadow-lg'
                  : 'md:group-hover:border-primary/50 md:group-hover:shadow-md'
              )}
            >
              {/* 文件预览区域 */}
              {fileItem.type?.startsWith('image/') && fileItem.preview ? (
                <img
                  src={fileItem.preview}
                  alt={fileItem.name}
                  className="h-full w-full object-cover transition-transform group-hover:scale-105"
                />
              ) : (
                <div className="flex h-full items-center justify-center bg-muted text-muted-foreground">
                  {getFileIcon(fileItem.type)}
                </div>
              )}
              
              {/* 上传进度指示器 */}
              {fileItem.progress !== undefined && (
                <div className="absolute inset-0 flex items-center justify-center bg-black/50">
                  <div className="relative size-16">
                    <svg className="size-full -rotate-90" viewBox="0 0 100 100">
                      {/* 背景圆环 */}
                      <circle
                        cx="50"
                        cy="50"
                        r="45"
                        fill="none"
                        stroke="currentColor"
                        strokeWidth="8"
                        className="text-white/20"
                      />
                      {/* 进度圆环 */}
                      <circle
                        cx="50"
                        cy="50"
                        r="45"
                        fill="none"
                        stroke="currentColor"
                        strokeWidth="8"
                        strokeLinecap="round"
                        strokeDasharray={`${2 * Math.PI * 45}`}
                        strokeDashoffset={`${2 * Math.PI * 45 * (1 - fileItem.progress / 100)}`}
                        className="text-primary transition-all duration-300"
                      />
                    </svg>
                    <div className="absolute inset-0 flex items-center justify-center">
                      <span className="text-sm font-semibold text-white">
                        {Math.round(fileItem.progress)}%
                      </span>
                    </div>
                  </div>
                </div>
              )}

              {/* PC端悬停或移动端点击后显示的操作按钮 */}
              {(showDownload || showRemove || fileItem.type?.startsWith('image/')) && (
                <div
                  className={cn(
                    'absolute inset-0 flex items-center justify-center gap-2 rounded-lg bg-black/50 transition-opacity',
                    activeFileId === fileItem.id ? 'opacity-100' : 'opacity-0 md:group-hover:opacity-100 pointer-events-none md:group-hover:pointer-events-auto'
                  )}
                >
                  {fileItem.type?.startsWith('image/') && (
                    <Button
                      onClick={(e) => handlePreview(fileItem.id, e)}
                      type="button"
                      variant="secondary"
                      size="icon"
                      disabled={disabled}
                      className={cn(
                        'size-7',
                        activeFileId === fileItem.id && 'pointer-events-auto'
                      )}
                      title="预览"
                    >
                      <ZoomIn className="size-4" />
                    </Button>
                  )}
                  {showDownload && (fileItem.file || onDownload) && (
                    <Button
                      onClick={(e) => handleDownload(fileItem.id, e)}
                      type="button"
                      variant="secondary"
                      size="icon"
                      disabled={disabled}
                      className={cn(
                        'size-7',
                        activeFileId === fileItem.id && 'pointer-events-auto'
                      )}
                      title="下载"
                    >
                      <Download className="size-4" />
                    </Button>
                  )}
                  {showRemove && onRemove && (
                    <Button
                      onClick={(e) => handleRemove(fileItem.id, e)}
                      type="button"
                      variant="secondary"
                      size="icon"
                      disabled={disabled}
                      className={cn(
                        'size-7',
                        activeFileId === fileItem.id && 'pointer-events-auto'
                      )}
                      title="删除"
                    >
                      <X className="size-4" />
                    </Button>
                  )}
                </div>
              )}

              {/* PC端悬停或移动端点击后显示的文件信息 */}
              {showFileInfo && (
                <div
                  className={cn(
                    'absolute bottom-0 left-0 right-0 rounded-b-lg bg-gradient-to-t from-black/80 via-black/60 to-transparent p-2 pt-8 text-white transition-opacity',
                    activeFileId === fileItem.id ? 'opacity-100' : 'opacity-0 md:group-hover:opacity-100'
                  )}
                >
                  <p className="truncate text-xs font-medium" title={fileItem.name}>
                    {fileItem.name}
                  </p>
                  <p className="text-xs text-gray-300">
                    {formatBytes(fileItem.size)}
                  </p>
                </div>
              )}
            </div>
          </div>
        ))}
      </div>

      {/* 轮播预览 */}
      <FileCarouselPreview
        files={files}
        initialIndex={carouselIndex}
        open={carouselOpen}
        onClose={() => setCarouselOpen(false)}
        onDownload={onDownload}
      />
    </div>
  );
}


// ==================== 轮播预览组件 ====================

/**
 * 文件轮播预览组件的属性
 */
export interface FileCarouselPreviewProps {
  /** 文件列表 */
  files: FilePreviewItem[];
  /** 初始显示的文件索引 */
  initialIndex?: number;
  /** 是否打开预览 */
  open: boolean;
  /** 关闭预览的回调 */
  onClose: () => void;
  /** 下载文件的回调函数 */
  onDownload?: (id: string, file: FilePreviewItem) => void;
}

/**
 * 文件轮播预览组件
 * 
 * 全屏图片查看器，支持缩放、旋转、拖拽、键盘导航等功能。
 * 
 * 特性：
 * - Portal 渲染（避免 z-index 问题）
 * - ESC 键关闭，缩放、旋转、拖拽均有快捷键支持
 * - 缩放（按钮 + 滚轮）、旋转、拖拽移动（放大后）
 * - 下载图片
 * - 平滑动画
 * - 响应式设计
 * - 触摸友好
 * - ARIA 属性
 * - 键盘导航
 * 
 * @example
 * ```tsx
 * const [open, setOpen] = useState(false);
 * const [index, setIndex] = useState(0);
 * 
 * <FileCarouselPreview
 *   files={files}
 *   initialIndex={index}
 *   open={open}
 *   onClose={() => setOpen(false)}
 * />
 * ```
 */
export function FileCarouselPreview({
  files,
  initialIndex = 0,
  open,
  onClose,
  onDownload,
}: FileCarouselPreviewProps) {
  const [mounted, setMounted] = useState(false);
  const [emblaRef, emblaApi] = useEmblaCarousel({
    startIndex: initialIndex,
    loop: false,
    duration: 20, // 设置切换动画时长（毫秒）
  });
  
  const [currentIndex, setCurrentIndex] = useState(initialIndex);
  const [rotation, setRotation] = useState(0);
  const [showHelp, setShowHelp] = useState(false);
  const [currentScale, setCurrentScale] = useState(1);
  
  // 使用 framer-motion 的 motion values 和 spring 动画
  const scaleMotion = useMotionValue(1);
  const xMotion = useMotionValue(0);
  const yMotion = useMotionValue(0);
  
  // 使用 useSpring 包装 motion values，添加弹性物理效果
  const scale = useSpring(scaleMotion, { stiffness: 300, damping: 30 });
  const x = useSpring(xMotion, { stiffness: 300, damping: 30 });
  const y = useSpring(yMotion, { stiffness: 300, damping: 30 });
  
  // 监听 scale 变化，更新 state 以触发按钮状态更新
  useMotionValueEvent(scale, "change", (latest) => {
    setCurrentScale(latest);
  });
  
  const imageRef = useRef<HTMLDivElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const thumbnailRef = useRef<HTMLDivElement>(null);

  // 确保组件在客户端挂载
  useEffect(() => {
    setMounted(true);
  }, []);

  // 监听 embla 选中事件
  useEffect(() => {
    if (!emblaApi) return;

    const onSelect = () => {
      setCurrentIndex(emblaApi.selectedScrollSnap());
      // 切换图片时重置变换
      animate(scaleMotion, 1, { duration: 0.2 });
      animate(xMotion, 0, { duration: 0.2 });
      animate(yMotion, 0, { duration: 0.2 });
      setRotation(0);
    };

    emblaApi.on('select', onSelect);
    onSelect();

    return () => {
      emblaApi.off('select', onSelect);
    };
  }, [emblaApi, scaleMotion, xMotion, yMotion]);

  // 禁用背景滚动
  useEffect(() => {
    if (open) {
      document.body.style.overflow = 'hidden';
      return () => {
        document.body.style.overflow = '';
      };
    }
  }, [open]);

  // 缩放功能
  const handleZoomIn = useCallback(() => {
    const current = scaleMotion.get();
    animate(scaleMotion, Math.min(current + 0.25, 5), { duration: 0.2 });
  }, [scaleMotion]);

  const handleZoomOut = useCallback(() => {
    const current = scaleMotion.get();
    animate(scaleMotion, Math.max(current - 0.25, 0.5), { duration: 0.2 });
  }, [scaleMotion]);

  const handleRotate = useCallback(() => {
    setRotation((prev) => (prev + 90) % 360);
  }, []);

  const handleReset = useCallback(() => {
    animate(scaleMotion, 1, { duration: 0.2 });
    animate(xMotion, 0, { duration: 0.2 });
    animate(yMotion, 0, { duration: 0.2 });
    setRotation(0);
  }, [scaleMotion, xMotion, yMotion]);


  // 键盘事件处理
  useEffect(() => {
    if (!open) return;

    const handleKeyDown = (e: KeyboardEvent) => {
      // 阻止事件冒泡，避免关闭父对话框
      switch (e.key) {
        case 'Escape':
          e.preventDefault();
          e.stopPropagation();
          onClose();
          break;
        case 'ArrowLeft':
          e.preventDefault();
          e.stopPropagation();
          emblaApi?.scrollPrev();
          break;
        case 'ArrowRight':
          e.preventDefault();
          e.stopPropagation();
          emblaApi?.scrollNext();
          break;
        case '+':
        case '=':
          e.preventDefault();
          e.stopPropagation();
          handleZoomIn();
          break;
        case '-':
          e.preventDefault();
          e.stopPropagation();
          handleZoomOut();
          break;
        case 'r':
        case 'R':
          e.preventDefault();
          e.stopPropagation();
          handleRotate();
          break;
        case '0':
          e.preventDefault();
          e.stopPropagation();
          handleReset();
          break;
        case '?':
          e.preventDefault();
          e.stopPropagation();
          setShowHelp((prev) => !prev);
          break;
      }
    };

    // 使用 capture 阶段捕获事件，优先级更高
    window.addEventListener('keydown', handleKeyDown, true);
    return () => window.removeEventListener('keydown', handleKeyDown, true);
  }, [open, emblaApi, onClose, handleZoomIn, handleZoomOut, handleRotate, handleReset]);

  // 使用 use-gesture 处理所有手势
  // 注意：必须使用 target 选项才能正确使用 preventDefault
  useGesture(
    {
      // 拖拽手势 - 用于移动图片或切换图片
      onDrag: ({ offset: [ox, oy], active }) => {
        const currentScale = scale.get();
        
        // 如果图片放大了，拖拽用于移动图片
        if (currentScale > 1) {
          x.set(ox);
          y.set(oy);
        }
        else if (!active) {
          // 重置位置，切换的逻辑embla-carousel-react处理，这里不用管
          animate(x, 0, { duration: 0.3 });
          animate(y, 0, { duration: 0.3 });
        }
      },
      
      // 滚轮手势 - 用于缩放
      onWheel: ({ event, delta: [, dy], last }) => {
        // 避免在最后一个事件中访问 event（debounced）
        if (!last && event) {
          event.preventDefault();
        }
        const currentScale = scaleMotion.get();
        const scaleDelta = dy > 0 ? -0.1 : 0.1;
        const newScale = Math.max(0.5, Math.min(5, currentScale + scaleDelta));
        if (!last) {
          scaleMotion.set(newScale);
        }
      },
      
      // 双指缩放手势 - 移动端
      onPinch: ({ offset: [s], origin: [ox, oy], first, memo, last }) => {
        if (first) {
          const currentScale = scaleMotion.get();
          const currentX = xMotion.get();
          const currentY = yMotion.get();
          return [currentScale, currentX, currentY, ox, oy];
        }
        
        const [initialScale, initialX, initialY, initialOx, initialOy] = memo;
        const newScale = Math.max(0.5, Math.min(5, s));
        
        // 计算缩放中心偏移
        if (imageRef.current) {
          const rect = imageRef.current.getBoundingClientRect();
          const centerX = rect.left + rect.width / 2;
          const centerY = rect.top + rect.height / 2;
          
          // 相对于图片中心的偏移
          const offsetX = ox - centerX;
          const offsetY = oy - centerY;
          
          // 根据缩放调整位置，使缩放中心保持在手指位置
          const scaleRatio = newScale / initialScale;
          xMotion.set(initialX + offsetX * (1 - scaleRatio));
          yMotion.set(initialY + offsetY * (1 - scaleRatio));
        }
        
        if (!last) {
          scaleMotion.set(newScale);
        }
        return memo;
      },
    },
    {
      target: imageRef,
      drag: {
        from: () => [x.get(), y.get()],
        bounds: (state) => {
          const currentScale = scale.get();
          if (currentScale <= 1) {
            // 未放大时，允许左右拖拽切换
            return { left: -200, right: 200, top: 0, bottom: 0 };
          }
          // 放大时不限制边界
          return { left: -Infinity, right: Infinity, top: -Infinity, bottom: Infinity };
        },
      },
      pinch: {
        scaleBounds: { min: 0.5, max: 5 },
        eventOptions: { passive: false },
      },
      wheel: {
        eventOptions: { passive: false },
      },
    }
  );

  // 缩略图容器的拖动手势
  useGesture(
    {
      onDrag: ({ movement: [mx], memo = thumbnailRef.current?.scrollLeft ?? 0 }) => {
        if (thumbnailRef.current) {
          thumbnailRef.current.scrollLeft = memo - mx;
        }
        return memo;
      },
    },
    {
      target: thumbnailRef,
      drag: {
        axis: 'x',
        filterTaps: true,
      },
    }
  );

  // 下载当前文件
  const handleDownloadCurrent = useCallback(() => {
    const currentFile = files[currentIndex];
    if (currentFile) {
      if (onDownload) {
        onDownload(currentFile.id, currentFile);
      } else if (currentFile.file) {
        downloadFromFile(currentFile.file);
      }
    }
  }, [files, currentIndex, onDownload]);


  if (!mounted || !open) return null;

  const currentFile = files[currentIndex];
  const canScrollPrev = emblaApi?.canScrollPrev() ?? false;
  const canScrollNext = emblaApi?.canScrollNext() ?? false;

  return createPortal(
    <div
      ref={containerRef}
      className="fixed inset-0 z-70 flex items-center justify-center bg-black/95 pointer-events-auto"
      onKeyDown={(e) => {
        // 阻止键盘事件冒泡到父组件
        e.stopPropagation();
      }}
      role="dialog"
      aria-modal="true"
      aria-label="文件预览"
    >
      {/* 顶部工具栏 */}
      <div
        className="absolute top-0 left-0 right-0 z-10 flex items-start gap-2 p-4 bg-gradient-to-b from-black/50 to-transparent pointer-events-none"
      >
        <span className="text-sm font-medium text-white shrink-0">
          {currentIndex + 1} / {files.length}
        </span>
        
        {currentFile && (
          <span className="text-sm text-gray-300 break-words flex-1 min-w-0">
            {currentFile.name}
          </span>
        )}
        
        <div className="flex items-center gap-2 shrink-0 pointer-events-auto">
          <Button
            variant="ghost"
            size="icon"
            onClick={(e) => {
              setShowHelp((prev) => !prev);
            }}
            className="text-white hover:bg-white/20"
            title="快捷键帮助 (?)"
          >
            <HelpCircle className='size-5'/>
          </Button>
          <Button
            variant="ghost"
            size="icon"
            onClick={(e) => {
              onClose();
            }}
            className="text-white hover:bg-white/20"
            title="关闭 (ESC)"
          >
            <X className="size-5" />
          </Button>
        </div>
      </div>

      {/* 快捷键帮助面板 */}
      {showHelp && (
        <div
          className="absolute top-20 right-4 z-20 bg-black/90 text-white p-4 rounded-lg text-sm space-y-3 max-w-xs pointer-events-none"
        >
          <h3 className="font-semibold mb-2">键盘快捷键</h3>
          <div className="space-y-2">
            <div className="flex justify-between items-center gap-4">
              <Kbd className="bg-white/10 text-white border border-white/20">ESC</Kbd>
              <span className="text-gray-300">关闭</span>
            </div>
            <div className="flex justify-between items-center gap-4">
              <div className="flex gap-1">
                <Kbd className="bg-white/10 text-white border border-white/20">
                  <ArrowLeft className="size-3" />
                </Kbd>
                <Kbd className="bg-white/10 text-white border border-white/20">
                  <ArrowRight className="size-3" />
                </Kbd>
              </div>
              <span className="text-gray-300">切换图片</span>
            </div>
            <div className="flex justify-between items-center gap-4">
              <div className="flex gap-1">
                <Kbd className="bg-white/10 text-white border border-white/20">
                  <Plus className="size-3" />
                </Kbd>
                <Kbd className="bg-white/10 text-white border border-white/20">
                  <Minus className="size-3" />
                </Kbd>
              </div>
              <span className="text-gray-300">缩放</span>
            </div>
            <div className="flex justify-between items-center gap-4">
              <Kbd className="bg-white/10 text-white border border-white/20">R</Kbd>
              <span className="text-gray-300">旋转</span>
            </div>
            <div className="flex justify-between items-center gap-4">
              <Kbd className="bg-white/10 text-white border border-white/20">0</Kbd>
              <span className="text-gray-300">重置</span>
            </div>
            <div className="flex justify-between items-center gap-4">
              <Kbd className="bg-white/10 text-white border border-white/20">?</Kbd>
              <span className="text-gray-300">显示/隐藏帮助</span>
            </div>
          </div>
        </div>
      )}

      {/* 左侧工具栏 */}
      <div className="absolute left-4 top-1/2 -translate-y-1/2 z-10 flex flex-col gap-2">
        <Button
          variant="secondary"
          size="icon"
          onClick={(e) => {
            handleZoomIn();
          }}
          disabled={currentScale >= 5}
          title="放大 (+)"
          className="bg-black/50 hover:bg-black/70 text-white"
        >
          <ZoomIn className="size-5" />
        </Button>
        <Button
          variant="secondary"
          size="icon"
          onClick={(e) => {
            handleZoomOut();
          }}
          disabled={currentScale <= 0.5}
          title="缩小 (-)"
          className="bg-black/50 hover:bg-black/70 text-white"
        >
          <ZoomOut className="size-5" />
        </Button>
        <Button
          variant="secondary"
          size="icon"
          onClick={(e) => {
            handleRotate();
          }}
          title="旋转 (R)"
          className="bg-black/50 hover:bg-black/70 text-white"
        >
          <RotateCw className="size-5" />
        </Button>
        <Button
          variant="secondary"
          size="icon"
          onClick={(e) => {
            handleReset();
          }}
          title="重置 (0)"
          className="bg-black/50 hover:bg-black/70 text-white"
        >
          <Maximize2 className="size-5" />
        </Button>
        {(currentFile?.file || onDownload) && (
          <Button
            variant="secondary"
            size="icon"
            onClick={(e) => {
              handleDownloadCurrent();
            }}
            title="下载"
            className="bg-black/50 hover:bg-black/70 text-white"
          >
            <Download className="size-5" />
          </Button>
        )}
      </div>

      {/* 轮播容器 */}
      <div className="relative w-full h-full flex items-center justify-center">
        <div ref={emblaRef} className="overflow-hidden w-full h-full">
          <div className="flex h-full gap-8">
            {files.map((file, index) => (
              <div
                key={file.id}
                className="flex-[0_0_100%] min-w-0 flex items-center justify-center"
              >
                <div
                  ref={index === currentIndex ? imageRef : null}
                  className="relative flex items-center justify-center w-full h-full touch-none"
                  style={{
                    cursor: index === currentIndex && scale.get() > 1 ? 'grab' : 'default',
                  }}
                >
                  {file.type?.startsWith('image/') && file.preview ? (
                    <motion.img
                      src={file.preview}
                      alt={file.name}
                      className="max-w-full max-h-full object-contain select-none"
                      style={
                        index === currentIndex
                          ? {
                              scale,
                              x,
                              y,
                              rotate: rotation,
                            }
                          : {}
                      }
                      draggable={false}
                    />
                  ) : (
                    <div className="flex flex-col items-center justify-center gap-4 text-white">
                      {getFileIcon(file.type)}
                      <div className="text-center">
                        <p className="text-lg font-medium">{file.name}</p>
                        <p className="text-sm text-gray-400">{formatBytes(file.size)}</p>
                      </div>
                    </div>
                  )}
                </div>
              </div>
            ))}
          </div>
        </div>

      </div>

      {/* 底部导航区域：左右切换按钮 + 缩略图 */}
      <div className="absolute bottom-4 left-1/2 -translate-x-1/2 z-10 flex items-center gap-2">
        {/* 左切换按钮 */}
        <Button
          variant="secondary"
          size="icon"
          onClick={() => emblaApi?.scrollPrev()}
          disabled={!canScrollPrev}
          className="size-10 rounded-full bg-black/50 hover:bg-black/70 text-white flex-shrink-0 disabled:opacity-30 disabled:cursor-not-allowed"
          title="上一张 (←)"
        >
          <ChevronLeft className="size-5" />
        </Button>
        
        {/* 缩略图导航 */}
        <div
          ref={thumbnailRef}
          className="flex gap-2 max-w-[70vw] overflow-x-auto scrollbar-muted p-2 bg-black/50 rounded-lg cursor-grab active:cursor-grabbing touch-pan-x"
        >
          {files.map((file, index) => (
            <button
              key={file.id}
              onClick={() => emblaApi?.scrollTo(index)}
              className={cn(
                'relative size-16 flex-shrink-0 rounded overflow-hidden border-2 transition-all cursor-pointer select-none',
                index === currentIndex
                  ? 'border-primary ring-2 ring-primary'
                  : 'border-transparent hover:border-white/50'
              )}
              title={file.name}
            >
              {file.type?.startsWith('image/') && file.preview ? (
                <img
                  src={file.preview}
                  alt={file.name}
                  className="w-full h-full object-cover"
                />
              ) : (
                <div className="w-full h-full flex items-center justify-center bg-muted text-muted-foreground">
                  {getFileIcon(file.type)}
                </div>
              )}
            </button>
          ))}
        </div>
        
        {/* 右切换按钮 */}
        <Button
          variant="secondary"
          size="icon"
          onClick={() => emblaApi?.scrollNext()}
          disabled={!canScrollNext}
          className="size-10 rounded-full bg-black/50 hover:bg-black/70 text-white flex-shrink-0 disabled:opacity-30 disabled:cursor-not-allowed"
          title="下一张 (→)"
        >
          <ChevronRight className="size-5" />
        </Button>
      </div>
    </div>,
    document.body
  );
}