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,
  FileImageOutlined,
} from '@ant-design/icons';
import { getAdminGenerationRecords, getVideoEngines, getImageEngines } from '../api';
import type { AdminGenerationRecord, GenerationAIMediaReference } from '../types';
import { formatDate } from '../utils/formatDate';
import { getGenerationStageLabel, getGenerationStatusColor, resolveGenerationUiState } from '../utils/generationTaskStatus';

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 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 [filterEngineId, setFilterEngineId] = useState<string>('');
  const [filterIncludeMedia, setFilterIncludeMedia] = useState<'' | 'true' | 'false'>('');
  const [engineOptions, setEngineOptions] = useState<Array<{ value: string; label: 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 load = useCallback(async () => {
    setLoading(true);
    try {
      const res = await getAdminGenerationRecords({
        userId: filterUserId.trim() || undefined,
        status: filterStatus || undefined,
        engineId: filterEngineId || undefined,
        includeMediaReferences: filterIncludeMedia === '' ? undefined : filterIncludeMedia === 'true',
        page,
        pageSize,
      });
      setRecords((res.items || []).map((item: any) => ({
        id: item.id,
        userId: item.userId,
        username: item.username,
        projectId: item.projectId,
        projectName: item.projectName,
        industry: item.industry,
        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,
        engineId: item.engineId,
        engineName: item.engineName,
        engineSnapshot: item.engineSnapshot,
        includeMediaReferences: item.includeMediaReferences,
      })));
      setTotal(res.total || 0);
    } catch {
      message.error('加载记录失败');
    } finally {
      setLoading(false);
    }
  }, [filterStatus, filterUserId, filterEngineId, filterIncludeMedia, page, pageSize]);

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

  useEffect(() => {
    Promise.all([
      getImageEngines({ includeDeleted: true }),
      getVideoEngines({ includeDeleted: true }),
    ])
      .then(([imageEngines, videoEngines]) => {
        const items = [...(imageEngines || []), ...(videoEngines || [])];
        const seen = new Set<string>();
        setEngineOptions(items.reduce<Array<{ value: string; label: string }>>((acc, item: any) => {
          const id = String(item?.id || '');
          if (!id || seen.has(id)) return acc;
          seen.add(id);
          const deletedSuffix = item?.deletedAt ? '（已删除）' : '';
          acc.push({ value: id, label: item?.name ? `${item.name}${deletedSuffix} (${id})` : `${id}${deletedSuffix}` });
          return acc;
        }, []));
      })
      .catch(() => setEngineOptions([]));
  }, []);

  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 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: 'industry', width: 100, ellipsis: true,
      render: (v: string) => <Tag color="cyan">{v || '-'}</Tag>,
    },
    {
      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' ? (
          <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}
            {!r.duration && !r.aspectRatio && !r.resolution ? <Tag color="default">待配置</Tag> : null}
            {r.engineName || r.engineId ? <Tag color="purple">{r.engineName || truncateId(r.engineId || '')}</Tag> : null}
            <Tag color={r.includeMediaReferences ? 'green' : 'default'}>
              {r.includeMediaReferences ? '携带附件' : '不携带附件'}{r.references?.length ? `(${r.references.length})` : ''}
            </Tag>
          </Space>
        ) : (
          <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}
            {!r.imageSize && !r.imageProportion && !r.imagePx ? <Tag color="default">待配置</Tag> : null}
            {r.engineName || r.engineId ? <Tag color="purple">{r.engineName || truncateId(r.engineId || '')}</Tag> : null}
            <Tag color={r.includeMediaReferences ? 'green' : 'default'}>
              {r.includeMediaReferences ? '携带附件' : '不携带附件'}{r.references?.length ? `(${r.references.length})` : ''}
            </Tag>
          </Space>
        )
      ),
    },
    {
      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 state = resolveGenerationUiState({ status: v });
        const icon = state.isActive ? <LoadingOutlined spin /> : (state.isSuccess ? <CheckCircleOutlined /> : (state.isFailure ? <CloseCircleOutlined /> : <ClockCircleOutlined />));
        return <Tag color={state.color} icon={icon}>{state.label}</Tag>;
      },
    },
    {
      title: '阶段', dataIndex: 'pipelineStage', width: 150,
      render: (v: string) => <Tag color={getGenerationStatusColor(v)}>{getGenerationStageLabel(v)}</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: 90, fixed: 'right' as const,
      render: (_: any, r: AdminGenerationRecord) => (
        <Button size="small" icon={<EyeOutlined />} onClick={() => handleOpenPreview(r)}>
          详情
        </Button>
      ),
    },
  ], [handleOpenPreview]);

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

  const renderResultImage = () => {
    if (!preview || preview.genType !== 'image' || !resolveGenerationUiState(preview).isSuccess) 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' || !resolveGenerationUiState(preview).isSuccess) 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: '失败' },
              ]}
            />
            <Select
              placeholder="引擎筛选"
              allowClear
              showSearch
              optionFilterProp="label"
              style={{ width: 220 }}
              value={filterEngineId || undefined}
              onChange={(v) => { setFilterEngineId(v || ''); setPage(1); }}
              options={engineOptions}
            />
            <Select
              placeholder="附件状态"
              allowClear
              style={{ width: 130 }}
              value={filterIncludeMedia || undefined}
              onChange={(v) => { setFilterIncludeMedia((v || '') as '' | 'true' | 'false'); setPage(1); }}
              options={[
                { value: 'true', label: '携带附件' },
                { value: 'false', 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.isActive ? <LoadingOutlined spin /> : (previewStatusConfig.isSuccess ? <CheckCircleOutlined /> : (previewStatusConfig.isFailure ? <CloseCircleOutlined /> : <ClockCircleOutlined />))}>{previewStatusConfig.label}</Tag> : null}
                  {preview.pipelineStage ? <Tag color={getGenerationStatusColor(preview.pipelineStage)}>{getGenerationStageLabel(preview.pipelineStage)}</Tag> : null}
                  {preview.videoUpscaleEnabled ? <Tag color="purple">已启用超分</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()}

            {resolveGenerationUiState(preview).isSuccess ? (
              <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 */}
            {resolveGenerationUiState(preview).isFailure && 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>

    </div>
  );
};

export default AdminGenerationRecords;
