import { useState, useEffect, useRef, useCallback } from 'react';
import {
  listFiles,
  deleteFile,
  uploadFile,
  downloadFile,
  getFileThumbnailUrl,
  getFileDownloadUrl,
  type FileInfo,
} from '@/api/files';

interface FilePanelProps {
  onClose: () => void;
}

/** MIME 类型分类 */
function getCategory(mimeType: string): 'image' | 'audio' | 'video' | 'document' | 'other' {
  if (mimeType.startsWith('image/')) return 'image';
  if (mimeType.startsWith('audio/')) return 'audio';
  if (mimeType.startsWith('video/')) return 'video';
  if (mimeType.startsWith('text/') || mimeType === 'application/pdf' || mimeType.includes('word')) return 'document';
  return 'other';
}

/** 文件类型图标 */
function getFileIcon(mimeType: string): string {
  const cat = getCategory(mimeType);
  switch (cat) {
    case 'image': return '🖼️';
    case 'audio': return '🎵';
    case 'video': return '🎬';
    case 'document': return '📄';
    default: return '📎';
  }
}

/** 格式化文件大小 */
function formatSize(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`;
}

/** 格式化时间 */
function formatTime(ts: string): string {
  try {
    const d = new Date(Number(ts));
    return d.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });
  } catch {
    return ts;
  }
}

/** 允许的文件扩展名 */
const ALLOWED_EXTS = new Set([
  '.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg',
  '.pdf', '.txt', '.md', '.doc', '.docx',
  '.mp3', '.wav', '.ogg',
  '.mp4', '.webm',
]);

/** 允许的 MIME 类型前缀 */
const ALLOWED_MIME_PREFIXES = [
  'image/', 'audio/', 'video/',
  'application/pdf', 'text/', 'application/msword',
  'application/vnd.openxmlformats-officedocument.wordprocessingml',
];

export function FilePanel({ onClose }: FilePanelProps) {
  // 双视图：list / upload
  const [view, setView] = useState<'list' | 'upload'>('list');

  // 文件列表
  const [files, setFiles] = useState<FileInfo[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  // 筛选
  const [search, setSearch] = useState('');
  const [typeFilter, setTypeFilter] = useState<string>('all');

  // 上传
  const [uploading, setUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [dragOver, setDragOver] = useState(false);
  const [uploadErr, setUploadErr] = useState('');
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Lightbox 预览
  const [previewFile, setPreviewFile] = useState<FileInfo | null>(null);

  // 上下文菜单
  const [contextMenu, setContextMenu] = useState<{ x: number; y: number; file: FileInfo } | null>(null);

  const limit = 20;

  // 加载文件列表
  const loadFiles = useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const { files: f, total: t } = await listFiles(page, limit);
      setFiles(f);
      setTotal(t);
    } catch (e) {
      setError('加载文件列表失败');
      console.error('[FilePanel] 加载文件列表失败:', e);
    } finally {
      setLoading(false);
    }
  }, [page]);

  useEffect(() => {
    loadFiles();
  }, [loadFiles]);

  const totalPages = Math.ceil(total / limit);

  // 验证文件
  function validateFile(file: File): string | null {
    if (file.size > 20 * 1024 * 1024) {
      return `文件 "${file.name}" 超过 20MB 限制`;
    }
    const ext = '.' + file.name.split('.').pop()?.toLowerCase();
    const mimeOk = ALLOWED_MIME_PREFIXES.some(p => file.type.startsWith(p));
    const extOk = ALLOWED_EXTS.has(ext);
    if (!mimeOk && !extOk) {
      return `不支持的文件类型: ${file.type || ext}`;
    }
    return null;
  }

  // 处理上传
  async function handleUpload(fileList: FileList | File[]) {
    const filesToUpload = Array.from(fileList);
    if (filesToUpload.length === 0) return;

    // 验证所有文件
    for (const f of filesToUpload) {
      const err = validateFile(f);
      if (err) {
        setUploadErr(err);
        return;
      }
    }

    setUploading(true);
    setUploadErr('');
    setUploadProgress(0);

    let successCount = 0;
    for (let i = 0; i < filesToUpload.length; i++) {
      try {
        await uploadFile(filesToUpload[i]);
        successCount++;
      } catch (e) {
        console.error('[FilePanel] 上传失败:', e);
      }
      setUploadProgress(Math.round(((i + 1) / filesToUpload.length) * 100));
    }

    setUploading(false);
    setUploadProgress(0);

    if (successCount > 0) {
      setView('list');
      setPage(1);
      await loadFiles();
    }
    if (successCount < filesToUpload.length) {
      setUploadErr(`${filesToUpload.length - successCount} 个文件上传失败`);
    }
  }

  // 删除文件
  async function handleDelete(file: FileInfo) {
    setContextMenu(null);
    if (!confirm(`确定删除 "${file.filename}" 吗？此操作不可恢复。`)) return;
    try {
      const ok = await deleteFile(file.id);
      if (ok) {
        setFiles(prev => prev.filter(f => f.id !== file.id));
        setTotal(prev => prev - 1);
      }
    } catch (e) {
      console.error('[FilePanel] 删除失败:', e);
    }
  }

  // 下载文件
  function handleDownload(file: FileInfo) {
    setContextMenu(null);
    downloadFile(file.id, file.filename).catch(e => {
      console.error('[FilePanel] 下载失败:', e);
    });
  }

  // 过滤文件
  const filteredFiles = files.filter(f => {
    if (search && !f.filename.toLowerCase().includes(search.toLowerCase())) return false;
    if (typeFilter !== 'all' && getCategory(f.mime_type) !== typeFilter) return false;
    return true;
  });

  // Lightbox 关闭
  useEffect(() => {
    if (!previewFile) return;
    function handleKey(e: KeyboardEvent) {
      if (e.key === 'Escape') setPreviewFile(null);
    }
    document.addEventListener('keydown', handleKey);
    return () => document.removeEventListener('keydown', handleKey);
  }, [previewFile]);

  // 关闭上下文菜单
  useEffect(() => {
    if (!contextMenu) return;
    function handleClick() { setContextMenu(null); }
    document.addEventListener('click', handleClick);
    return () => document.removeEventListener('click', handleClick);
  }, [contextMenu]);

  return (
    <div className="flex flex-col h-full">
      {/* 视图切换标签 */}
      <div className="flex border-b border-gray-100 dark:border-gray-700">
        <button
          onClick={() => setView('list')}
          className={`flex-1 py-2 text-xs font-medium transition-colors ${
            view === 'list'
              ? 'text-pink-500 border-b-2 border-pink-500'
              : 'text-gray-400 hover:text-gray-600 dark:hover:text-gray-300'
          }`}
        >
          📋 文件列表
        </button>
        <button
          onClick={() => { setView('upload'); setUploadErr(''); }}
          className={`flex-1 py-2 text-xs font-medium transition-colors ${
            view === 'upload'
              ? 'text-pink-500 border-b-2 border-pink-500'
              : 'text-gray-400 hover:text-gray-600 dark:hover:text-gray-300'
          }`}
        >
          📤 上传
        </button>
      </div>

      {/* 文件列表视图 */}
      {view === 'list' && (
        <div className="flex-1 flex flex-col min-h-0">
          {/* 搜索和筛选 */}
          <div className="px-3 py-2 flex gap-2">
            <input
              type="text"
              value={search}
              onChange={e => setSearch(e.target.value)}
              placeholder="🔍 搜索文件名..."
              className="flex-1 px-2 py-1 text-xs border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-pink-300"
            />
            <select
              value={typeFilter}
              onChange={e => setTypeFilter(e.target.value)}
              className="px-2 py-1 text-xs border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none"
            >
              <option value="all">全部类型</option>
              <option value="image">🖼️ 图片</option>
              <option value="document">📄 文档</option>
              <option value="audio">🎵 音频</option>
              <option value="video">🎬 视频</option>
              <option value="other">📎 其他</option>
            </select>
          </div>

          {/* 文件列表 */}
          <div className="flex-1 overflow-y-auto px-3">
            {loading && files.length === 0 && (
              <div className="flex items-center justify-center py-8 text-sm text-gray-400">
                <div className="animate-spin mr-2">⏳</div> 加载中...
              </div>
            )}

            {error && (
              <div className="py-4 text-center text-sm text-red-500">
                {error}
                <button onClick={loadFiles} className="ml-2 underline">重试</button>
              </div>
            )}

            {!loading && !error && filteredFiles.length === 0 && (
              <div className="flex flex-col items-center justify-center py-12 text-gray-400">
                <span className="text-4xl mb-3">📁</span>
                <p className="text-sm">暂无文件</p>
                <button
                  onClick={() => setView('upload')}
                  className="mt-3 px-4 py-1.5 text-xs text-pink-500 border border-pink-200 dark:border-pink-800 rounded-lg hover:bg-pink-50 dark:hover:bg-pink-900/20 transition-colors"
                >
                  📤 上传文件
                </button>
              </div>
            )}

            {filteredFiles.length > 0 && (
              <div className="grid grid-cols-2 gap-2 py-2">
                {filteredFiles.map(f => (
                  <div
                    key={f.id}
                    className="group relative flex flex-col items-center p-2 border border-gray-100 dark:border-gray-700 rounded-lg hover:border-pink-200 dark:hover:border-pink-800 hover:bg-pink-50/50 dark:hover:bg-pink-900/10 cursor-pointer transition-colors"
                    onClick={() => {
                      if (getCategory(f.mime_type) === 'image') {
                        setPreviewFile(f);
                      } else {
                        handleDownload(f);
                      }
                    }}
                    onContextMenu={e => {
                      e.preventDefault();
                      setContextMenu({ x: e.clientX, y: e.clientY, file: f });
                    }}
                  >
                    {/* 缩略图或图标 */}
                    <div className="w-16 h-16 flex items-center justify-center rounded bg-gray-50 dark:bg-gray-700 mb-1 overflow-hidden">
                      {getCategory(f.mime_type) === 'image' ? (
                        <img
                          src={getFileThumbnailUrl(f.id)}
                          alt={f.filename}
                          className="w-full h-full object-cover"
                          loading="lazy"
                          onError={e => {
                            (e.target as HTMLImageElement).style.display = 'none';
                            (e.target as HTMLImageElement).nextElementSibling?.classList.remove('hidden');
                          }}
                        />
                      ) : null}
                      <span className={`text-2xl ${getCategory(f.mime_type) === 'image' ? 'hidden' : ''}`}>
                        {getFileIcon(f.mime_type)}
                      </span>
                    </div>

                    {/* 文件名 */}
                    <p className="text-xs text-gray-700 dark:text-gray-300 text-center truncate w-full" title={f.filename}>
                      {f.filename}
                    </p>

                    {/* 大小和时间 */}
                    <p className="text-[10px] text-gray-400 mt-0.5">
                      {formatSize(f.size)} · {formatTime(f.created_at)}
                    </p>

                    {/* 操作按钮 (悬停显示) */}
                    <div className="absolute top-1 right-1 hidden group-hover:flex gap-0.5">
                      <button
                        onClick={e => { e.stopPropagation(); handleDownload(f); }}
                        className="p-1 text-gray-400 hover:text-pink-500 bg-white dark:bg-gray-800 rounded shadow-sm"
                        title="下载"
                      >
                        <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
                        </svg>
                      </button>
                      <button
                        onClick={e => { e.stopPropagation(); handleDelete(f); }}
                        className="p-1 text-gray-400 hover:text-red-500 bg-white dark:bg-gray-800 rounded shadow-sm"
                        title="删除"
                      >
                        <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                        </svg>
                      </button>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>

          {/* 分页 */}
          {totalPages > 1 && (
            <div className="flex items-center justify-between px-3 py-2 border-t border-gray-100 dark:border-gray-700">
              <span className="text-[10px] text-gray-400">
                共 {total} 个文件
              </span>
              <div className="flex gap-1">
                <button
                  onClick={() => setPage(p => Math.max(1, p - 1))}
                  disabled={page <= 1}
                  className="px-2 py-0.5 text-xs rounded border border-gray-200 dark:border-gray-600 disabled:opacity-30 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
                >
                  ‹
                </button>
                <span className="px-2 py-0.5 text-xs text-gray-500">{page} / {totalPages}</span>
                <button
                  onClick={() => setPage(p => Math.min(totalPages, p + 1))}
                  disabled={page >= totalPages}
                  className="px-2 py-0.5 text-xs rounded border border-gray-200 dark:border-gray-600 disabled:opacity-30 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
                >
                  ›
                </button>
              </div>
            </div>
          )}
        </div>
      )}

      {/* 上传视图 */}
      {view === 'upload' && (
        <div className="flex-1 flex flex-col p-4">
          {/* 拖放区域 */}
          <div
            className={`flex-1 flex flex-col items-center justify-center border-2 border-dashed rounded-xl transition-colors ${
              dragOver
                ? 'border-pink-400 bg-pink-50 dark:bg-pink-900/20'
                : 'border-gray-300 dark:border-gray-600 hover:border-pink-300'
            }`}
            onDragOver={e => { e.preventDefault(); setDragOver(true); }}
            onDragLeave={() => setDragOver(false)}
            onDrop={e => {
              e.preventDefault();
              setDragOver(false);
              if (e.dataTransfer.files.length > 0) {
                handleUpload(e.dataTransfer.files);
              }
            }}
            onClick={() => fileInputRef.current?.click()}
          >
            {uploading ? (
              <div className="flex flex-col items-center gap-3">
                <div className="animate-spin text-3xl">⏳</div>
                <p className="text-sm text-gray-500">上传中...</p>
                <div className="w-48 h-2 bg-gray-200 dark:bg-gray-600 rounded-full overflow-hidden">
                  <div
                    className="h-full bg-pink-500 rounded-full transition-all duration-300"
                    style={{ width: `${uploadProgress}%` }}
                  />
                </div>
                <p className="text-xs text-gray-400">{uploadProgress}%</p>
              </div>
            ) : (
              <div className="flex flex-col items-center gap-2 pointer-events-none">
                <span className="text-4xl">📤</span>
                <p className="text-sm text-gray-500 dark:text-gray-400">
                  {dragOver ? '释放以上传文件' : '拖放文件到此处或点击选择'}
                </p>
                <p className="text-xs text-gray-400">
                  支持图片、文档、音频、视频 · 最大 20MB
                </p>
              </div>
            )}
          </div>

          {/* 隐藏的文件输入 */}
          <input
            ref={fileInputRef}
            type="file"
            multiple
            className="hidden"
            accept=".jpg,.jpeg,.png,.gif,.webp,.svg,.pdf,.txt,.md,.doc,.docx,.mp3,.wav,.ogg,.mp4,.webm"
            onChange={e => {
              if (e.target.files && e.target.files.length > 0) {
                handleUpload(e.target.files);
                e.target.value = '';
              }
            }}
          />

          {/* 上传错误 */}
          {uploadErr && (
            <div className="mt-3 p-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded text-xs text-red-600 dark:text-red-400">
              {uploadErr}
              <button onClick={() => setUploadErr('')} className="ml-2 underline">关闭</button>
            </div>
          )}

          {/* 支持的文件类型 */}
          <div className="mt-3 text-[10px] text-gray-400 space-y-1">
            <p>🖼️ 图片: JPG, PNG, GIF, WebP, SVG</p>
            <p>📄 文档: PDF, TXT, MD, DOC, DOCX</p>
            <p>🎵 音频: MP3, WAV, OGG</p>
            <p>🎬 视频: MP4, WebM</p>
          </div>
        </div>
      )}

      {/* 右键菜单 */}
      {contextMenu && (
        <div
          className="fixed z-[100] bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-xl py-1 min-w-[120px]"
          style={{ left: contextMenu.x, top: contextMenu.y }}
        >
          <button
            onClick={() => handleDownload(contextMenu.file)}
            className="w-full text-left px-3 py-1.5 text-xs text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center gap-2"
          >
            ⬇️ 下载
          </button>
          {getCategory(contextMenu.file.mime_type) === 'image' && (
            <button
              onClick={() => { setPreviewFile(contextMenu.file); setContextMenu(null); }}
              className="w-full text-left px-3 py-1.5 text-xs text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center gap-2"
            >
              🔍 预览
            </button>
          )}
          <button
            onClick={() => handleDelete(contextMenu.file)}
            className="w-full text-left px-3 py-1.5 text-xs text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 flex items-center gap-2"
          >
            🗑️ 删除
          </button>
        </div>
      )}

      {/* Lightbox 图片预览 */}
      {previewFile && (
        <div
          className="fixed inset-0 z-[200] bg-black/80 flex items-center justify-center p-4"
          onClick={() => setPreviewFile(null)}
        >
          <button
            onClick={() => setPreviewFile(null)}
            className="absolute top-4 right-4 text-white/80 hover:text-white text-2xl z-10"
          >
            ✕
          </button>
          <div className="flex flex-col items-center max-w-full max-h-full" onClick={e => e.stopPropagation()}>
            <img
              src={getFileDownloadUrl(previewFile.id)}
              alt={previewFile.filename}
              className="max-w-full max-h-[70vh] object-contain rounded-lg shadow-2xl"
            />
            <div className="mt-3 text-center">
              <p className="text-white text-sm font-medium">{previewFile.filename}</p>
              <p className="text-white/60 text-xs mt-1">{formatSize(previewFile.size)}</p>
              <div className="flex gap-3 mt-3 justify-center">
                <button
                  onClick={() => handleDownload(previewFile)}
                  className="px-4 py-1.5 text-xs text-white bg-pink-500 hover:bg-pink-600 rounded-lg transition-colors"
                >
                  ⬇️ 下载
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
