import React from 'react';
import { Card, Collapse, Descriptions, Empty, Space, Table, Typography } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { JsonBlock } from './JsonCollapse';

const FIELD_LABELS: Record<string, string> = {
  schema_version: 'Schema 版本',
  generation_type: '生成类型',
  business_type: '业务类型',
  usage: '用途',
  product_type: '产品类型',
  target_audience: '目标受众',
  style: '风格',
  aspect_ratio: '画面比例',
  resolution: '分辨率',
  duration: '时长',
  fps: '帧率',
  final_prompt: '最终提示词',
  prompt: '提示词',
  description: '说明',
  content: '内容',
  time: '时间',
  time_range: '时间段',
  start_time: '开始时间',
  end_time: '结束时间',
  stage: '阶段',
  scene: '场景',
  action: '动作',
  camera: '镜头',
  shot: '镜头',
  lens: '镜头',
  subtitle: '字幕',
  voiceover: '口播',
  audio: '音频',
  rhythm: '节奏',
  notes: '备注',
};

const SECTION_LABELS: Record<string, string> = {
  basic: '基础信息',
  basic_info: '基础信息',
  material: '素材理解',
  material_understanding: '素材理解',
  business: '业务属性',
  business_info: '业务属性',
  visual: '画面与风格',
  visual_style: '画面与风格',
  time_plan: '时间规划',
  timeline: '时间规划',
  scene_timeline: '场景时间线',
  action_flow: '动作流程',
  motion_flow: '动作流程',
  character_action_flow: '角色动作流程',
  camera_flow: '镜头流程',
  shot_flow: '镜头流程',
  lens_flow: '镜头流程',
  subtitle: '字幕',
  subtitles: '字幕',
  voiceover: '口播',
  audio: '音频',
  rhythm: '节奏',
  compliance: '合规控制',
  final_prompt: '最终提示词',
};

const isRecord = (value: unknown): value is Record<string, unknown> => !!value && typeof value === 'object' && !Array.isArray(value);

const labelOf = (key: string): string => SECTION_LABELS[key] || FIELD_LABELS[key] || key;

const isLongText = (value: unknown): boolean => typeof value === 'string' && value.length > 80;


const EMPTY_TEXTS = new Set(['', '无', 'null', 'None', 'none', '未提及', '不适用']);
const PLACEHOLDER_FLOW_TEXTS = new Set([
  '展示主体动作、核心卖点或主要视觉内容',
  '展示主要动作、核心卖点或主要视觉内容',
  '展示核心卖点或主要视觉内容',
  '展示主体动作',
  '无',
]);
const ACTION_CONTENT_KEYS = ['动作内容', '动作', '动作说明', '内容', '说明', '主体动作', '动作变化'];
const CAMERA_CONTENT_KEYS = ['镜头内容', '镜头', '镜头说明', '运镜', '运镜说明', '内容', '说明'];

const toText = (value: unknown): string => {
  if (value === null || value === undefined) return '';
  if (typeof value === 'string') return value.trim();
  if (typeof value === 'number' || typeof value === 'boolean') return String(value);
  try {
    return JSON.stringify(value);
  } catch {
    return String(value);
  }
};

const isEmptyText = (value: unknown): boolean => EMPTY_TEXTS.has(toText(value));

const isActionFlowSection = (sectionKey: string): boolean => {
  const lower = sectionKey.toLowerCase();
  return lower.includes('action') || lower.includes('motion') || lower.includes('动作');
};

const isCameraFlowSection = (sectionKey: string): boolean => {
  const lower = sectionKey.toLowerCase();
  return lower.includes('camera') || lower.includes('shot') || lower.includes('lens') || lower.includes('镜头');
};

const isTimePlanSection = (sectionKey: string): boolean => {
  const lower = sectionKey.toLowerCase();
  return lower.includes('time') || lower.includes('timeline') || lower.includes('时间规划') || lower.includes('动态时间规划');
};

const pickFirstContent = (item: Record<string, unknown>, keys: string[]): string => {
  for (const key of keys) {
    if (key in item && !isEmptyText(item[key])) return toText(item[key]);
  }
  return '';
};

const normalizeFlowContent = (baseContent: string, extras: string[]): string => {
  const cleanBase = baseContent.trim();
  const uniqueExtras = extras.filter((item, index) => item && extras.indexOf(item) === index);
  if (uniqueExtras.length && (!cleanBase || PLACEHOLDER_FLOW_TEXTS.has(cleanBase))) {
    return uniqueExtras.join('；');
  }
  const parts = cleanBase && !EMPTY_TEXTS.has(cleanBase) ? [cleanBase] : [];
  uniqueExtras.forEach((item) => {
    if (item && !parts.includes(item)) parts.push(item);
  });
  return parts.join('；') || '-';
};

const normalizeFlowItemForDisplay = (
  item: Record<string, unknown>,
  contentKey: '动作内容' | '镜头内容',
  contentKeys: string[],
): Record<string, unknown> => {
  const allowed = new Set(['时间段', contentKey, ...contentKeys]);
  const extras: string[] = [];
  Object.entries(item).forEach(([field, value]) => {
    if (allowed.has(field)) return;
    const fieldText = toText(field);
    const valueText = toText(value);
    if (fieldText && !EMPTY_TEXTS.has(fieldText)) extras.push(fieldText);
    if (valueText && !EMPTY_TEXTS.has(valueText) && valueText !== fieldText) extras.push(valueText);
  });
  return {
    时间段: toText(item['时间段']) || '-',
    [contentKey]: normalizeFlowContent(pickFirstContent(item, contentKeys), extras),
  };
};

const normalizeRecordForSection = (sectionKey: string, item: Record<string, unknown>): Record<string, unknown> => {
  if (isActionFlowSection(sectionKey)) {
    return normalizeFlowItemForDisplay(item, '动作内容', ACTION_CONTENT_KEYS);
  }
  if (isCameraFlowSection(sectionKey)) {
    return normalizeFlowItemForDisplay(item, '镜头内容', CAMERA_CONTENT_KEYS);
  }
  if (isTimePlanSection(sectionKey)) {
    return {
      时间段: toText(item['时间段']) || '-',
      阶段: toText(item['阶段']) || '-',
      说明: toText(item['说明']) || '-',
    };
  }
  return item;
};

const renderValue = (value: unknown): React.ReactNode => {
  if (value === null || value === undefined || value === '') return <Typography.Text type="secondary">-</Typography.Text>;
  if (typeof value === 'boolean') return value ? '是' : '否';
  if (typeof value === 'number') return value;
  if (typeof value === 'string') {
    return <Typography.Paragraph style={{ marginBottom: 0, whiteSpace: 'pre-wrap' }}>{value}</Typography.Paragraph>;
  }
  return <JsonBlock value={value} maxHeight={220} />;
};

const getArrayMode = (key: string): 'card' | 'table' => {
  const lower = key.toLowerCase();
  if (
    lower.includes('action') ||
    lower.includes('motion') ||
    lower.includes('camera') ||
    lower.includes('shot') ||
    lower.includes('lens') ||
    lower.includes('flow') ||
    lower.includes('动作') ||
    lower.includes('镜头')
  ) {
    return 'card';
  }
  return 'table';
};

const renderCardArray = (sectionKey: string, items: Record<string, unknown>[]): React.ReactNode => (
  <Space direction="vertical" size={12} style={{ width: '100%' }}>
    {items.map((item, index) => {
      const displayItem = normalizeRecordForSection(sectionKey, item);
      return (
        <Card
          key={`${sectionKey}-${index}`}
          size="small"
          title={`${labelOf(sectionKey)} ${index + 1}`}
          styles={{ body: { padding: 12 } }}
        >
          <Descriptions size="small" column={1} bordered>
            {Object.entries(displayItem).map(([field, value]) => (
              <Descriptions.Item key={field} label={labelOf(field)}>
                {renderValue(value)}
              </Descriptions.Item>
            ))}
          </Descriptions>
        </Card>
      );
    })}
  </Space>
);

const renderTableArray = (sectionKey: string, items: Record<string, unknown>[]): React.ReactNode => {
  const displayItems = items.map(item => normalizeRecordForSection(sectionKey, item));
  const fields = Array.from(new Set(displayItems.flatMap(item => Object.keys(item))));
  const columns: ColumnsType<Record<string, unknown>> = fields.map(field => ({
    title: labelOf(field),
    dataIndex: field,
    key: field,
    width: isLongText(displayItems.find(item => item[field])?.[field]) ? 280 : 160,
    render: (value: unknown) => renderValue(value),
  }));

  return (
    <Table
      size="small"
      rowKey={(_, index) => `${sectionKey}-${index}`}
      columns={columns}
      dataSource={displayItems}
      pagination={false}
      scroll={{ x: Math.max(900, fields.length * 180) }}
      tableLayout="fixed"
    />
  );
};

const renderArray = (sectionKey: string, value: unknown[]): React.ReactNode => {
  if (!value.length) return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无数据" />;
  if (value.every(isRecord)) {
    return getArrayMode(sectionKey) === 'card'
      ? renderCardArray(sectionKey, value)
      : renderTableArray(sectionKey, value);
  }
  return <JsonBlock value={value} maxHeight={260} />;
};

const renderRecord = (value: Record<string, unknown>): React.ReactNode => (
  <Descriptions size="small" column={2} bordered>
    {Object.entries(value).map(([field, fieldValue]) => (
      <Descriptions.Item key={field} label={labelOf(field)} span={Array.isArray(fieldValue) || isRecord(fieldValue) || isLongText(fieldValue) ? 2 : 1}>
        {Array.isArray(fieldValue)
          ? renderArray(field, fieldValue)
          : isRecord(fieldValue)
            ? renderRecord(fieldValue)
            : renderValue(fieldValue)}
      </Descriptions.Item>
    ))}
  </Descriptions>
);

const renderSection = (key: string, value: unknown): React.ReactNode => {
  if (Array.isArray(value)) return renderArray(key, value);
  if (isRecord(value)) return renderRecord(value);
  return renderValue(value);
};

interface VideoPromptSchemaViewerProps {
  schema?: Record<string, any> | null;
  finalPrompt?: string | null;
}

const VideoPromptSchemaViewer: React.FC<VideoPromptSchemaViewerProps> = ({ schema, finalPrompt }) => {
  const hasSchema = !!schema && Object.keys(schema).length > 0;
  if (!hasSchema && !finalPrompt) {
    return <Empty description="暂无视频提词 schema" />;
  }

  const schemaItems = hasSchema
    ? Object.entries(schema || {}).map(([key, value]) => ({
        key,
        label: labelOf(key),
        children: renderSection(key, value),
      }))
    : [];

  const defaultKeys = finalPrompt ? ['final_prompt'] : [];

  return (
    <Space direction="vertical" size={12} style={{ width: '100%' }}>
      {finalPrompt ? (
        <Card size="small" title="最终视频提示词">
          <Typography.Paragraph style={{ whiteSpace: 'pre-wrap', marginBottom: 0 }}>{finalPrompt}</Typography.Paragraph>
        </Card>
      ) : null}

      {schemaItems.length ? (
        <Collapse
          size="small"
          defaultActiveKey={defaultKeys}
          items={schemaItems}
        />
      ) : null}
    </Space>
  );
};

export default VideoPromptSchemaViewer;
