/**
 * 成片库页面 — V21 设计系统
 * 卡片网格布局，支持视频播放/下载/分享、批量操作、筛选
 * 使用 useQuery 对接后端真实 API（api/products.ts）
 */
import React, {
  useMemo,
  useState,
  useRef,
  useEffect,
  useCallback,
} from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useNavigate } from "react-router-dom";
import { message, Popconfirm } from "antd";
import {
  SearchOutlined,
  VideoCameraOutlined,
  DownloadOutlined,
  ShareAltOutlined,
  DeleteOutlined,
  PlayCircleOutlined,
  PauseCircleOutlined,
  CloseOutlined,
  CheckOutlined,
  CloudUploadOutlined,
  EyeOutlined,
} from "@ant-design/icons";
import { Button, Input, Select } from "@/components/ui";
import {
  getProducts,
  deleteProduct,
  getProductDownloadUrl,
  type ProductItem as ApiProductItem,
} from "@/api/products";
import "./products.css";

/* ============================================================
 * 类型 & 常量
 * ============================================================ */
type ProductStatus = "completed" | "processing" | "review" | "failed";

interface ProductItem {
  id: string;
  name: string;
  status: ProductStatus;
  duration: number; // 秒
  date: string;
  gradient: string;
  duplicateRate: number; // 查重率百分比
  isPublished: boolean;
  resolution: string;
  fileSize: number; // MB
  videoUrl?: string;
  thumbnailUrl?: string;
}

/** 将后端 status 映射为前端 ProductStatus */
const normalizeStatus = (s: string): ProductStatus => {
  const map: Record<string, ProductStatus> = {
    completed: "completed",
    succeeded: "completed",
    processing: "processing",
    running: "processing",
    review: "review",
    failed: "failed",
    error: "failed",
  };
  return map[s] ?? "processing";
};

/** 渐变色列表（按 id hash 选取） */
const GRADIENTS = [
  "linear-gradient(135deg, #1e1b4b 0%, #4f46e5 50%, #818cf8 100%)",
  "linear-gradient(135deg, #831843 0%, #db2777 50%, #f472b6 100%)",
  "linear-gradient(135deg, #064e3b 0%, #059669 50%, #34d399 100%)",
  "linear-gradient(135deg, #78350f 0%, #d97706 50%, #fbbf24 100%)",
  "linear-gradient(135deg, #1e3a5f 0%, #2563eb 50%, #60a5fa 100%)",
  "linear-gradient(135deg, #581c87 0%, #9333ea 50%, #c084fc 100%)",
  "linear-gradient(135deg, #7f1d1d 0%, #dc2626 50%, #f87171 100%)",
  "linear-gradient(135deg, #134e4a 0%, #0d9488 50%, #5eead4 100%)",
  "linear-gradient(135deg, #1e1b4b 0%, #6366f1 50%, #a5b4fc 100%)",
  "linear-gradient(135deg, #3b0764 0%, #7c3aed 50%, #a78bfa 100%)",
  "linear-gradient(135deg, #052e16 0%, #16a34a 50%, #86efac 100%)",
  "linear-gradient(135deg, #450a0e 0%, #e11d48 50%, #fb7185 100%)",
];

/** 根据 id 生成稳定的渐变色 */
const gradientForId = (id: string): string => {
  let hash = 0;
  for (let i = 0; i < id.length; i++) hash = (hash * 31 + id.charCodeAt(i)) | 0;
  return GRADIENTS[Math.abs(hash) % GRADIENTS.length];
};

/** 将后端 ProductItem 映射为前端 ProductItem */
const mapApiProduct = (item: ApiProductItem): ProductItem => ({
  id: item.id,
  name: item.title,
  status: normalizeStatus(item.status),
  duration: item.duration_seconds ?? 0,
  date: item.created_at
    ? new Date(item.created_at).toISOString().slice(0, 10)
    : "—",
  gradient: gradientForId(item.id),
  duplicateRate: item.duplicate_rate ?? 0,
  isPublished: false, // TODO: 后端发布状态字段待补齐
  resolution: item.resolution ?? "1080×1920",
  fileSize: item.file_size ? +(item.file_size / (1024 * 1024)).toFixed(1) : 0,
  videoUrl: item.video_url,
  thumbnailUrl: item.thumbnail_url,
});

/* ============================================================
 * 工具函数
 * ============================================================ */
const statusConfig: Record<ProductStatus, { text: string; className: string }> =
  {
    completed: { text: "已完成", className: "completed" },
    processing: { text: "处理中", className: "processing" },
    review: { text: "待复核", className: "review" },
    failed: { text: "失败", className: "failed" },
  };

/** 格式化时间 mm:ss */
const formatTime = (seconds: number): string => {
  const mins = Math.floor(seconds / 60);
  const secs = Math.floor(seconds % 60);
  return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
};

/** 格式化文件大小 */
const formatSize = (mb: number): string => {
  if (mb <= 0) return "-";
  if (mb < 1) return `${(mb * 1024).toFixed(0)} KB`;
  return `${mb.toFixed(1)} MB`;
};

/* ============================================================
 * ProductCard 组件
 * ============================================================ */
const ProductCard: React.FC<{
  product: ProductItem;
  isSelected: boolean;
  batchMode: boolean;
  onToggleSelect: (id: string) => void;
  onPlay: (product: ProductItem) => void;
  onDownload: (product: ProductItem) => void;
  onShare: (product: ProductItem) => void;
  onDelete: (id: string) => void;
  onPublish: (product: ProductItem) => void;
}> = ({
  product,
  isSelected,
  batchMode,
  onToggleSelect,
  onPlay,
  onDownload,
  onShare,
  onDelete,
  onPublish,
}) => {
  const st = statusConfig[product.status];

  /** 查重率样式 */
  const dupClass =
    product.duplicateRate <= 5
      ? "good"
      : product.duplicateRate <= 15
        ? "warn"
        : "bad";

  /** 点击卡片 */
  const handleCardClick = () => {
    if (batchMode) {
      onToggleSelect(product.id);
    } else {
      onPlay(product);
    }
  };

  /** 点击复选框 */
  const handleCheckboxClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    onToggleSelect(product.id);
  };

  return (
    <div
      className={`xx-product-card${isSelected ? " selected" : ""}${product.isPublished ? " published" : ""}`}
      onClick={handleCardClick}
    >
      {/* 复选框（左上角） */}
      <div
        className={`xx-product-card-checkbox${isSelected ? " checked" : ""}`}
        onClick={handleCheckboxClick}
        title={isSelected ? "取消选择" : "选择"}
      >
        {isSelected && <CheckOutlined />}
      </div>

      {/* 已发布徽章（右上角） */}
      {product.isPublished && <div className="xx-product-badge">✅ 已发布</div>}

      {/* 缩略图 */}
      <div className="xx-product-thumb">
        {product.thumbnailUrl ? (
          <img
            className="xx-product-thumb-bg"
            src={product.thumbnailUrl}
            alt={product.name}
            style={{ width: "100%", height: "100%", objectFit: "cover" }}
          />
        ) : (
          <div
            className="xx-product-thumb-bg"
            style={{ background: product.gradient }}
          />
        )}
        <div className="xx-product-play">
          <PlayCircleOutlined />
        </div>
        {product.duration > 0 && (
          <span className="xx-product-duration">
            {formatTime(product.duration)}
          </span>
        )}
      </div>

      {/* 信息区 */}
      <div className="xx-product-info">
        <h4 className="xx-product-title" title={product.name}>
          {product.name}
        </h4>
        <div className="xx-product-meta">
          <span className={`xx-product-status ${st.className}`}>{st.text}</span>
          <span className="xx-product-date">{product.date}</span>
        </div>
        {product.duplicateRate > 0 && (
          <span className={`xx-product-dup-rate ${dupClass}`}>
            查重率：{product.duplicateRate.toFixed(1)}%
          </span>
        )}
      </div>

      {/* 操作按钮 */}
      <div className="xx-product-actions" onClick={(e) => e.stopPropagation()}>
        <button
          className="xx-product-action-btn"
          onClick={() => onDownload(product)}
          disabled={product.status !== "completed"}
          title="下载"
        >
          <DownloadOutlined /> 下载
        </button>
        <button
          className="xx-product-action-btn"
          onClick={() => onShare(product)}
          disabled={product.status !== "completed"}
          title="分享"
        >
          <ShareAltOutlined /> 分享
        </button>
        {product.isPublished ? (
          <span
            className="xx-product-action-btn success"
            style={{ cursor: "default" }}
          >
            ✅ 已发布
          </span>
        ) : (
          <button
            className="xx-product-action-btn primary"
            onClick={() => onPublish(product)}
            disabled={product.status !== "completed"}
            title="发布"
          >
            <CloudUploadOutlined /> 发布
          </button>
        )}
      </div>

      {/* 删除按钮（不在批量模式下显示） */}
      {!batchMode && (
        <div
          style={{ padding: "0 14px 14px" }}
          onClick={(e) => e.stopPropagation()}
        >
          <Popconfirm
            title={`确定删除"${product.name}"？`}
            onConfirm={() => onDelete(product.id)}
            okText="删除"
            cancelText="取消"
          >
            <button
              className="xx-product-action-btn"
              style={{ width: "100%", color: "#dc2626" }}
              title="删除"
            >
              <DeleteOutlined /> 删除
            </button>
          </Popconfirm>
        </div>
      )}
    </div>
  );
};

/* ============================================================
 * VideoPlayer 弹窗组件
 * ============================================================ */
const VideoPlayer: React.FC<{
  product: ProductItem;
  onClose: () => void;
  onDownload: (product: ProductItem) => void;
  onShare: (product: ProductItem) => void;
  onViewDetail: (product: ProductItem) => void;
}> = ({ product, onClose, onDownload, onShare, onViewDetail }) => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const progressRef = useRef<HTMLDivElement>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(product.duration);

  const hasVideo = !!product.videoUrl;

  /** 播放/暂停 */
  const handlePlayPause = useCallback(() => {
    const video = videoRef.current;
    if (!video) return;
    if (isPlaying) {
      video.pause();
    } else {
      video.play().catch(() => {});
    }
    setIsPlaying(!isPlaying);
  }, [isPlaying]);

  /** 视频事件监听 */
  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;
    const onTime = () => setCurrentTime(video.currentTime);
    const onDur = () => setDuration(video.duration || product.duration);
    const onEnd = () => setIsPlaying(false);
    video.addEventListener("timeupdate", onTime);
    video.addEventListener("loadedmetadata", onDur);
    video.addEventListener("ended", onEnd);
    return () => {
      video.removeEventListener("timeupdate", onTime);
      video.removeEventListener("loadedmetadata", onDur);
      video.removeEventListener("ended", onEnd);
    };
  }, [product.duration]);

  /** 进度条点击 */
  const handleProgressClick = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!progressRef.current) return;
    const rect = progressRef.current.getBoundingClientRect();
    const percent = (e.clientX - rect.left) / rect.width;
    const newTime = percent * duration;
    setCurrentTime(newTime);
    if (videoRef.current) videoRef.current.currentTime = newTime;
  };

  /** ESC 关闭 */
  useEffect(() => {
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    window.addEventListener("keydown", handleKey);
    return () => window.removeEventListener("keydown", handleKey);
  }, [onClose]);

  const progress = duration > 0 ? (currentTime / duration) * 100 : 0;

  return (
    <div className="xx-player-overlay" onClick={onClose}>
      <div className="xx-player-container" onClick={(e) => e.stopPropagation()}>
        {/* 视频区域 */}
        <div className="xx-player-video-wrap">
          {hasVideo ? (
            <video
              ref={videoRef}
              src={product.videoUrl}
              style={{ width: "100%", height: "100%", objectFit: "contain" }}
            />
          ) : (
            /* 无视频 URL 时用渐变占位 */
            <div
              style={{
                width: "100%",
                height: "100%",
                background: product.gradient,
                display: "grid",
                placeItems: "center",
                color: "rgba(255,255,255,0.3)",
                fontSize: "64px",
              }}
            >
              <VideoCameraOutlined />
            </div>
          )}

          {/* 播放/暂停按钮 */}
          <button className="xx-player-play-btn" onClick={handlePlayPause}>
            {isPlaying ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
          </button>

          {/* 关闭按钮 */}
          <button className="xx-player-close" onClick={onClose}>
            <CloseOutlined />
          </button>

          {/* 进度条 */}
          <div className="xx-player-progress-wrap">
            <div
              ref={progressRef}
              className="xx-player-progress"
              onClick={handleProgressClick}
            >
              <div
                className="xx-player-progress-bar"
                style={{ width: `${progress}%` }}
              />
            </div>
            <div className="xx-player-time">
              <span>{formatTime(currentTime)}</span>
              <span>{formatTime(duration)}</span>
            </div>
          </div>
        </div>

        {/* 信息区 */}
        <div className="xx-player-info">
          <h3 className="xx-player-title">{product.name}</h3>
          <div className="xx-player-details">
            <div className="xx-player-detail-item">
              <span className="xx-player-detail-label">分辨率：</span>
              <span className="xx-player-detail-value">
                {product.resolution}
              </span>
            </div>
            <div className="xx-player-detail-item">
              <span className="xx-player-detail-label">时长：</span>
              <span className="xx-player-detail-value">
                {formatTime(product.duration)}
              </span>
            </div>
            <div className="xx-player-detail-item">
              <span className="xx-player-detail-label">文件大小：</span>
              <span className="xx-player-detail-value">
                {formatSize(product.fileSize)}
              </span>
            </div>
            <div className="xx-player-detail-item">
              <span className="xx-player-detail-label">查重率：</span>
              <span className="xx-player-detail-value">
                {product.duplicateRate > 0
                  ? `${product.duplicateRate.toFixed(1)}%`
                  : "-"}
              </span>
            </div>
          </div>
        </div>

        {/* 底部操作 */}
        <div className="xx-player-footer">
          <Button
            buttonType="ghost"
            buttonSize="sm"
            icon={<DownloadOutlined />}
            onClick={() => onDownload(product)}
            disabled={product.status !== "completed"}
          >
            下载视频
          </Button>
          <Button
            buttonType="ghost"
            buttonSize="sm"
            icon={<ShareAltOutlined />}
            onClick={() => onShare(product)}
            disabled={product.status !== "completed"}
          >
            分享
          </Button>
          <Button
            buttonType="ghost"
            buttonSize="sm"
            icon={<EyeOutlined />}
            onClick={() => onViewDetail(product)}
          >
            查看详情
          </Button>
          <div style={{ flex: 1 }} />
          <Button buttonType="primary" buttonSize="sm" onClick={onClose}>
            关闭
          </Button>
        </div>
      </div>
    </div>
  );
};

/* ============================================================
 * 主组件
 * ============================================================ */
const ProductLibrary: React.FC = () => {
  const queryClient = useQueryClient();
  const navigate = useNavigate();

  /* ── 获取成品列表 ── */
  const {
    data: apiProducts = [],
    isLoading,
    isError,
    error,
    refetch,
  } = useQuery<ApiProductItem[], Error>({
    queryKey: ["products"],
    queryFn: getProducts,
    staleTime: 30_000,
  });

  // 映射为前端类型
  const products = useMemo(() => apiProducts.map(mapApiProduct), [apiProducts]);

  /* ── 删除 mutation ── */
  const deleteMutation = useMutation({
    mutationFn: deleteProduct,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["products"] });
      message.success("已删除");
    },
    onError: () => {
      message.error("删除失败");
    },
  });

  /* 筛选 */
  const [searchText, setSearchText] = useState("");
  const [filterStatus, setFilterStatus] = useState<string>("all");
  const [filterTime, setFilterTime] = useState<string>("all");
  const [filterDuration, setFilterDuration] = useState<string>("all");

  /* 批量操作 */
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());

  /* 播放器 */
  const [playingProduct, setPlayingProduct] = useState<ProductItem | null>(
    null,
  );

  /* 派生数据 */
  const batchMode = selectedIds.size > 0;

  const filteredProducts = useMemo(() => {
    let list = products;

    /* 状态筛选 */
    if (filterStatus !== "all") {
      list = list.filter((p) => p.status === filterStatus);
    }

    /* 时间筛选 */
    if (filterTime !== "all") {
      const now = new Date();
      list = list.filter((p) => {
        const d = new Date(p.date);
        const diff = (now.getTime() - d.getTime()) / (1000 * 60 * 60 * 24);
        switch (filterTime) {
          case "today":
            return diff < 1;
          case "week":
            return diff <= 7;
          case "month":
            return diff <= 30;
          default:
            return true;
        }
      });
    }

    /* 时长筛选 */
    if (filterDuration !== "all") {
      list = list.filter((p) => {
        switch (filterDuration) {
          case "short":
            return p.duration > 0 && p.duration <= 60;
          case "medium":
            return p.duration > 60 && p.duration <= 180;
          case "long":
            return p.duration > 180;
          default:
            return true;
        }
      });
    }

    /* 搜索 */
    if (searchText.trim()) {
      const q = searchText.trim().toLowerCase();
      list = list.filter((p) => p.name.toLowerCase().includes(q));
    }

    return list;
  }, [products, filterStatus, filterTime, filterDuration, searchText]);

  /* 全选 */
  const allSelected =
    filteredProducts.length > 0 &&
    filteredProducts.every((p) => selectedIds.has(p.id));

  const handleSelectAll = () => {
    if (allSelected) {
      setSelectedIds(new Set());
    } else {
      setSelectedIds(new Set(filteredProducts.map((p) => p.id)));
    }
  };

  /* 切换单个选择 */
  const handleToggleSelect = (id: string) => {
    setSelectedIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) {
        next.delete(id);
      } else {
        next.add(id);
      }
      return next;
    });
  };

  /* 下载 — 调用真实 API 获取下载链接 */
  const handleDownload = async (product: ProductItem) => {
    if (product.status !== "completed") return;
    try {
      const { url } = await getProductDownloadUrl(product.id);
      // 打开下载链接
      const a = document.createElement("a");
      a.href = url;
      a.download = "";
      a.click();
      message.success(`正在下载"${product.name}"`);
    } catch {
      message.error("获取下载链接失败");
    }
  };

  /* 分享 */
  const handleShare = (product: ProductItem) => {
    if (product.status !== "completed") return;
    const link = `${window.location.origin}/share/${product.id}`;
    navigator.clipboard?.writeText(link).then(
      () => message.success(`分享链接已复制：${link}`),
      () => message.success(`分享链接：${link}（请手动复制）`),
    );
  };

  /* 查看详情 — 跳转到产品详情页 */
  const handleViewDetail = (product: ProductItem) => {
    setPlayingProduct(null); // 关闭播放器
    navigate(`/app/products/${product.id}`);
  };

  /* 删除 */
  const handleDelete = (id: string) => {
    deleteMutation.mutate(id);
    setSelectedIds((prev) => {
      const next = new Set(prev);
      next.delete(id);
      return next;
    });
  };

  /* 发布 — TODO: 后端发布 API 待实现 */
  const handlePublish = (_product: ProductItem) => {
    // TODO: 对接后端发布 API（当前后端未提供发布接口）
    message.info("发布功能待后端 API 补齐");
  };

  /* 批量下载 */
  const handleBatchDownload = async () => {
    const ids = Array.from(selectedIds);
    let successCount = 0;
    for (const id of ids) {
      try {
        const { url } = await getProductDownloadUrl(id);
        const a = document.createElement("a");
        a.href = url;
        a.download = "";
        a.click();
        successCount++;
      } catch {
        // 忽略单个失败
      }
    }
    message.success(`已下载 ${successCount}/${ids.length} 个视频`);
    setSelectedIds(new Set());
  };

  /* 批量删除 */
  const handleBatchDelete = async () => {
    const ids = Array.from(selectedIds);
    let successCount = 0;
    for (const id of ids) {
      try {
        await deleteProduct(id);
        successCount++;
      } catch {
        // 忽略单个失败
      }
    }
    queryClient.invalidateQueries({ queryKey: ["products"] });
    setSelectedIds(new Set());
    message.success(`已批量删除 ${successCount}/${ids.length} 个视频`);
  };

  /* 批量发布 */
  const handleBatchPublish = () => {
    // TODO: 对接后端批量发布 API
    message.info("批量发布功能待后端 API 补齐");
    setSelectedIds(new Set());
  };

  // ── Loading 状态 ──
  if (isLoading) {
    return (
      <div className="xx-products-page">
        <div className="xx-products-empty">
          <div className="xx-products-empty-icon">⏳</div>
          <p>加载中...</p>
        </div>
      </div>
    );
  }

  // ── Error 状态 ──
  if (isError) {
    console.error("[ProductLibrary] 加载失败:", error);
    const errorMsg = error?.message || "加载失败";
    // 404 视为空数据（API 尚未就绪或无数据）
    const is404 = errorMsg.includes("404") || errorMsg.includes("Not Found");
    if (is404) {
      return (
        <div className="xx-products-page">
          <div className="xx-products-header">
            <h2>
              <VideoCameraOutlined /> 成片库
            </h2>
          </div>
          <div className="xx-products-empty">
            <div className="xx-products-empty-icon">🎬</div>
            <p>暂无成片数据</p>
            <p
              style={{
                fontSize: 12,
                color: "var(--text-tertiary)",
                marginTop: 4,
              }}
            >
              完成视频生成后，成片将自动保存到这里
            </p>
          </div>
        </div>
      );
    }
    return (
      <div className="xx-products-page">
        <div className="xx-products-empty">
          <div className="xx-products-empty-icon">❌</div>
          <p>{errorMsg || "加载失败，请稍后重试"}</p>
          <Button
            buttonType="primary"
            buttonSize="sm"
            onClick={() => refetch()}
          >
            重新加载
          </Button>
        </div>
      </div>
    );
  }

  return (
    <div className="xx-products-page">
      {/* 页面头部 */}
      <div className="xx-products-header">
        <h2>
          <VideoCameraOutlined /> 成片库
        </h2>
        <div style={{ display: "flex", gap: "var(--space-sm)" }}>
          <Button
            buttonType="ghost"
            buttonSize="sm"
            icon={<DownloadOutlined />}
          >
            批量导出
          </Button>
        </div>
      </div>

      {/* 批量操作栏 */}
      {batchMode && (
        <div className="xx-products-batch-bar">
          <div className="xx-products-batch-bar-left">
            <div
              className={`xx-products-checkbox${allSelected ? " checked" : ""}`}
              onClick={handleSelectAll}
            >
              {allSelected && <CheckOutlined />}
            </div>
            <span className="xx-products-select-all" onClick={handleSelectAll}>
              {allSelected ? "取消全选" : "全选"}
            </span>
            <span className="xx-products-batch-count">
              已选择 {selectedIds.size} 项
            </span>
          </div>
          <div className="xx-products-batch-bar-right">
            <Button
              buttonType="ghost"
              buttonSize="sm"
              icon={<DownloadOutlined />}
              onClick={handleBatchDownload}
            >
              批量下载
            </Button>
            <Button
              buttonType="primary"
              buttonSize="sm"
              icon={<CloudUploadOutlined />}
              onClick={handleBatchPublish}
            >
              批量发布
            </Button>
            <Popconfirm
              title={`确定删除选中的 ${selectedIds.size} 个视频？`}
              onConfirm={handleBatchDelete}
              okText="删除"
              cancelText="取消"
            >
              <Button
                buttonType="danger"
                buttonSize="sm"
                icon={<DeleteOutlined />}
              >
                批量删除
              </Button>
            </Popconfirm>
            <Button
              buttonType="ghost"
              buttonSize="sm"
              onClick={() => setSelectedIds(new Set())}
            >
              取消选择
            </Button>
          </div>
        </div>
      )}

      {/* 筛选栏 */}
      <div className="xx-products-filters">
        <div className="xx-products-filters-left">
          <Input
            placeholder="搜索成片名称..."
            prefix={<SearchOutlined />}
            value={searchText}
            onChange={(e) => setSearchText(e.target.value)}
            allowClear
            style={{ width: 220 }}
          />
          <Select
            value={filterStatus}
            onChange={setFilterStatus}
            style={{ width: 120 }}
            options={[
              { value: "all", label: "全部状态" },
              { value: "completed", label: "已完成" },
              { value: "processing", label: "处理中" },
              { value: "review", label: "待复核" },
              { value: "failed", label: "失败" },
            ]}
          />
          <Select
            value={filterTime}
            onChange={setFilterTime}
            style={{ width: 120 }}
            options={[
              { value: "all", label: "全部时间" },
              { value: "today", label: "今天" },
              { value: "week", label: "近一周" },
              { value: "month", label: "近一月" },
            ]}
          />
          <Select
            value={filterDuration}
            onChange={setFilterDuration}
            style={{ width: 120 }}
            options={[
              { value: "all", label: "全部时长" },
              { value: "short", label: "≤1分钟" },
              { value: "medium", label: "1-3分钟" },
              { value: "long", label: ">3分钟" },
            ]}
          />
        </div>
        <div className="xx-products-filters-right">
          <span
            style={{
              fontSize: "var(--font-size-sm)",
              color: "var(--text-tertiary)",
            }}
          >
            共 {filteredProducts.length} 个成片
          </span>
        </div>
      </div>

      {/* 卡片网格 */}
      {filteredProducts.length > 0 ? (
        <div className="xx-products-grid">
          {filteredProducts.map((product) => (
            <ProductCard
              key={product.id}
              product={product}
              isSelected={selectedIds.has(product.id)}
              batchMode={batchMode}
              onToggleSelect={handleToggleSelect}
              onPlay={setPlayingProduct}
              onDownload={handleDownload}
              onShare={handleShare}
              onDelete={handleDelete}
              onPublish={handlePublish}
            />
          ))}
        </div>
      ) : (
        <div className="xx-products-empty">
          <div className="xx-products-empty-icon">
            <VideoCameraOutlined />
          </div>
          <p>暂无成片，去一键生成吧</p>
          <Button
            buttonType="primary"
            buttonSize="sm"
            onClick={() => message.info("跳转到生成页面")}
          >
            去生成
          </Button>
        </div>
      )}

      {/* 视频播放弹窗 */}
      {playingProduct && (
        <VideoPlayer
          product={playingProduct}
          onClose={() => setPlayingProduct(null)}
          onDownload={handleDownload}
          onShare={handleShare}
          onViewDetail={handleViewDetail}
        />
      )}
    </div>
  );
};

export default ProductLibrary;
