import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  Button,
  Card,
  Empty,
  Input,
  message,
  Modal,
  Select,
  Space,
  Table,
  Tag,
  Tooltip,
  Typography,
} from 'antd';
import {
  PlayCircleOutlined,
  EyeOutlined,
  ClockCircleOutlined,
  CheckCircleOutlined,
  LoadingOutlined,
  CloseCircleOutlined,
  SearchOutlined,
  VideoCameraOutlined,
  ExclamationCircleOutlined,
  FileImageOutlined,
} from '@ant-design/icons';
import { getAdminGenerationRecords, adminUpdateGenerationStatus, adminGenerateVideo } from '../api';
import type { AdminGenerationRecord, GenerationAIMediaReference } from '../types';
import { formatDate } from '../utils/formatDate';

const RAW_API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:8000';
// 后端返回的图片/视频一般是 /images、/videos、/uploads 等相对路径。
// 如果 VITE_API_BASE 配置为 http://host/api，这里需要去掉末尾 /api，避免资源被拼成 /api/images 导致 404。
const RESOURCE_BASE = RAW_API_BASE.replace(/\/api\/?$/i, '').replace(/\/$/, '');

type ResourceState = 'empty' | 'checking' | 'valid' | 'invalid';

interface PreviewResourceState {
  image: ResourceState;
  video: ResourceState;
  videoCover: ResourceState;
  references: Record<string, ResourceState>;
}

const EMPTY_RESOURCE_STATE: PreviewResourceState = {
  image: 'empty',
  video: 'empty',
  videoCover: 'empty',
  references: {},
};

const STATUS_MAP: Record<string, { color: string; text: string; icon: React.ReactNode }> = {
  optimizing: { color: 'processing', text: '优化中', icon: <LoadingOutlined spin /> },
  prompt_optimized: { color: 'processing', text: '待生成', icon: <ClockCircleOutlined /> },
  generating: { color: 'warning', text: '生成中', icon: <LoadingOutlined spin /> },
  completed: { color: 'success', text: '已完成', icon: <CheckCircleOutlined /> },
  failed: { color: 'error', text: '失败', icon: <CloseCircleOutlined /> },
};

const GEN_TYPE_MAP: Record<string, { text: string; color: string; icon: React.ReactNode }> = {
  image: { text: '图片', color: 'purple', icon: <FileImageOutlined /> },
  video: { text: '视频', color: 'geekblue', icon: <VideoCameraOutlined /> },
};

const isAbsoluteLikeUrl = (url: string): boolean => (
  /^(https?:)?\/\//i.test(url) || /^(blob|data):/i.test(url)
);

const isBlobUrl = (url?: string | null): boolean => !!url && /^blob:/i.test(url.trim());

const apiUrl = (url?: string | null): string => {
  if (!url) return '';
  const value = String(url).trim();
  if (!value) return '';
  if (isAbsoluteLikeUrl(value)) return value;

  if (!RESOURCE_BASE) {
    return value.startsWith('/') ? value : `/${value}`;
  }
  return `${RESOURCE_BASE}${value.startsWith('/') ? value : `/${value}`}`;
};

const truncateId = (value?: string | null): string => {
  if (!value) return '-';
  return value.length > 12 ? `${value.slice(0, 8)}...` : value;
};

const safeDate = (value?: string | null): string => {
  if (!value) return '-';
  return formatDate(value);
};

const isEmptyValue = (value: React.ReactNode): boolean => (
  value === null || value === undefined || value === ''
);

const isUrlExpired = (url?: string | null): boolean => {
  if (!url || isBlobUrl(url)) return false;

  try {
    const parsed = new URL(apiUrl(url), window.location.origin);
    const expireValue =
      parsed.searchParams.get('exp') ||
      parsed.searchParams.get('expires') ||
      parsed.searchParams.get('expire') ||
      parsed.searchParams.get('expires_at') ||
      parsed.searchParams.get('x-expires');

    if (!expireValue) return false;

    const expireNumber = Number(expireValue);
    if (!Number.isFinite(expireNumber)) return false;

    const expireMs = expireNumber > 10_000_000_000 ? expireNumber : expireNumber * 1000;
    return Date.now() >= expireMs;
  } catch {
    return false;
  }
};

const getInitialResourceState = (url?: string | null): ResourceState => {
  if (!url) return 'empty';
  if (isBlobUrl(url)) return 'invalid';
  if (isUrlExpired(url)) return 'invalid';
  return 'checking';
};

const getReferenceUrl = (ref: GenerationAIMediaReference): string | undefined => {
  const value = ref.url || ref.mediaUrl || ref.fileUrl;
  return typeof value === 'string' && value.trim() ? value.trim() : undefined;
};

const getReferenceType = (ref: GenerationAIMediaReference): string => {
  const rawType = String(ref.type || ref.mediaType || ref.mimeType || '').toLowerCase();
  const url = getReferenceUrl(ref)?.toLowerCase() || '';

  if (rawType.includes('video') || /\.(mp4|mov|webm|m4v)(\?|$)/i.test(url)) return 'video';
  if (rawType.includes('image') || /\.(png|jpe?g|webp|gif|bmp|svg)(\?|$)/i.test(url)) return 'image';
  return rawType || 'unknown';
};

const getReferenceKey = (ref: GenerationAIMediaReference, index: number): string => {
  const refUrl = getReferenceUrl(ref) || 'empty';
  return `${index}-${refUrl}`;
};

const getMediaInvalidText = (url?: string | null, type = '资源'): string => {
  if (isBlobUrl(url)) return '本地临时素材已失效';
  if (isUrlExpired(url)) return `${type}链接已超时，请刷新列表或重新搜索后再查看`;
  return `${type}加载失败，请刷新列表或重新搜索后再查看`;
};

const MediaPlaceholder: React.FC<{
  text: string;
  minHeight?: number;
  compact?: boolean;
  action?: React.ReactNode;
}> = ({ text, minHeight = 240, compact = false, action }) => (
  <div
    style={{
      width: '100%',
      minHeight: compact ? undefined : minHeight,
      height: compact ? '100%' : undefined,
      borderRadius: compact ? 10 : 12,
      background: '#f8f9fc',
      border: '1px dashed #cbd5e1',
      color: '#64748b',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      flexDirection: 'column',
      gap: compact ? 4 : 10,
      textAlign: 'center',
    }}
  >
    <Typography.Text style={{ color: '#64748b', fontSize: compact ? 11 : 13 }}>{text}</Typography.Text>
    {action}
  </div>
);

const InfoItem: React.FC<{ label: string; value?: React.ReactNode }> = ({ label, value }) => (
  <div style={{ flex: 1, minWidth: 120 }}>
    <Typography.Text style={{ fontSize: 11, color: '#94a3b8', display: 'block' }}>{label}</Typography.Text>
    <Typography.Text strong style={{ fontSize: 14 }}>{isEmptyValue(value) ? '-' : value}</Typography.Text>
  </div>
);

const AdminGenerationRecords: React.FC = () => {
  const [records, setRecords] = useState<AdminGenerationRecord[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [page, setPage] = useState(1);
  const [pageSize] = useState(20);
  const [filterStatus, setFilterStatus] = useState<string>('');
  const [filterUserId, setFilterUserId] = useState<string>('');
  const [reloadKey, setReloadKey] = useState(0);
  const [preview, setPreview] = useState<AdminGenerationRecord | null>(null);
  const [resourceState, setResourceState] = useState<PreviewResourceState>(EMPTY_RESOURCE_STATE);
  const [videoPlaying, setVideoPlaying] = useState(false);
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const [updating, setUpdating] = useState<string | null>(null);
  const [genModal, setGenModal] = useState<{ record: AdminGenerationRecord; ratio: string; resolution: string; image_size: string } | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const res = await getAdminGenerationRecords({
        userId: filterUserId.trim() || undefined,
        status: filterStatus || undefined,
        page,
        pageSize,
      });
      setRecords((res.items || []).map((item: any) => ({
        id: item.id,
        userId: item.userId,
        username: item.username,
        projectId: item.projectId,
        projectName: item.projectName,
        originalPrompt: item.originalPrompt,
        optimizedPrompt: item.optimizedPrompt,
        duration: item.duration,
        aspectRatio: item.aspectRatio,
        resolution: item.resolution,
        status: item.status,
        videoUrl: item.videoUrl,
        videoCoverUrl: item.videoCoverUrl,
        references: item.references,
        creditsCost: item.creditsCost || 0,
        textCreditsCost: item.textCreditsCost || 0,
        textTokensUsed: item.textTokensUsed || 0,
        videoTokensUsed: item.videoTokensUsed || 0,
        errorMessage: item.errorMessage,
        createdAt: item.createdAt,
        generatedAt: item.generatedAt,
        genType: item.genType,
        imageSize: item.imageSize,
        imageUrl: item.imageUrl,
        imageTokensUsed: item.imageTokensUsed || 0,
        imageProportion: item.imageProportion,
        imagePx: item.imagePx,
      })));
      setTotal(res.total || 0);
    } catch {
      message.error('加载记录失败');
    } finally {
      setLoading(false);
    }
  }, [filterStatus, filterUserId, page, pageSize]);

  useEffect(() => {
    load();
  }, [load, reloadKey]);

  useEffect(() => {
    if (!preview) {
      setResourceState(EMPTY_RESOURCE_STATE);
      return;
    }

    const references = preview.references || [];
    const initialReferences = references.reduce<Record<string, ResourceState>>((acc, ref, index) => {
      const refUrl = getReferenceUrl(ref);
      acc[getReferenceKey(ref, index)] = getInitialResourceState(refUrl);
      return acc;
    }, {});

    if (videoRef.current) {
      videoRef.current.pause();
      videoRef.current.currentTime = 0;
    }

    setVideoPlaying(false);
    setResourceState({
      image: getInitialResourceState(preview.imageUrl),
      video: getInitialResourceState(preview.videoUrl),
      videoCover: getInitialResourceState(preview.videoCoverUrl),
      references: initialReferences,
    });
  }, [preview]);

  const handleSearch = () => {
    setPage(1);
    setReloadKey((v) => v + 1);
  };

  const handleOpenPreview = useCallback((record: AdminGenerationRecord) => {
    setPreview(record);
  }, []);

  const handleClosePreview = () => {
    if (videoRef.current) {
      videoRef.current.pause();
    }
    setVideoPlaying(false);
    setPreview(null);
  };

  const patchResourceState = (patch: Partial<PreviewResourceState>) => {
    setResourceState((prev) => ({ ...prev, ...patch }));
  };

  const patchReferenceState = (key: string, state: ResourceState) => {
    setResourceState((prev) => ({
      ...prev,
      references: {
        ...prev.references,
        [key]: state,
      },
    }));
  };

  const handleOpenExternalResource = (url?: string | null, type = '素材') => {
    if (!url) {
      message.warning(`${type}链接为空，暂无法查看`);
      return;
    }

    if (isBlobUrl(url)) {
      message.warning('本地临时素材已失效，暂无法查看');
      return;
    }

    if (isUrlExpired(url)) {
      message.warning(`${type}链接已超时，请刷新列表或重新搜索后再查看`);
      return;
    }

    window.open(apiUrl(url), '_blank', 'noopener,noreferrer');
  };

  const handlePlayVideo = () => {
    if (!preview?.videoUrl) return;

    if (isUrlExpired(preview.videoUrl)) {
      patchResourceState({ video: 'invalid' });
      message.warning('视频链接已超时，请刷新列表或重新搜索后再查看');
      return;
    }

    setVideoPlaying(true);
    window.setTimeout(() => {
      videoRef.current?.play().catch(() => {
        setVideoPlaying(false);
        patchResourceState({ video: 'invalid' });
        message.warning('视频播放失败，请确认资源链接是否仍然有效');
      });
    }, 0);
  };

  const handleStatusUpdate = async (recordId: string, newStatus: string, videoUrl?: string) => {
    setUpdating(recordId);
    try {
      await adminUpdateGenerationStatus(recordId, newStatus, videoUrl);
      message.success('状态已更新');
      load();
    } catch (e: any) {
      message.error(e?.message || '更新失败');
    } finally {
      setUpdating(null);
    }
  };

  const handleGenerate = async () => {
    if (!genModal) return;
    setUpdating(genModal.record.id);
    try {
      await adminGenerateVideo(genModal.record.id, genModal.ratio, genModal.resolution, genModal.image_size);
      message.success(`已提交${genModal.record.genType === 'video' ? '视频' : '图片'}生成`);
      setGenModal(null);
      load();
    } catch (e: any) {
      message.error(e?.message || '生成失败');
    } finally {
      setUpdating(null);
    }
  };

  const columns = useMemo(() => [
    {
      title: '用户', key: 'user', width: 120,
      render: (_: any, r: AdminGenerationRecord) => (
        <div>
          <Typography.Text strong style={{ fontSize: 13 }}>{r.username || '未知用户'}</Typography.Text>
          <div style={{ fontSize: 11, color: '#94a3b8' }}>{truncateId(r.userId)}</div>
        </div>
      ),
    },
    {
      title: '项目', dataIndex: 'projectName', width: 120, ellipsis: true,
      render: (v: string) => <Typography.Text style={{ fontSize: 13 }}>{v || '-'}</Typography.Text>,
    },
    {
      title: '类型', dataIndex: 'genType', width: 90, ellipsis: true,
      render: (v: string) => {
        const cfg = GEN_TYPE_MAP[v] || { text: v || '-', color: 'default', icon: null };
        return <Tag color={cfg.color} icon={cfg.icon}>{cfg.text}</Tag>;
      },
    },
    {
      title: '提示词', key: 'prompt', ellipsis: true,
      render: (_: any, r: AdminGenerationRecord) => (
        <Tooltip title={r.originalPrompt} placement="topLeft">
          <Typography.Text style={{ fontSize: 12, color: '#475569' }} ellipsis>
            {r.originalPrompt || '-'}
          </Typography.Text>
        </Tooltip>
      ),
    },
    {
      title: '参数', key: 'params', width: 160,
      render: (_: any, r: AdminGenerationRecord) => (
        r.genType === 'video' ? (
          r.duration || r.aspectRatio || r.resolution ? (
            <Space size={4} wrap>
              {r.duration ? <Tag>{r.duration}s</Tag> : null}
              {r.aspectRatio ? <Tag>{r.aspectRatio}</Tag> : null}
              {r.resolution ? <Tag>{r.resolution}</Tag> : null}
            </Space>
          ) : <Tag color="default">待配置</Tag>
        ) : (
          r.imageSize || r.imageProportion || r.imagePx ? (
            <Space size={4} wrap>
              {r.imageSize ? <Tag>{r.imageSize}</Tag> : null}
              {r.imageProportion ? <Tag>{r.imageProportion}</Tag> : null}
              {r.imagePx ? <Tag>{r.imagePx}</Tag> : null}
            </Space>
          ) : <Tag color="default">待配置</Tag>
        )
      ),
    },
    {
      title: '积分', key: 'credits', width: 120,
      render: (_: any, r: AdminGenerationRecord) => (
        <div style={{ fontSize: 12 }}>
          {r.textCreditsCost > 0 ? (
            <div style={{ color: '#f59e0b' }}>文字: {r.textCreditsCost}</div>
          ) : null}
          {r.creditsCost > 0 ? (
            <div style={{ color: '#6366f1' }}>{r.genType === 'video' ? '视频' : '图片'}: {r.creditsCost}</div>
          ) : null}
          {r.textCreditsCost === 0 && r.creditsCost === 0 ? (
            <Typography.Text style={{ color: '#94a3b8' }}>0</Typography.Text>
          ) : null}
        </div>
      ),
    },
    {
      title: '状态', dataIndex: 'status', width: 90,
      render: (v: string) => {
        const cfg = STATUS_MAP[v] || { color: 'default', text: v || '-', icon: null };
        return <Tag color={cfg.color} icon={cfg.icon}>{cfg.text}</Tag>;
      },
    },
    {
      title: '时间', key: 'time', width: 150,
      render: (_: any, r: AdminGenerationRecord) => (
        <div style={{ fontSize: 12, color: '#94a3b8' }}>
          <div>{safeDate(r.createdAt)}</div>
          {r.generatedAt ? <div style={{ color: '#10b981' }}>生成: {safeDate(r.generatedAt)}</div> : null}
        </div>
      ),
    },
    {
      title: '操作', key: 'action', width: 150, fixed: 'right' as const,
      render: (_: any, r: AdminGenerationRecord) => (
        <Space size={4} wrap>
          <Button size="small" icon={<EyeOutlined />} onClick={() => handleOpenPreview(r)}>
            详情
          </Button>
          {r.status === 'generating' ? (
            <Button
              size="small"
              danger
              loading={updating === r.id}
              onClick={() => {
                Modal.confirm({
                  title: '确认操作',
                  icon: <ExclamationCircleOutlined />,
                  content: '确定将此记录标记为失败？',
                  onOk: () => handleStatusUpdate(r.id, 'failed'),
                });
              }}
            >
              标记失败
            </Button>
          ) : null}
          {r.status === 'failed' ? (
            <Button
              size="small"
              type="primary"
              danger
              loading={updating === r.id}
              onClick={() => setGenModal({ record: r, ratio: r.aspectRatio || '16:9', resolution: r.resolution || '720p', image_size: r.imageSize || '2K' })}
            >
              重试生成
            </Button>
          ) : null}
          {r.status === 'prompt_optimized' ? (
            <>
              <Button
                size="small"
                type="primary"
                loading={updating === r.id}
                onClick={() => setGenModal({ record: r, ratio: r.aspectRatio || '16:9', resolution: r.resolution || '720p', image_size: r.imageSize || '2K' })}
                style={{ background: '#6366f1', border: 'none' }}
              >
                生成{r.genType === 'video' ? '视频' : '图片'}
              </Button>
              <Button
                size="small"
                danger
                loading={updating === r.id}
                onClick={() => {
                  Modal.confirm({
                    title: '确认操作',
                    icon: <ExclamationCircleOutlined />,
                    content: '确定将此记录标记为失败？',
                    onOk: () => handleStatusUpdate(r.id, 'failed'),
                  });
                }}
              >
                标记失败
              </Button>
            </>
          ) : null}
        </Space>
      ),
    },
  ], [handleOpenPreview, updating]);

  const previewTypeConfig = preview ? (GEN_TYPE_MAP[preview.genType || ''] || { text: preview.genType || '-', color: 'default', icon: null }) : null;
  const previewStatusConfig = preview ? (STATUS_MAP[preview.status] || { color: 'default', text: preview.status || '-', icon: null }) : null;

  const renderResultImage = () => {
    if (!preview || preview.genType !== 'image' || preview.status !== 'completed') return null;

    if (!preview.imageUrl) {
      return <MediaPlaceholder text="此图片任务暂无结果图片" minHeight={260} />;
    }

    if (resourceState.image === 'invalid') {
      return <MediaPlaceholder text={getMediaInvalidText(preview.imageUrl, '图片')} minHeight={260} />;
    }

    const src = apiUrl(preview.imageUrl);

    return (
      <div
        title="点击新页面查看图片"
        onClick={() => handleOpenExternalResource(preview.imageUrl, '生成图片')}
        style={{
          position: 'relative',
          width: '100%',
          minHeight: 260,
          borderRadius: 12,
          background: '#f8f9fc',
          border: '1px solid #e2e8f0',
          overflow: 'hidden',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          cursor: 'pointer',
        }}
      >
        <img
          key={`${preview.id}-${src}`}
          src={src}
          alt="生成图片"
          onLoad={() => patchResourceState({ image: 'valid' })}
          onError={() => patchResourceState({ image: 'invalid' })}
          style={{
            display: resourceState.image === 'valid' ? 'block' : 'none',
            width: '100%',
            maxHeight: 560,
            objectFit: 'contain',
            background: '#fff',
          }}
        />
        {resourceState.image === 'checking' ? (
          <MediaPlaceholder text="图片加载检测中..." minHeight={260} />
        ) : null}
      </div>
    );
  };

  const renderVideoMask = () => {
    if (!preview || videoPlaying || resourceState.video === 'invalid') return null;

    const canPlay = !!preview.videoUrl;
    const playButton = canPlay ? (
      <Button
        type="primary"
        shape="circle"
        size="large"
        icon={<PlayCircleOutlined />}
        onClick={handlePlayVideo}
        style={{ boxShadow: '0 8px 20px rgba(15,23,42,0.25)' }}
      />
    ) : null;

    if (!preview.videoCoverUrl) {
      return (
        <div
          style={{
            position: 'absolute',
            inset: 0,
            borderRadius: 12,
            overflow: 'hidden',
            background: '#f8f9fc',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
          }}
        >
          <MediaPlaceholder text="此视频无封面" minHeight={340} action={playButton} />
        </div>
      );
    }

    if (resourceState.videoCover === 'invalid') {
      return <MediaPlaceholder text={getMediaInvalidText(preview.videoCoverUrl, '视频封面')} minHeight={340} action={playButton} />;
    }

    const coverSrc = apiUrl(preview.videoCoverUrl);

    return (
      <div
        style={{
          position: 'absolute',
          inset: 0,
          borderRadius: 12,
          overflow: 'hidden',
          background: '#f8f9fc',
          border: '1px solid #e2e8f0',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        <img
          key={`${preview.id}-cover-${coverSrc}`}
          src={coverSrc}
          alt="视频封面"
          onLoad={() => patchResourceState({ videoCover: 'valid' })}
          onError={() => patchResourceState({ videoCover: 'invalid' })}
          style={{
            display: resourceState.videoCover === 'valid' ? 'block' : 'none',
            width: '100%',
            height: '100%',
            objectFit: 'contain',
            background: '#000',
          }}
        />

        {resourceState.videoCover === 'checking' ? (
          <MediaPlaceholder text="视频封面加载检测中..." minHeight={340} action={playButton} />
        ) : null}

        {resourceState.videoCover === 'valid' ? (
          <div
            style={{
              position: 'absolute',
              inset: 0,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              background: 'rgba(15,23,42,0.18)',
            }}
          >
            {playButton}
          </div>
        ) : null}
      </div>
    );
  };

  const renderResultVideo = () => {
    if (!preview || preview.genType !== 'video' || preview.status !== 'completed') return null;

    if (!preview.videoUrl) {
      return <MediaPlaceholder text="此视频任务暂无结果视频" minHeight={340} />;
    }

    if (resourceState.video === 'invalid') {
      return <MediaPlaceholder text={getMediaInvalidText(preview.videoUrl, '视频')} minHeight={340} />;
    }

    const videoSrc = apiUrl(preview.videoUrl);

    return (
      <div
        style={{
          position: 'relative',
          width: '100%',
          height: 340,
          borderRadius: 12,
          background: '#000',
          overflow: 'hidden',
          border: '1px solid #e2e8f0',
        }}
      >
        <video
          key={`${preview.id}-${videoSrc}`}
          ref={videoRef}
          src={videoSrc}
          preload="metadata"
          controls={videoPlaying}
          onLoadedMetadata={() => patchResourceState({ video: 'valid' })}
          onCanPlay={() => patchResourceState({ video: 'valid' })}
          onPlaying={() => {
            setVideoPlaying(true);
            patchResourceState({ video: 'valid' });
          }}
          onPause={() => setVideoPlaying(false)}
          onEnded={() => setVideoPlaying(false)}
          onError={() => {
            setVideoPlaying(false);
            patchResourceState({ video: 'invalid' });
          }}
          style={{
            width: '100%',
            height: '100%',
            objectFit: 'contain',
            background: '#000',
            opacity: videoPlaying ? 1 : 0,
            pointerEvents: videoPlaying ? 'auto' : 'none',
          }}
        />
        {renderVideoMask()}
      </div>
    );
  };

  const renderReferenceTile = (ref: GenerationAIMediaReference, index: number) => {
    const refUrl = getReferenceUrl(ref);
    const refType = getReferenceType(ref);
    const refKey = getReferenceKey(ref, index);
    const state = resourceState.references[refKey] || getInitialResourceState(refUrl);
    const isImage = refType === 'image';
    const isVideo = refType === 'video';
    const title = typeof ref.name === 'string' && ref.name ? ref.name : `参考素材 ${index + 1}`;

    if (!refUrl) {
      return (
        <div key={refKey} style={{ width: 94 }}>
          <div style={{ width: 94, height: 94 }}>
            <MediaPlaceholder text="无链接" compact />
          </div>
          <Typography.Text ellipsis style={{ display: 'block', marginTop: 4, fontSize: 11, color: '#94a3b8' }}>{title}</Typography.Text>
        </div>
      );
    }

    if (state === 'invalid') {
      return (
        <div key={refKey} style={{ width: 94 }}>
          <div style={{ width: 94, height: 94 }}>
            <MediaPlaceholder text={isBlobUrl(refUrl) ? '本地临时素材已失效' : '素材不可访问'} compact />
          </div>
          <Tooltip title={title}>
            <Typography.Text ellipsis style={{ display: 'block', marginTop: 4, fontSize: 11, color: '#94a3b8' }}>{title}</Typography.Text>
          </Tooltip>
        </div>
      );
    }

    const src = apiUrl(refUrl);

    return (
      <div key={refKey} style={{ width: 94 }}>
        <div
          role="button"
          tabIndex={0}
          title="点击新页面查看素材"
          onClick={() => handleOpenExternalResource(refUrl, isVideo ? '视频素材' : isImage ? '图片素材' : '素材')}
          onKeyDown={(e) => {
            if (e.key === 'Enter') handleOpenExternalResource(refUrl, isVideo ? '视频素材' : isImage ? '图片素材' : '素材');
          }}
          style={{
            width: 94,
            height: 94,
            borderRadius: 10,
            overflow: 'hidden',
            border: '1px solid #e2e8f0',
            background: '#f8f9fc',
            position: 'relative',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            cursor: 'pointer',
          }}
        >
          {isImage ? (
            <img
              src={src}
              alt={title}
              onLoad={() => patchReferenceState(refKey, 'valid')}
              onError={() => patchReferenceState(refKey, 'invalid')}
              style={{
                display: state === 'valid' ? 'block' : 'none',
                width: '100%',
                height: '100%',
                objectFit: 'cover',
              }}
            />
          ) : null}

          {isVideo ? (
            <>
              <video
                src={src}
                preload="metadata"
                onLoadedMetadata={() => patchReferenceState(refKey, 'valid')}
                onError={() => patchReferenceState(refKey, 'invalid')}
                style={{ display: 'none' }}
              />
              <div style={{ color: '#64748b', fontSize: 12, textAlign: 'center' }}>
                <PlayCircleOutlined style={{ fontSize: 18 }} />
                <div>视频素材</div>
                <div style={{ fontSize: 10, color: '#94a3b8', marginTop: 2 }}>点击查看</div>
              </div>
            </>
          ) : null}

          {!isImage && !isVideo ? (
            <div style={{ color: '#64748b', fontSize: 12, textAlign: 'center' }}>
              文件素材
              <div style={{ fontSize: 10, color: '#94a3b8', marginTop: 2 }}>点击查看</div>
            </div>
          ) : null}

          {state === 'checking' && isImage ? (
            <div
              style={{
                position: 'absolute',
                inset: 0,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                background: '#f8f9fc',
              }}
            >
              <LoadingOutlined style={{ color: '#6366f1' }} />
            </div>
          ) : null}
        </div>
        <Tooltip title={title}>
          <Typography.Text ellipsis style={{ display: 'block', marginTop: 4, fontSize: 11, color: '#94a3b8' }}>{title}</Typography.Text>
        </Tooltip>
      </div>
    );
  };

  const renderReferences = () => {
    if (!preview?.references || preview.references.length === 0) return null;

    return (
      <div>
        <Typography.Text style={{ fontSize: 12, color: '#94a3b8', display: 'block', marginBottom: 6 }}>参考内容</Typography.Text>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
          {preview.references.map((ref, index) => renderReferenceTile(ref, index))}
        </div>
      </div>
    );
  };

  return (
    <div>
      <Card variant="outlined" style={{ borderRadius: 12, border: '1px solid #f0f0f5' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 12 }}>
          <Space>
            <VideoCameraOutlined style={{ fontSize: 18, color: '#6366f1' }} />
            <Typography.Text strong style={{ fontSize: 16 }}>生成记录管理</Typography.Text>
            <Tag color="purple">{total} 条记录</Tag>
          </Space>
          <Space>
            <Select
              placeholder="状态筛选"
              allowClear
              style={{ width: 120 }}
              value={filterStatus || undefined}
              onChange={(v) => { setFilterStatus(v || ''); setPage(1); }}
              options={[
                { value: 'optimizing', label: '优化中' },
                { value: 'prompt_optimized', label: '待生成' },
                { value: 'generating', label: '生成中' },
                { value: 'completed', label: '已完成' },
                { value: 'failed', label: '失败' },
              ]}
            />
            <Input
              placeholder="用户ID搜索"
              prefix={<SearchOutlined style={{ color: '#94a3b8' }} />}
              style={{ width: 200 }}
              value={filterUserId}
              onChange={(e) => setFilterUserId(e.target.value)}
              onPressEnter={handleSearch}
              allowClear
            />
            <Button type="primary" onClick={handleSearch} style={{ borderRadius: 8 }}>
              搜索
            </Button>
          </Space>
        </div>

        <Table
          columns={columns as any}
          dataSource={records}
          rowKey="id"
          loading={loading}
          scroll={{ x: 1120 }}
          pagination={{
            current: page,
            pageSize,
            total,
            onChange: setPage,
            showSizeChanger: false,
            showTotal: (t) => `共 ${t} 条`,
          }}
        />
      </Card>

      {/* Detail modal */}
      <Modal
        title={(
          <Space>
            {preview?.genType === 'video' ? <VideoCameraOutlined /> : <FileImageOutlined />}
            <span>生成记录详情</span>
          </Space>
        )}
        open={!!preview}
        onCancel={handleClosePreview}
        footer={null}
        width={900}
        destroyOnClose
      >
        {preview ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16, marginTop: 16 }}>
            {/* User & Project info */}
            <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>
              <div style={{ flex: 1, minWidth: 150, padding: 12, borderRadius: 10, background: '#f8f9fc' }}>
                <Typography.Text style={{ fontSize: 11, color: '#94a3b8', display: 'block' }}>用户</Typography.Text>
                <Typography.Text strong>{preview.username || '-'}</Typography.Text>
              </div>
              <div style={{ flex: 1, minWidth: 150, padding: 12, borderRadius: 10, background: '#f8f9fc' }}>
                <Typography.Text style={{ fontSize: 11, color: '#94a3b8', display: 'block' }}>项目</Typography.Text>
                <Typography.Text strong>{preview.projectName || '-'}</Typography.Text>
              </div>
              <div style={{ flex: 1, minWidth: 150, padding: 12, borderRadius: 10, background: '#f8f9fc' }}>
                <Typography.Text style={{ fontSize: 11, color: '#94a3b8', display: 'block' }}>类型 / 状态</Typography.Text>
                <Space size={4} wrap>
                  {previewTypeConfig ? <Tag color={previewTypeConfig.color} icon={previewTypeConfig.icon}>{previewTypeConfig.text}</Tag> : null}
                  {previewStatusConfig ? <Tag color={previewStatusConfig.color} icon={previewStatusConfig.icon}>{previewStatusConfig.text}</Tag> : null}
                </Space>
              </div>
            </div>

            {/* Prompts */}
            <div>
              <Typography.Text style={{ fontSize: 12, color: '#94a3b8', display: 'block', marginBottom: 6 }}>原始提示词</Typography.Text>
              <div style={{ padding: 12, borderRadius: 10, background: '#f8f9fc', border: '1px solid #f0f0f5' }}>
                <Typography.Text style={{ fontSize: 13, color: '#475569', lineHeight: 1.7 }}>{preview.originalPrompt || '-'}</Typography.Text>
              </div>
            </div>
            <div>
              <Typography.Text style={{ fontSize: 12, color: '#94a3b8', display: 'block', marginBottom: 6 }}>优化后提示词</Typography.Text>
              <div style={{ padding: 12, borderRadius: 10, background: 'rgba(99,102,241,0.02)', border: '1px solid rgba(99,102,241,0.1)' }}>
                <Typography.Text style={{ fontSize: 13, color: '#1a1a2e', lineHeight: 1.7 }}>{preview.optimizedPrompt || '-'}</Typography.Text>
              </div>
            </div>

            {/* Credits */}
            <div style={{ display: 'flex', gap: 16, padding: 12, borderRadius: 10, background: '#f8f9fc', flexWrap: 'wrap' }}>
              <InfoItem
                label="文字积分"
                value={(
                  <>
                    <Typography.Text strong style={{ color: '#f59e0b' }}>{preview.textCreditsCost || 0}</Typography.Text>
                    <Typography.Text style={{ fontSize: 11, color: '#94a3b8' }}> ({preview.textTokensUsed || 0} tokens)</Typography.Text>
                  </>
                )}
              />
              <InfoItem
                label={`${preview.genType === 'image' ? '图片' : '视频'}积分`}
                value={(
                  <>
                    <Typography.Text strong style={{ color: '#6366f1' }}>{preview.creditsCost || 0}</Typography.Text>
                    {preview.genType === 'video' && preview.videoTokensUsed ? (
                      <Typography.Text style={{ fontSize: 11, color: '#94a3b8' }}> ({preview.videoTokensUsed} tokens)</Typography.Text>
                    ) : null}
                    {preview.genType === 'image' && preview.imageTokensUsed ? (
                      <Typography.Text style={{ fontSize: 11, color: '#94a3b8' }}> ({preview.imageTokensUsed} tokens)</Typography.Text>
                    ) : null}
                  </>
                )}
              />
              <InfoItem label="总积分" value={(preview.textCreditsCost || 0) + (preview.creditsCost || 0)} />
            </div>

            {/* Video Params */}
            {preview.genType === 'video' ? (
              preview.duration || preview.aspectRatio || preview.resolution ? (
                <div style={{ display: 'flex', gap: 16, padding: 12, borderRadius: 10, background: '#f8f9fc', flexWrap: 'wrap' }}>
                  <InfoItem label="时长" value={preview.duration ? `${preview.duration}秒` : '-'} />
                  <InfoItem label="比例" value={preview.aspectRatio || '-'} />
                  <InfoItem label="分辨率" value={preview.resolution || '-'} />
                </div>
              ) : (
                <div style={{ padding: 12, borderRadius: 10, background: '#f8f9fc', textAlign: 'center' }}>
                  <Tag color="default">视频参数待用户配置</Tag>
                </div>
              )
            ) : null}

            {/* Image Params */}
            {preview.genType === 'image' ? (
              preview.imageSize || preview.imageProportion || preview.imagePx ? (
                <div style={{ display: 'flex', gap: 16, padding: 12, borderRadius: 10, background: '#f8f9fc', flexWrap: 'wrap' }}>
                  <InfoItem label="尺寸" value={preview.imagePx || '-'} />
                  <InfoItem label="比例" value={preview.imageProportion || '-'} />
                  <InfoItem label="分辨率" value={preview.imageSize || '-'} />
                </div>
              ) : (
                <div style={{ padding: 12, borderRadius: 10, background: '#f8f9fc', textAlign: 'center' }}>
                  <Tag color="default">图片参数待用户配置</Tag>
                </div>
              )
            ) : null}

            {renderReferences()}

            {preview.status === 'completed' ? (
              <div>
                <Typography.Text style={{ fontSize: 12, color: '#94a3b8', display: 'block', marginBottom: 6 }}>
                  {preview.genType === 'video' ? '生成视频' : '生成图片'}
                </Typography.Text>
                {preview.genType === 'video' ? renderResultVideo() : renderResultImage()}
              </div>
            ) : null}

            {/* Error message */}
            {preview.status === 'failed' && preview.errorMessage ? (
              <div style={{ padding: 12, borderRadius: 10, background: 'rgba(239,68,68,0.04)', border: '1px solid rgba(239,68,68,0.15)' }}>
                <Typography.Text style={{ fontSize: 12, color: '#ef4444' }}>错误信息: {preview.errorMessage}</Typography.Text>
              </div>
            ) : null}

            {/* Timestamps */}
            <div style={{ display: 'flex', gap: 16, fontSize: 12, color: '#94a3b8', flexWrap: 'wrap' }}>
              <span>创建: {safeDate(preview.createdAt)}</span>
              <span>生成: {safeDate(preview.generatedAt)}</span>
            </div>
          </div>
        ) : (
          <Empty description="暂无详情" />
        )}
      </Modal>

      {/* Generate modal */}
      <Modal
        title={(
          <Space>
            {genModal && (genModal.record.genType === 'video' ? <PlayCircleOutlined /> : <FileImageOutlined />)}
            {genModal && (genModal.record.genType === 'video' ? '生成视频' : '生成图片')}
          </Space>
        )}
        open={!!genModal}
        onCancel={() => setGenModal(null)}
        onOk={handleGenerate}
        okText="提交生成"
        cancelText="取消"
        confirmLoading={genModal ? updating === genModal.record.id : false}
        width={420}
      >
        {genModal ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16, marginTop: 16 }}>
            {genModal.record.genType === 'video' ? (
              <>
                <div style={{ padding: 12, borderRadius: 10, background: '#f8f9fc' }}>
                  <Typography.Text style={{ fontSize: 11, color: '#94a3b8', display: 'block' }}>时长</Typography.Text>
                  <Typography.Text strong>{genModal.record.duration || 5}s</Typography.Text>
                </div>
                <div>
                  <Typography.Text style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 6 }}>画面比例</Typography.Text>
                  <Select
                    value={genModal.ratio}
                    onChange={(v) => setGenModal((prev) => (prev ? { ...prev, ratio: v } : null))}
                    style={{ width: '100%' }}
                    options={['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'].map((r) => ({ value: r, label: r }))}
                  />
                </div>
                <div>
                  <Typography.Text style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 6 }}>分辨率</Typography.Text>
                  <Select
                    value={genModal.resolution}
                    onChange={(v) => setGenModal((prev) => (prev ? { ...prev, resolution: v } : null))}
                    style={{ width: '100%' }}
                    options={['480p', '720p', '1080p'].map((r) => ({ value: r, label: r }))}
                  />
                </div>
              </>
            ) : (
              <>
                <div style={{ padding: 12, borderRadius: 10, background: '#f8f9fc' }}>
                  <Typography.Text style={{ fontSize: 11, color: '#94a3b8', display: 'block' }}>尺寸</Typography.Text>
                  <Typography.Text strong>{genModal.record.imagePx || '-'}</Typography.Text>
                </div>
                <div style={{ padding: 12, borderRadius: 10, background: '#f8f9fc' }}>
                  <Typography.Text style={{ fontSize: 11, color: '#94a3b8', display: 'block' }}>比例</Typography.Text>
                  <Typography.Text strong>{genModal.record.imageProportion || '-'}</Typography.Text>
                </div>
                <div>
                  <Typography.Text style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 6 }}>分辨率</Typography.Text>
                  <Select
                    value={genModal.image_size}
                    onChange={(v) => setGenModal((prev) => (prev ? { ...prev, image_size: v } : null))}
                    style={{ width: '100%' }}
                    options={['2K', '4K'].map((r) => ({ value: r, label: r }))}
                  />
                </div>
              </>
            )}
          </div>
        ) : null}
      </Modal>
    </div>
  );
};

export default AdminGenerationRecords;
