import React, { useState, useEffect } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { 
  History as HistoryIcon, 
  Search, 
  Filter,
  Clock,
  Eye,
  Download,
  RefreshCw,
  MoreHorizontal,
  Loader2,
  ImageOff,
  AlertCircle,
  Trash2
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { useAuth } from '../contexts/AuthContext';
import { aiSwapAPI } from '../api/ai_swap';
import { useNavigate } from 'react-router-dom';

// 获取媒体文件URL的辅助函数（支持图片和视频）
const getImageUrl = (item) => {
  if (!item || !item.stored_path) {
    console.log('无效的媒体数据:', item);
    return '';
  }
  
  try {
    const filename = item.stored_path.split(/[\\/]/).pop();
    if (!filename) {
      console.warn('无法从路径提取文件名:', item.stored_path);
      return '';
    }

    let baseUrl = import.meta.env.VITE_API_BASE_URL || '';
    if (!baseUrl) {
      console.warn('API基础URL未配置');
      return '';
    }
    
    // 根据文件类型和路径判断使用哪个静态文件服务
    let url = '';
    if (item.image_type === 'result' || item.stored_path.includes('output')) {
      // 结果文件使用 /output 路径
      url = `${baseUrl}/output/${filename}`;
    } else {
      // 素材文件使用 /materials 路径
      url = `${baseUrl}/materials/${filename}`;
    }
    
    console.log('生成的媒体文件URL:', url);
    return url;
  } catch (error) {
    console.error('生成媒体文件URL时出错:', error);
    return '';
  }
};

// 判断文件是否为视频格式
const isVideoFile = (url) => {
  if (!url) return false;
  const videoExtensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.webm', '.mkv', '.m4v'];
  const lowerUrl = url.toLowerCase();
  return videoExtensions.some(ext => lowerUrl.includes(ext));
};

// 媒体组件（支持图片和视频）
const MediaWithFallback = ({ src, alt, className, onLoad, ...mediaProps }) => {
  const [error, setError] = useState(false);
  const [loading, setLoading] = useState(true);
  const [isVideo, setIsVideo] = useState(false);

  useEffect(() => {
    if (src) {
      setIsVideo(isVideoFile(src));
    }
  }, [src]);

  const handleError = (e) => {
    console.error(`媒体加载失败 - ${alt}:`, e.message);
    setError(true);
    setLoading(false);
  };

  const handleLoad = () => {
    setLoading(false);
    if (onLoad) onLoad();
  };

  // 如果没有src，显示无媒体状态
  if (!src) {
    return (
      <div className={`flex items-center justify-center ${className} bg-slate-50`}>
        <ImageOff className="w-6 h-6 text-slate-400" />
        <span className="text-xs text-slate-500 ml-2">无媒体</span>
      </div>
    );
  }

  // 如果加载出错，显示错误状态
  if (error) {
    return (
      <div className={`flex items-center justify-center ${className} bg-slate-50`}>
        <AlertCircle className="w-6 h-6 text-red-400" />
        <span className="text-xs text-red-500 ml-2">加载失败</span>
      </div>
    );
  }

  return (
    <div className="relative w-full h-full">
      {loading && (
        <div className="absolute inset-0 flex items-center justify-center bg-slate-50">
          <Loader2 className="w-6 h-6 text-slate-400 animate-spin" />
        </div>
      )}
      {isVideo ? (
        <video
          src={src}
          className={`${className} ${loading ? 'invisible' : 'visible'}`}
          onError={handleError}
          onLoadedData={handleLoad}
          controls
          muted
          playsInline
          preload="metadata"
          {...mediaProps}
        >
          您的浏览器不支持视频播放。
        </video>
      ) : (
        <img
          src={src}
          alt={alt}
          className={`${className} ${loading ? 'invisible' : 'visible'}`}
          onError={handleError}
          onLoad={handleLoad}
          {...mediaProps}
        />
      )}
    </div>
  );
};

// 为了向后兼容，保留 ImageWithFallback 作为 MediaWithFallback 的别名
const ImageWithFallback = MediaWithFallback;

// 添加提取标题的辅助函数
const extractTitle = (text) => {
  if (!text) return '';
  
  // 查找标题部分（以 "- 标题：" 开头的内容）
  const titleMatch = text.match(/[-\s]*标题：\s*([^\n-]+)/);
  if (titleMatch && titleMatch[1]) {
    return titleMatch[1].trim();
  }
  
  return '';
};

const extractContent = (text) => {
  if (!text) return '';
  
  // 多行文案匹配：获取“文案：”之后到“话题标签：”之前（或文本结束）的所有内容
  // 允许前缀中出现破折号/空白
  const contentMatch = text.match(/[-\s]*文案：\s*([\s\S]*?)(?:\n[-\s]*话题标签：|$)/);
  if (contentMatch && contentMatch[1]) {
    return contentMatch[1].trim();
  }
  
  return '';
};

const extractLabel = (text) => {
  if (!text) return '';
  
  // 查找标题部分（以 "- 标题：" 开头的内容）
  const titleMatch = text.match(/[-\s]*话题标签：\s*([^\n-]+)/);
  if (titleMatch && titleMatch[1]) {
    return titleMatch[1].trim();
  }
  
  return '';
};

export default function History() {
  const { user, isAuthenticated } = useAuth();
  const navigate = useNavigate();
  const [generatedContents, setGeneratedContents] = useState([]);
  const [searchTerm, setSearchTerm] = useState('');
  const [filterStatus, setFilterStatus] = useState('all');
  const [filterPlatform, setFilterPlatform] = useState('all');
  const [loading, setLoading] = useState(false);
  const [pagination, setPagination] = useState({
    current: 1,
    pageSize: 10,
    total: 0,
  });
  const [detailModalVisible, setDetailModalVisible] = useState(false);
  const [selectedRecord, setSelectedRecord] = useState(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [isEditing, setIsEditing] = useState(false);
  const [editedText, setEditedText] = useState({
    title: '',
    content: '',
    label: ''
  });
  const [isSaving, setIsSaving] = useState(false);
  const [isApproving, setIsApproving] = useState(false);

  // 统一的预览尺寸，确保人脸、服装与结果图片大小一致
  // 使用最小高度而不是完全填满，避免撑破布局导致“结果图片”标题被遮挡
  const previewSizeClass = 'h-auto min-h-[18rem] md:min-h-[24rem]';

  // 下载辅助：生成文件名
  const sanitizeFilename = (name) => {
    return String(name || 'download')
      .replace(/[\\/:*?"<>|\n\r]+/g, '_')
      .slice(0, 100);
  };

  const getStoredFilename = (img, fallback) => {
    try {
      const p = img?.stored_path || '';
      const name = p.split(/[/\\]/).pop();
      return name || fallback;
    } catch {
      return fallback;
    }
  };

  const downloadBlob = (blob, filename) => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
  };

  const downloadUrl = async (url, filename) => {
    const res = await fetch(url, { mode: 'cors' });
    if (!res.ok) throw new Error(`下载失败 ${res.status}`);
    const blob = await res.blob();
    downloadBlob(blob, filename);
  };

  // 分组合并的“基准记录”选择工具，保证保存后的文案稳定不被其他拆分记录覆盖
  const getGroupKey = (faceId, clothId) => `${faceId}-${clothId}`;
  const getPreferredRecordId = (groupKey) => {
    try { return localStorage.getItem(`historyPreferred:${groupKey}`); } catch { return null; }
  };
  const setPreferredRecordId = (groupKey, recordId) => {
    try { localStorage.setItem(`historyPreferred:${groupKey}`, String(recordId)); } catch {}
  };

  // 检查用户认证状态
  useEffect(() => {
    if (!isAuthenticated) {
      console.log('用户未登录，重定向到登录页面');
      navigate('/login');
      return;
    }
  }, [isAuthenticated, navigate]);

  useEffect(() => {
    if (isAuthenticated && user?.id) {
      loadHistory();
    }
  }, [user, pagination.current, pagination.pageSize, isAuthenticated]);

  const loadHistory = async () => {
    if (!isAuthenticated || !user?.id) {
      console.log('用户未登录或ID无效，无法加载历史记录');
      console.log('isAuthenticated:', isAuthenticated);
      console.log('user:', user);
      return;
    }
    
    try {
      setLoading(true);
      console.log('开始加载历史记录（全量），用户ID:', user.id);

      // 先拉取第一页，拿到 total_pages 后并发拉取剩余页，确保不遗漏任何记录
      const firstPageSize = 100; // 后端最大允许100，减少请求次数
      const firstResp = await aiSwapAPI.getUserProcessHistory(user.id, 1, firstPageSize);
      console.log('历史记录第一页响应:', firstResp);

      if (firstResp && Array.isArray(firstResp.records)) {
        let allRecords = [...firstResp.records];
        const totalPages = Number(firstResp.total_pages || Math.ceil((firstResp.total || allRecords.length) / (firstResp.page_size || firstPageSize)) || 1);
        console.log('总页数:', totalPages, '当前累计记录数:', allRecords.length);

        if (totalPages > 1) {
          const pageNumbers = [];
          for (let p = 2; p <= totalPages; p++) pageNumbers.push(p);
          const rest = await Promise.all(
            pageNumbers.map(pn => aiSwapAPI.getUserProcessHistory(user.id, pn, firstPageSize).catch(err => { console.warn('拉取历史记录第', pn, '页失败:', err); return null; }))
          );
          for (const r of rest) {
            if (r && Array.isArray(r.records)) allRecords = allRecords.concat(r.records);
          }
        }

        // 以记录ID去重，避免重复
        const seen = new Set();
        const dedupedRecords = [];
        for (const rec of allRecords) {
          const rid = rec && rec.id;
          if (rid == null) continue;
          if (!seen.has(rid)) { seen.add(rid); dedupedRecords.push(rec); }
        }

        console.log('开始转换数据（全量），记录数量:', dedupedRecords.length);
        
        // 转换后端数据格式为前端需要的格式（先平铺，再分组合并）
        const transformedData = await Promise.all(dedupedRecords.map(async record => {
          console.log('处理记录:', record);
          
          let detail = null;
          try {
            // 获取每条记录的详细信息
            detail = await aiSwapAPI.getProcessDetail(record.id, user.id);
            console.log('记录详情:', detail);
          } catch (error) {
            console.warn(`获取记录 ${record.id} 详情失败:`, error);
            // 如果获取详情失败，使用基础记录信息
            detail = {
              process_record: record,
              face_image: null,
              cloth_image: null,
              result_image: null
            };
          }
          
          const generatedText = detail?.process_record?.generated_text || record.generated_text || '';
          
          return {
            id: record.id,
            face_image_id: record.face_image_id,
            cloth_image_id: record.cloth_image_id,
            title: extractTitle(generatedText) || `AI换脸换装处理 - 记录 #${record.id}`,
            content_text: extractContent(generatedText) || '无文案内容',
            status: record.status || 'completed',
            platform: 'ai_swap',
            created_date: new Date(record.completed_at || record.created_at).toLocaleString(),
            completed_at_ts: new Date(record.completed_at || record.created_at).getTime(),
            face_image: detail?.face_image || null,
            cloth_image: detail?.cloth_image || null,
            result_image: detail?.result_image || null,
            additional_images: detail?.additional_images || [],
            label: extractLabel(generatedText) || '无话题标签'
          };
        }));

        console.log('转换后的数据（全量）:', transformedData);

        // 合并相同 face_image_id + cloth_image_id 的记录
        const groupedMap = new Map();
        for (const item of transformedData) {
          const groupKey = `${item.face_image_id}-${item.cloth_image_id}`;
          const existing = groupedMap.get(groupKey);
          const currentResultImage = item.result_image ? [item.result_image] : [];

          if (!existing) {
            groupedMap.set(groupKey, {
              ...item,
              groupKey,
              // 将所有结果图片聚合为数组，便于详情展示
              result_images: currentResultImage.slice(),
              // 该合并卡片包含的所有原始记录ID
              record_ids: [item.id],
              members: [
                {
                  id: item.id,
                  title: item.title,
                  content_text: item.content_text,
                  label: item.label,
                  status: item.status,
                  created_date: item.created_date,
                  completed_at_ts: item.completed_at_ts,
                }
              ],
              // 额外计数在渲染时由 additional_images 显示
            });
          } else {
            // 结果图片聚合：最新的放在最前面
            if (currentResultImage.length > 0) {
              if (item.completed_at_ts > existing.completed_at_ts) {
                existing.result_images = currentResultImage.concat(existing.result_images);
              } else {
                existing.result_images = existing.result_images.concat(currentResultImage);
              }
            }

            // 使用最新一条记录的文案、时间、状态等
            if (item.completed_at_ts > existing.completed_at_ts) {
              existing.id = item.id;
              existing.title = item.title;
              existing.content_text = item.content_text;
              existing.label = item.label;
              existing.status = item.status;
              existing.created_date = item.created_date;
              existing.completed_at_ts = item.completed_at_ts;
              existing.result_image = item.result_image || existing.result_image;
              // face/cloth 图片保持不变（相同素材）
            }

            // 追加记录ID
            if (!existing.record_ids) {
              existing.record_ids = [];
            }
            existing.record_ids.push(item.id);

            // 累加成员，便于后续选择基准文案
            if (!existing.members) existing.members = [];
            existing.members.push({
              id: item.id,
              title: item.title,
              content_text: item.content_text,
              label: item.label,
              status: item.status,
              created_date: item.created_date,
              completed_at_ts: item.completed_at_ts,
            });
          }
        }

        // 将聚合结果转成数组，并同步 additional_images（用于列表+N展示）
        const groupedData = Array.from(groupedMap.values()).map(group => {
          const uniqueByPath = (images) => {
            const seen = new Set();
            const result = [];
            for (const img of images || []) {
              const key = img?.stored_path || JSON.stringify(img || {});
              if (!seen.has(key)) {
                seen.add(key);
                result.push(img);
              }
            }
            return result;
          };

          const allResults = uniqueByPath(group.result_images || (group.result_image ? [group.result_image] : []));
          // 选择该组合的“基准记录”：优先使用上次保存偏好，否则取最新时间
          const preferredId = getPreferredRecordId(group.groupKey);
          const canonicalMember = (preferredId && group.members?.find(m => String(m.id) === String(preferredId)))
            || (group.members || []).reduce((acc, cur) => (cur.completed_at_ts > acc.completed_at_ts ? cur : acc), (group.members || [group])[0]);

          return {
            ...group,
            id: canonicalMember?.id ?? group.id,
            title: canonicalMember?.title ?? group.title,
            content_text: canonicalMember?.content_text ?? group.content_text,
            label: canonicalMember?.label ?? group.label,
            status: canonicalMember?.status ?? group.status,
            created_date: canonicalMember?.created_date ?? group.created_date,
            completed_at_ts: canonicalMember?.completed_at_ts ?? group.completed_at_ts,
            result_image: allResults[0] || group.result_image || null,
            additional_images: allResults.slice(1),
            result_images: allResults,
            record_ids: Array.isArray(group.record_ids) ? Array.from(new Set(group.record_ids)) : [group.id],
          };
        });

        setGeneratedContents(groupedData);
        setPagination(prev => ({
          ...prev,
          total: groupedData.length,
        }));
        console.log('历史记录加载并合并成功（全量），原始记录', (firstResp.total || transformedData.length), '条，合并后', groupedData.length, '条');
      } else {
        console.warn('历史记录响应格式异常:', response);
        setGeneratedContents([]);
      }
    } catch (error) {
      console.error('加载历史记录失败:', error);
      console.error('错误详情:', error.message);
      console.error('错误堆栈:', error.stack);
      setGeneratedContents([]);
    } finally {
      setLoading(false);
    }
  };

  const handleViewDetail = async (content) => {
    if (!isAuthenticated || !user?.id) {
      console.log('用户未登录或ID无效，无法查看详情');
      return;
    }

    try {
      setDetailLoading(true);
      setSelectedRecord(content);
      console.log('开始获取处理详情，记录ID:', content.id);

      // 调用后端API获取处理详情
      const response = await aiSwapAPI.getProcessDetail(content.id, user.id);
      console.log('处理详情响应:', response);

      if (response && response.process_record) {
        // 详细调试图片数据
        console.log('=== 图片数据调试 ===');
        console.log('完整响应数据:', response);
        console.log('人脸图片数据:', response.face_image);
        console.log('服装图片数据:', response.cloth_image);
        console.log('结果图片数据:', response.result_image);
        
        // 检查图片路径
        if (response.face_image) {
          console.log('人脸图片URL:', getImageUrl(response.face_image));
        }
        if (response.cloth_image) {
          console.log('服装图片URL:', getImageUrl(response.cloth_image));
        }
        if (response.result_image) {
          console.log('结果图片URL:', getImageUrl(response.result_image));
        }
        
        // 如果该卡片是合并后的记录，则把所有结果图片一起带入详情
        // 为了支持删除单张结果图，需要为每张图保留其来源的 process_id
        let groupRecordIds = Array.isArray(content.record_ids) && content.record_ids.length > 0
          ? Array.from(new Set(content.record_ids))
          : [content.id];

        // 拉取该组合内所有记录的详情，构建 { image, process_id } 列表
        let resultImagesMeta = [];
        try {
          const allDetails = await Promise.all(
            groupRecordIds.map(pid => aiSwapAPI.getProcessDetail(pid, user.id).catch(() => null))
          );
          resultImagesMeta = allDetails
            .filter(d => d && d.result_image)
            .map(d => ({ image: d.result_image, process_id: d.process_record?.id }));
        } catch (_) {}

        const mergedSelected = {
          ...response,
          result_images: resultImagesMeta.length > 0
            ? resultImagesMeta.map(m => m.image)
            : ((content.result_images && content.result_images.length > 0)
                ? content.result_images
                : (response.result_image ? [response.result_image] : [])),
          result_images_meta: resultImagesMeta,
        };
        // 同步首图与额外图，便于已有的渲染逻辑复用
        mergedSelected.result_image = mergedSelected.result_images[0] || response.result_image || null;
        mergedSelected.additional_images = (mergedSelected.result_images || []).slice(1);
        // 关键：保留合并卡片的所有记录ID，便于批量审核
        mergedSelected.record_ids = Array.isArray(content.record_ids) && content.record_ids.length > 0
          ? Array.from(new Set(content.record_ids))
          : [content.id];

        setSelectedRecord(mergedSelected);
        setDetailModalVisible(true);
      } else {
        console.warn('处理详情响应格式异常:', response);
        // 显示错误提示
        alert('获取处理详情失败，请稍后重试');
      }
    } catch (error) {
      console.error('获取详情失败:', error);
      // 显示错误提示
      alert('获取处理详情失败：' + error.message);
    } finally {
      setDetailLoading(false);
    }
  };

  // 删除结果图片（整条记录的结果图）
  const handleDeleteResultImage = async (processId) => {
    if (!isAuthenticated || !user?.id) return;
    try {
      if (!window.confirm('确定要删除该结果图片吗？删除后不可恢复。')) return;
      await aiSwapAPI.deleteResultImage(processId, user.id);
      // 本地同步：仅移除被删除对应 processId 的那一张
      if (selectedRecord) {
        const updated = { ...selectedRecord };
        const metas = Array.isArray(updated.result_images_meta) ? updated.result_images_meta.slice() : [];
        const filtered = metas.filter(m => String(m.process_id) !== String(processId));
        updated.result_images_meta = filtered;
        updated.result_images = filtered.map(m => m.image);
        updated.additional_images = (updated.result_images || []).slice(1);
        // 若当前主图属于被删项，重置首图
        if (updated.result_image && filtered.every(m => getImageUrl(m.image) !== getImageUrl(updated.result_image))) {
          updated.result_image = updated.result_images[0] || null;
        }
        setSelectedRecord(updated);
      }
      alert('删除成功');
    } catch (e) {
      alert('删除失败：' + (e.message || '未知错误'));
    }
  };

  // 下载当前卡片的所有结果图 + 文本信息(txt)
  const handleDownload = async (content) => {
    try {
      const title = content.title || `记录#${content.id}`;
      const textLines = [
        `标题: ${content.title || ''}`,
        `文案: ${content.content_text || ''}`,
        `标签: ${content.label || ''}`,
      ];
      const txtBlob = new Blob([textLines.join('\n')], { type: 'text/plain;charset=utf-8' });
      downloadBlob(txtBlob, `${sanitizeFilename(title)}.txt`);

      const resultImages = [];
      if (content.result_image) resultImages.push(content.result_image);
      if (Array.isArray(content.additional_images) && content.additional_images.length > 0) {
        resultImages.push(...content.additional_images);
      }

      if (resultImages.length === 0) return;

      // 逐个下载图片（避免并发过高触发浏览器限制）
      for (let i = 0; i < resultImages.length; i++) {
        const img = resultImages[i];
        // 优先走后端带CORS的直链
        let url = getImageUrl(img);
        try {
          const base = import.meta.env.VITE_API_BASE_URL || '';
          const name = getStoredFilename(img, 'image.png');
          if (img?.image_type === 'result' || (img?.stored_path || '').includes('output')) {
            url = `${base}/api/v1/output/${name}`;
          } else {
            url = `${base}/api/v1/materials/${name}`;
          }
        } catch {}
        if (!url) continue;
        const fallback = `${sanitizeFilename(title)}_${i + 1}.png`;
        const filename = sanitizeFilename(getStoredFilename(img, fallback));
        await downloadUrl(url, filename);
      }
    } catch (e) {
      console.error('下载失败:', e);
      alert('下载失败：' + (e.message || '未知错误'));
    }
  };

  const getPlatformName = (platform) => {
    const names = {
      xiaohongshu: '小红书',
      weibo: '微博',
      douyin: '抖音',
      bilibili: 'B站',
      ai_swap: 'AI换脸换装'
    };
    return names[platform] || platform;
  };

  const getStatusColor = (status) => {
    const colors = {
      '已发布': 'bg-green-100 text-green-700',
      '待发布': 'bg-orange-100 text-orange-700',
      '已审核': 'bg-blue-100 text-blue-700',
      '已拒绝': 'bg-red-100 text-red-700',
      '待审核': 'bg-yellow-100 text-yellow-700',
      'processing': 'bg-orange-100 text-orange-700',
      'failed': 'bg-red-100 text-red-700'
    };
    return colors[status] || 'bg-gray-100 text-gray-700';
  };

  const getStatusName = (status) => {
    const names = {
      '已发布': '已发布',
      '待发布': '待发布',
      '已审核': '已审核',
      '已拒绝': '已拒绝',
      '待审核': '待审核',
      'processing': '处理中',
      'failed': '处理失败'
    };
    return names[status] || status;
  };

  const filteredContents = generatedContents.filter(content => {
    const searchLower = (searchTerm || '').trim().toLowerCase();
    if (!searchLower) {
      const matchesStatus = filterStatus === 'all' || content.status === filterStatus;
      const matchesPlatform = filterPlatform === 'all' || content.platform === filterPlatform;
      return matchesStatus && matchesPlatform;
    }

    // 组装可搜索字段：标题、文案、标签、创建时间（本地化+ISO日期）
    const createdIsoDate = (() => {
      try { return new Date(content.completed_at_ts).toISOString().slice(0, 10); } catch { return ''; }
    })();

    const matchesSearch = (
      (content.title || '').toLowerCase().includes(searchLower) ||
      (content.content_text || '').toLowerCase().includes(searchLower) ||
      (content.label || '').toLowerCase().includes(searchLower) ||
      (content.created_date || '').toLowerCase().includes(searchLower) ||
      createdIsoDate.includes(searchLower)
    );
    const matchesStatus = filterStatus === 'all' || content.status === filterStatus;
    const matchesPlatform = filterPlatform === 'all' || content.platform === filterPlatform;
    return matchesSearch && matchesStatus && matchesPlatform;
  });

  const handlePaginationChange = (page, pageSize) => {
    setPagination(prev => ({
      ...prev,
      current: page,
      pageSize: pageSize || prev.pageSize,
    }));
  };

  // 处理编辑状态切换
  const handleEditToggle = () => {
    if (isEditing) {
      // 退出编辑模式，重置编辑内容
      setEditedText({
        title: extractTitle(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || '',
        content: extractContent(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || '',
        label: extractLabel(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || ''
      });
    } else {
      // 进入编辑模式，初始化编辑内容
      setEditedText({
        title: extractTitle(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || '',
        content: extractContent(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || '',
        label: extractLabel(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || ''
      });
    }
    setIsEditing(!isEditing);
  };

  // 处理保存
  const handleSave = async () => {
    if (!isAuthenticated || !user?.id) {
      console.log('用户未登录或ID无效，无法保存');
      return;
    }

    try {
      setIsSaving(true);
      console.log('准备保存数据:', {
        processId: selectedRecord.process_record?.id || selectedRecord.id,
        userId: user.id,
        editedText
      });

      // 将本次保存所属组合固定为当前显示ID，避免下次合并选择其他拆分记录
      const currentFaceId = selectedRecord.process_record?.face_image_id || selectedRecord.face_image_id;
      const currentClothId = selectedRecord.process_record?.cloth_image_id || selectedRecord.cloth_image_id;
      if (currentFaceId && currentClothId) {
        const groupKey = getGroupKey(currentFaceId, currentClothId);
        setPreferredRecordId(groupKey, selectedRecord.process_record?.id || selectedRecord.id);
      }

      const response = await aiSwapAPI.updateProcessText(
        selectedRecord.process_record?.id || selectedRecord.id,
        user.id,
        {
          title: editedText.title.trim(),
          content: editedText.content.trim(),
          label: editedText.label.trim()
        }
      );

      console.log('保存响应:', response);

      if (response && response.process_record) {
        // 更新本地数据
        setSelectedRecord(response);
        
        // 退出编辑模式
        setIsEditing(false);
        
        // 显示成功提示
        alert('保存成功！');
        
        // 刷新列表
        await loadHistory();
      } else {
        throw new Error('服务器响应格式错误');
      }
    } catch (error) {
      console.error('保存失败:', error);
      alert('保存失败：' + (error.message || '未知错误'));
    } finally {
      setIsSaving(false);
    }
  };

  // 处理审核通过
  const handleApprove = async () => {
    if (!isAuthenticated || !user?.id) {
      console.log('用户未登录或ID无效，无法审核');
      return;
    }

    try {
      setIsApproving(true);
      console.log('准备审核记录:', {
        processId: selectedRecord.process_record?.id || selectedRecord.id,
        userId: user.id
      });

      // 组内所有记录ID（若没有则退化为当前ID）
      const recordIds = (selectedRecord && Array.isArray(selectedRecord.record_ids) && selectedRecord.record_ids.length > 0)
        ? selectedRecord.record_ids
        : [selectedRecord.process_record?.id || selectedRecord.id];

      console.log('准备批量审核记录 IDs:', recordIds);

      // 逐条调用审核接口
      for (const pid of recordIds) {
        try {
          const res = await aiSwapAPI.approveProcessRecord(pid, user.id);
          if (!res || !res.success) {
            throw new Error(res?.message || '未知错误');
          }
        } catch (e) {
          console.error(`记录 ${pid} 审核失败:`, e);
          throw new Error(`记录 ${pid} 审核失败: ${e.message}`);
        }
      }

      // 更新本地选中记录的显示状态
      // 更新选中记录与列表中对应分组的状态
      if (selectedRecord.process_record) {
        selectedRecord.process_record.status = '已审核';
      }
      selectedRecord.status = '已审核';
      setSelectedRecord({ ...selectedRecord });

      // 同步当前页面卡片状态（按 record_ids 找到对应项）
      setGeneratedContents(prev => prev.map(item => {
        const ids = item.record_ids || [item.id];
        const anyMatched = ids.some(id => (selectedRecord.record_ids || []).includes(id));
        return anyMatched ? { ...item, status: '已审核' } : item;
      }));

      alert('审核通过成功！');
      await loadHistory();
    } catch (error) {
      console.error('审核失败:', error);
      alert('审核失败：' + (error.message || '未知错误'));
    } finally {
      setIsApproving(false);
    }
  };

  return (
    <div className="p-6">
      <div className="max-w-7xl mx-auto">
        {/* 页面标题 */}
        <div className="mb-8">
          <h1 className="text-3xl font-bold text-slate-900 mb-2">历史记录</h1>
        </div>

        {/* 筛选器 */}
        <div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 mb-6">
          <div className="flex flex-col md:flex-row gap-4">
            <div className="relative flex-1">
              <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-slate-400 w-4 h-4" />
              <Input
                placeholder="搜索 标题/文案/标签/创建时间(如 2025/8/13) ..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="pl-10"
              />
            </div>
            
            <Select value={filterStatus} onValueChange={setFilterStatus}>
              <SelectTrigger className="w-full md:w-40">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">全部状态</SelectItem>
                <SelectItem value="待审核">待审核</SelectItem>
                <SelectItem value="已审核">已审核</SelectItem>
                <SelectItem value="已发布">已发布</SelectItem>
                <SelectItem value="待发布">待发布</SelectItem>
                <SelectItem value="已拒绝">已拒绝</SelectItem>
                <SelectItem value="processing">处理中</SelectItem>
                <SelectItem value="failed">处理失败</SelectItem>
              </SelectContent>
            </Select>
            
            <Select value={filterPlatform} onValueChange={setFilterPlatform}>
              <SelectTrigger className="w-full md:w-40">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">全部平台</SelectItem>
                <SelectItem value="ai_swap">AI换脸换装</SelectItem>
                <SelectItem value="xiaohongshu">小红书</SelectItem>
                <SelectItem value="douyin">抖音</SelectItem>
                <SelectItem value="weibo">微博</SelectItem>
                <SelectItem value="bilibili">B站</SelectItem>
              </SelectContent>
            </Select>
            
            <Button onClick={loadHistory} variant="outline" disabled={loading}>
              {loading ? (
                <Loader2 className="w-4 h-4 mr-2 animate-spin" />
              ) : (
                <RefreshCw className="w-4 h-4 mr-2" />
              )}
              刷新
            </Button>
          </div>
        </div>
        {/* 内容生成历史 */}
        <div>
          <div className="flex items-center gap-2 mb-4">
            <Clock className="w-5 h-5 text-slate-600" />
            <h2 className="text-xl font-semibold text-slate-900">
              内容生成历史 ({pagination.total} 条记录)
            </h2>
          </div>
          
          <div className="grid gap-4">
            <AnimatePresence>
              {loading ? (
                <Card>
                  <CardContent className="p-12 text-center">
                    <Loader2 className="w-8 h-8 text-slate-400 mx-auto mb-4 animate-spin" />
                    <p className="text-slate-600">正在加载历史记录...</p>
                  </CardContent>
                </Card>
              ) : filteredContents.length > 0 ? (
                filteredContents.map((content) => (
                  <motion.div
                    key={content.id}
                    initial={{ opacity: 0, y: 20 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: -20 }}
                    transition={{ duration: 0.3 }}
                  >
                    <Card className="border border-slate-200">
                      <CardContent className="p-6">
                        <div className="flex items-start justify-between">
                          <div className="flex-1">
                            <div className="flex items-center gap-2 mb-2">
                              <h3 className="text-lg font-semibold text-slate-900 line-clamp-1">
                                {content.title}
                              </h3>
                              <Badge className={getStatusColor(content.status)}>
                                {getStatusName(content.status)}
                              </Badge>
                              {/* <Badge className="bg-purple-100 text-purple-700">
                                {getPlatformName(content.platform)}
                              </Badge> */}
                            </div>
                            
                            <p className="text-slate-600 text-sm leading-relaxed mb-3 line-clamp-3">
                              {content.content_text}
                            </p>
                            <p className="text-slate-600 text-sm leading-relaxed mb-3 line-clamp-3">
                              {content.label} 
                            </p>
                            
                            <p className="text-xs text-slate-500 mb-3">
                              创建时间: {content.created_date}
                            </p>

                            {/* 图片预览区域 */}
                            <div className="flex gap-2">
                              {content.face_image && (
                                <div className="relative flex-shrink-0 group">
                                  <div className="w-16 h-16 bg-slate-100 rounded-lg overflow-hidden">
                                    <ImageWithFallback
                                      src={getImageUrl(content.face_image)}
                                      alt="人脸图片"
                                      className="w-full h-full object-cover"
                                    />
                                  </div>
                                  <div className="pointer-events-none absolute left-1/2 -translate-x-1/2 top-full mt-2 z-50 hidden group-hover:block">
                                    {isVideoFile(getImageUrl(content.face_image)) ? (
                                      <video 
                                        src={getImageUrl(content.face_image)} 
                                        className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" 
                                        autoPlay 
                                        muted 
                                        loop 
                                        playsInline
                                        controls={false}
                                      />
                                    ) : (
                                      <img src={getImageUrl(content.face_image)} alt="人脸图片预览" className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" />
                                    )}
                                  </div>
                                </div>
                              )}
                              {content.cloth_image && (
                                <div className="relative flex-shrink-0 group">
                                  <div className="w-16 h-16 bg-slate-100 rounded-lg overflow-hidden">
                                    <ImageWithFallback
                                      src={getImageUrl(content.cloth_image)}
                                      alt="服装图片"
                                      className="w-full h-full object-cover"
                                    />
                                  </div>
                                  <div className="pointer-events-none absolute left-1/2 -translate-x-1/2 top-full mt-2 z-50 hidden group-hover:block">
                                    {isVideoFile(getImageUrl(content.cloth_image)) ? (
                                      <video 
                                        src={getImageUrl(content.cloth_image)} 
                                        className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" 
                                        autoPlay 
                                        muted 
                                        loop 
                                        playsInline
                                        controls={false}
                                      />
                                    ) : (
                                      <img src={getImageUrl(content.cloth_image)} alt="服装图片预览" className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" />
                                    )}
                                  </div>
                                </div>
                              )}
                              {(content.result_image || (content.additional_images && content.additional_images.length > 0)) && (
                                <div className="w-px h-16 bg-slate-300 mx-2 rounded" />
                              )}
                              {content.result_image && (
                                <div className="relative flex-shrink-0 group">
                                  <div className="w-16 h-16 bg-slate-100 rounded-lg overflow-hidden">
                                    <ImageWithFallback
                                      src={getImageUrl(content.result_image)}
                                      alt="结果图片"
                                      className="w-full h-full object-cover"
                                    />
                                  </div>
                                  <div className="pointer-events-none absolute left-1/2 -translate-x-1/2 top-full mt-2 z-50 hidden group-hover:block">
                                    {isVideoFile(getImageUrl(content.result_image)) ? (
                                      <video 
                                        src={getImageUrl(content.result_image)} 
                                        className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" 
                                        autoPlay 
                                        muted 
                                        loop 
                                        playsInline
                                        controls={false}
                                      />
                                    ) : (
                                      <img src={getImageUrl(content.result_image)} alt="结果图片预览" className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" />
                                    )}
                                  </div>
                                </div>
                              )}
                              {content.additional_images && content.additional_images.length > 0 && (
                                <>
                                  {content.additional_images.map((img, idx) => (
                                    <div key={idx} className="relative flex-shrink-0 group">
                                      <div className="w-16 h-16 bg-slate-100 rounded-lg overflow-hidden">
                                        <ImageWithFallback
                                          src={getImageUrl(img)}
                                          alt={`结果图片${idx + 2}`}
                                          className="w-full h-full object-cover"
                                        />
                                      </div>
                                      <div className="pointer-events-none absolute left-1/2 -translate-x-1/2 top-full mt-2 z-50 hidden group-hover:block">
                                        {isVideoFile(getImageUrl(img)) ? (
                                          <video 
                                            src={getImageUrl(img)} 
                                            className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" 
                                            autoPlay 
                                            muted 
                                            loop 
                                            playsInline
                                            controls={false}
                                          />
                                        ) : (
                                          <img src={getImageUrl(img)} alt={`结果图片${idx + 2}预览`} className="max-h-[260px] max-w-[360px] rounded-lg shadow-xl border border-slate-200" />
                                        )}
                                      </div>
                                    </div>
                                  ))}
                                </>
                              )}
                            </div>
                          </div>
                          
                          <div className="flex items-center gap-2 ml-4">
                            <Button 
                              variant="ghost" 
                              size="sm"
                              onClick={() => handleViewDetail(content)}
                              disabled={detailLoading}
                            >
                              {detailLoading && selectedRecord?.id === content.id ? (
                                <Loader2 className="w-4 h-4 animate-spin" />
                              ) : (
                                <Eye className="w-4 h-4" />
                              )}
                            </Button>
                            <Button variant="ghost" size="sm" onClick={() => handleDownload(content)}>
                              <Download className="w-4 h-4" />
                            </Button>
                          </div>
                        </div>
                      </CardContent>
                    </Card>
                  </motion.div>
                ))
              ) : (
                <Card>
                  <CardContent className="p-12 text-center">
                    <Search className="w-12 h-12 text-slate-400 mx-auto mb-4" />
                    <p className="text-slate-600">未找到匹配的历史记录</p>
                    <p className="text-sm text-slate-500 mt-1">尝试调整搜索条件或筛选器</p>
                  </CardContent>
                </Card>
              )}
            </AnimatePresence>
          </div>

          {/* 分页器 */}
          {pagination.total > 0 && (
            <div className="mt-6 flex justify-center">
              <div className="flex items-center gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handlePaginationChange(pagination.current - 1)}
                  disabled={pagination.current <= 1}
                >
                  上一页
                </Button>
                <span className="text-sm text-slate-600">
                  第 {pagination.current} 页，共 {Math.ceil(pagination.total / pagination.pageSize)} 页
                </span>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handlePaginationChange(pagination.current + 1)}
                  disabled={pagination.current >= Math.ceil(pagination.total / pagination.pageSize)}
                >
                  下一页
                </Button>
              </div>
            </div>
          )}
        </div>
      </div>

      {/* 详情模态框 */}
      {detailModalVisible && selectedRecord && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 max-w-4xl max-h-[90vh] overflow-y-auto">
            <div className="flex justify-between items-center mb-4">
              <h3 className="text-lg font-semibold">记录详情</h3>
              <div className="flex gap-2">
                {/* 审核通过按钮 - 只在待审核状态下显示 */}
                {(selectedRecord.process_record?.status === '待审核' || selectedRecord.status === '待审核') && (
                  <Button
                    variant="default"
                    size="sm"
                    className="bg-green-500 hover:bg-green-600 text-white"
                    onClick={handleApprove}
                    disabled={isApproving || isSaving}
                  >
                    {isApproving ? (
                      <>
                        <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                        审核中
                      </>
                    ) : (
                      '审核通过'
                    )}
                  </Button>
                )}
                <Button
                  variant={isEditing ? "default" : "outline"}
                  size="sm"
                  className="bg-blue-400 hover:bg-blue-400 text-white"
                  onClick={handleEditToggle}
                  disabled={isSaving || isApproving}
                >
                  {isEditing ? '取消' : '编辑'}
                </Button>
                {isEditing && (
                  <Button
                    variant="default"
                    size="sm"
                    className="bg-green-400 hover:bg-green-400"
                    onClick={handleSave}
                    disabled={isSaving || isApproving}
                  >
                    {isSaving ? (
                      <>
                        <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                        保存中
                      </>
                    ) : (
                      '保存'
                    )}
                  </Button>
                )}
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => setDetailModalVisible(false)}
                  disabled={isSaving || isApproving}
                >
                  ✕
                </Button>
              </div>
            </div>

            <div className="space-y-4">
              {/* 基本信息 */}
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="text-sm font-medium text-slate-600">ID</label>
                  <p className="text-sm"> {selectedRecord.process_record?.id || selectedRecord.id}</p>
                </div>
                <div>
                  <label className="text-sm font-medium text-slate-600">状态</label>
                  <p className="text-sm">
                    {getStatusName(selectedRecord.process_record?.status || selectedRecord.status)}
                  </p>
                </div>
                <div>
                  <label className="text-sm font-medium text-slate-600">处理时间</label>
                  <p className="text-sm">
                    {new Date(selectedRecord.process_record?.completed_at || selectedRecord.completed_at).toLocaleString()}
                  </p>
                </div>
              </div>

              {/* 文案信息 */}
              <div>
                <label className="text-sm font-bold text-slate-600">标题</label>
                {isEditing ? (
                  <Input
                    value={editedText.title}
                    onChange={(e) => setEditedText(prev => ({ ...prev, title: e.target.value }))}
                    className="mt-1"
                    placeholder="请输入标题"
                  />
                ) : (
                  <p className="text-sm mt-1 p-3 bg-slate-50 rounded">
                    {extractTitle(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || '无文案内容'}
                  </p>
                )}

                <label className="text-sm font-bold text-slate-600 mt-4 block">文案</label>
                {isEditing ? (
                  <textarea
                    value={editedText.content}
                    onChange={(e) => setEditedText(prev => ({ ...prev, content: e.target.value }))}
                    className="w-full mt-1 p-2 border rounded-md"
                    rows={4}
                    placeholder="请输入文案内容"
                  />
                ) : (
                  <p className="text-sm mt-1 p-3 bg-slate-50 rounded whitespace-pre-line">
                    {extractContent(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || '无文案内容'}
                  </p>
                )}

                <label className="text-sm font-bold text-slate-600 mt-4 block">话题标签</label>
                {isEditing ? (
                  <Input
                    value={editedText.label}
                    onChange={(e) => setEditedText(prev => ({ ...prev, label: e.target.value }))}
                    className="mt-1"
                    placeholder="请输入话题标签"
                  />
                ) : (
                  <p className="text-sm mt-1 p-3 bg-slate-50 rounded">
                    {extractLabel(selectedRecord.process_record?.generated_text || selectedRecord.generated_text) || '无话题标签'}
                  </p>
                )}
              </div>

              {/* 图片信息：第一行并排显示人脸与服装 */}
              <div className="grid grid-cols-2 gap-4">
                {/* 人脸图片 */}
                <div>
                  <label className="text-sm font-bold text-slate-600">人脸图片</label>
                  <div className={`mt-2 w-full ${previewSizeClass} bg-slate-100 rounded overflow-hidden`}>
                    {selectedRecord.face_image && selectedRecord.face_image.stored_path ? (
                      <ImageWithFallback
                        src={getImageUrl(selectedRecord.face_image)}
                        alt="人脸图片"
                        className="w-full h-full object-cover"
                      />
                    ) : (
                      <div className="w-full h-full flex items-center justify-center">
                        <span className="text-xs text-slate-500">无媒体数据</span>
                      </div>
                    )}
                  </div>
                </div>

                {/* 服装图片 */}
                <div>
                  <label className="text-sm font-bold text-slate-600">服装图片</label>
                  <div className={`mt-2 w-full ${previewSizeClass} bg-slate-100 rounded overflow-hidden`}>
                    {selectedRecord.cloth_image && selectedRecord.cloth_image.stored_path ? (
                      <ImageWithFallback
                        src={getImageUrl(selectedRecord.cloth_image)}
                        alt="服装图片"
                        className="w-full h-full object-cover"
                      />
                    ) : (
                      <div className="w-full h-full flex items-center justify-center">
                        <span className="text-xs text-slate-500">无媒体数据</span>
                      </div>
                    )}
                  </div>
                </div>
              </div>

              {/* 第二行：结果图片（支持多张），尺寸与上面一致 */}
              <div className="mt-6 relative">
                <label className="text-sm font-bold text-slate-600 relative z-10">结果图片</label>
                {(selectedRecord.result_images_meta && selectedRecord.result_images_meta.length > 0) ? (
                  <div className="mt-2 grid grid-cols-2 gap-4">
                    {selectedRecord.result_images_meta.map((meta, idx) => (
                      <div key={idx} className="relative group">
                        <div className={`w-full ${previewSizeClass} bg-slate-100 rounded overflow-hidden`}>
                          <ImageWithFallback
                            src={getImageUrl(meta.image)}
                            alt={`结果图片${idx + 1}`}
                            className="w-full h-full object-cover"
                          />
                        </div>
                        <button
                          title="删除该结果图"
                          onClick={() => handleDeleteResultImage(meta.process_id)}
                          className="absolute top-2 right-2 hidden group-hover:flex items-center gap-1 bg-red-500 hover:bg-red-600 text-white text-xs px-2 py-1 rounded"
                        >
                          <Trash2 className="w-3 h-3" /> 删除
                        </button>
                      </div>
                    ))}
                  </div>
                ) : selectedRecord.result_images && selectedRecord.result_images.length > 0 ? (
                  <div className="mt-2 grid grid-cols-2 gap-4">
                    {selectedRecord.result_images.map((img, idx) => (
                      <div key={idx} className="relative group">
                        <div className={`w-full ${previewSizeClass} bg-slate-100 rounded overflow-hidden`}>
                          <ImageWithFallback
                            src={getImageUrl(img)}
                            alt={`结果图片${idx + 1}`}
                            className="w-full h-full object-cover"
                          />
                        </div>
                      </div>
                    ))}
                  </div>
                ) : (
                  <div className={`mt-2 w-full ${previewSizeClass} bg-slate-100 rounded overflow-hidden`}>
                    {selectedRecord.result_image && selectedRecord.result_image.stored_path ? (
                      <ImageWithFallback
                        src={getImageUrl(selectedRecord.result_image)}
                        alt="结果图片"
                        className="w-full h-full object-cover"
                      />
                    ) : (
                      <div className="w-full h-full flex items-center justify-center">
                        <span className="text-xs text-slate-500">无媒体数据</span>
                      </div>
                    )}
                  </div>
                )}
              </div>

              {/* 文案建议 */}
              {selectedRecord.process_record?.copywriter_text && (
                <div>
                  <label className="text-sm font-medium text-slate-600">文案建议</label>
                  <p className="text-sm mt-1 p-3 bg-blue-50 rounded">
                    {selectedRecord.process_record.copywriter_text}
                  </p>
                </div>
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}