import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
  Alert,
  Button,
  Card,
  Col,
  Collapse,
  Divider,
  Form,
  Input,
  InputNumber,
  Modal,
  Popconfirm,
  Row,
  Select,
  Space,
  Spin,
  Switch,
  Tabs,
  Tag,
  Typography,
  message,
} from 'antd';
import {
  DeleteOutlined,
  DownloadOutlined,
  EyeOutlined,
  PlusOutlined,
  ReloadOutlined,
  SaveOutlined,
  UploadOutlined,
} from '@ant-design/icons';
import {
  exportVideoPromptSchemaConfig,
  getVideoPromptSchemaConfig,
  importVideoPromptSchemaConfig,
  previewVideoPromptSchemaConfig,
  resetVideoPromptSchemaConfig,
  saveVideoPromptSchemaConfig,
} from '../api';
import type {
  VideoPromptFlowItemField,
  VideoPromptSchemaConfigData,
  VideoPromptSchemaNode,
  VideoPromptSchemaNodeType,
  VideoPromptTimePlanRule,
} from '../types';

const { Title, Text, Paragraph } = Typography;
const { TextArea } = Input;

const NODE_TYPES: { label: string; value: VideoPromptSchemaNodeType }[] = [
  { label: '对象', value: 'object' },
  { label: '数组', value: 'array' },
  { label: '字符串', value: 'string' },
  { label: '数字', value: 'number' },
  { label: '布尔', value: 'boolean' },
  { label: '流程数组', value: 'flow' },
];

const VIDEO_SPEC_SECTION_KEY = '画面属性';
const VIDEO_SPEC_LOCKED_FIELDS = new Set(['视频时长', '视频比例', '清晰度', '帧率', '推荐分辨率']);

function isLockedVideoSpecField(sectionKey: string | undefined, fieldKey: string | undefined): boolean {
  return sectionKey === VIDEO_SPEC_SECTION_KEY && !!fieldKey && VIDEO_SPEC_LOCKED_FIELDS.has(fieldKey);
}

function isLockedVideoSpecSection(sectionKey: string | undefined): boolean {
  return sectionKey === VIDEO_SPEC_SECTION_KEY;
}

function clone<T>(value: T): T {
  return JSON.parse(JSON.stringify(value ?? null));
}

function pick<T = any>(obj: any, camelKey: string, snakeKey: string, fallback?: T): T {
  if (!obj || typeof obj !== 'object') return fallback as T;
  if (obj[camelKey] !== undefined) return obj[camelKey] as T;
  if (obj[snakeKey] !== undefined) return obj[snakeKey] as T;
  return fallback as T;
}

function normalizeFlowField(field: any): VideoPromptFlowItemField {
  return {
    key: String(field?.key || field?.label || '新流程字段'),
    label: String(field?.label || field?.key || '新流程字段'),
    enabled: field?.enabled ?? true,
    editable: field?.editable ?? true,
    maxLength: Number(pick(field, 'maxLength', 'max_length', 800) || 800),
    value: field?.value ?? '',
  };
}

function normalizeNode(node: any): VideoPromptSchemaNode {
  const type = String(node?.type || 'string') as VideoPromptSchemaNodeType;
  const normalized: VideoPromptSchemaNode = {
    key: String(node?.key || node?.label || '新字段'),
    label: String(node?.label || node?.key || '新字段'),
    type,
    enabled: node?.enabled ?? true,
    editable: node?.editable ?? true,
    maxLength: Number(pick(node, 'maxLength', 'max_length', type === 'flow' ? 800 : 1000) || (type === 'flow' ? 800 : 1000)),
  };

  if (type === 'object') {
    normalized.children = Array.isArray(node?.children) ? node.children.map(normalizeNode) : [];
  } else if (type === 'flow') {
    normalized.contentKey = String(pick(node, 'contentKey', 'content_key', node?.key === '镜头流程' ? '镜头内容' : '动作内容'));
    const aliases = pick<any[]>(node, 'contentAliases', 'content_aliases', []);
    normalized.contentAliases = Array.isArray(aliases) ? aliases.map(item => String(item)).filter(Boolean) : [];
    const itemFields = pick<any[]>(node, 'itemFields', 'item_fields', []);
    normalized.itemFields = Array.isArray(itemFields) && itemFields.length > 0
      ? itemFields.map(normalizeFlowField)
      : [{ key: normalized.contentKey, label: normalized.contentKey, enabled: true, editable: true, maxLength: normalized.maxLength || 800, value: '' }];
  } else {
    normalized.value = node?.value ?? (type === 'array' ? [] : type === 'boolean' ? false : type === 'number' ? 0 : '无');
  }

  return normalized;
}

function normalizeTimeRule(rule: any): VideoPromptTimePlanRule {
  const rawSegments = Array.isArray(rule?.segments) ? rule.segments : [];
  const rawRatios = Array.isArray(rule?.ratios) ? rule.ratios : [];
  return {
    minDuration: Number(pick(rule, 'minDuration', 'min_duration', 1) || 1),
    maxDuration: Number(pick(rule, 'maxDuration', 'max_duration', 5) || 5),
    ratios: rawRatios.map((item: any) => Number(item || 0)),
    segments: rawSegments.map((segment: any) => ({
      stage: String(segment?.stage || '新阶段'),
      description: String(segment?.description || segment?.desc || '阶段说明'),
    })),
  };
}

function normalizeConfig(data: any): VideoPromptSchemaConfigData {
  const rawSections = Array.isArray(data?.sections) ? data.sections : [];
  const rawRules = Array.isArray(data?.timePlanRules)
    ? data.timePlanRules
    : Array.isArray(data?.time_plan_rules)
      ? data.time_plan_rules
      : [];
  return {
    version: data?.version || 'video_prompt_schema_config_v1',
    enabled: data?.enabled ?? true,
    sections: rawSections.map(normalizeNode),
    timePlanRules: rawRules.map(normalizeTimeRule),
  };
}

function toApiNode(node: VideoPromptSchemaNode, parentKey?: string): any {
  const lockedSection = isLockedVideoSpecSection(node.key);
  const lockedField = isLockedVideoSpecField(parentKey, node.key);
  const base: any = {
    key: node.key,
    label: node.label,
    type: lockedField ? 'string' : node.type,
    enabled: lockedSection || lockedField ? true : !!node.enabled,
    editable: lockedField ? false : !!node.editable,
    max_length: node.maxLength,
  };
  if (node.type === 'object') {
    base.children = (node.children || []).map(child => toApiNode(child, node.key));
  } else if (node.type === 'flow') {
    base.content_key = node.contentKey;
    base.content_aliases = node.contentAliases || [];
    base.item_fields = (node.itemFields || []).map(field => ({
      key: field.key,
      label: field.label,
      enabled: !!field.enabled,
      editable: !!field.editable,
      max_length: field.maxLength,
      value: field.value ?? '',
    }));
  } else {
    base.value = node.value;
  }
  return base;
}

function toApiConfig(config: VideoPromptSchemaConfigData, enabled: boolean): any {
  return {
    version: config.version,
    enabled,
    sections: (config.sections || []).map(section => toApiNode(section)),
    time_plan_rules: (config.timePlanRules || []).map(rule => ({
      min_duration: rule.minDuration,
      max_duration: rule.maxDuration,
      ratios: rule.ratios || [],
      segments: (rule.segments || []).map(segment => ({
        stage: segment.stage,
        description: segment.description,
      })),
    })),
  };
}

function runtimePreviewSchema(result: any): any {
  return result?.runtimeSchema || result?.runtime_schema || {};
}

function runtimePreviewTimePlan(result: any): any[] {
  const value = result?.timePlan || result?.time_plan || runtimePreviewSchema(result)?.动态时间规划 || [];
  return Array.isArray(value) ? value : [];
}

function runtimePreviewSnapshot(result: any): any {
  return result?.schemaConfigSnapshot || result?.schema_config_snapshot || {};
}

function downloadJson(filename: string, data: any): void {
  const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

const createNode = (type: VideoPromptSchemaNodeType = 'string'): VideoPromptSchemaNode => ({
  key: '新字段',
  label: '新字段',
  type,
  enabled: true,
  editable: true,
  maxLength: type === 'flow' ? 800 : 1000,
  value: type === 'array' ? [] : type === 'boolean' ? false : type === 'number' ? 0 : '无',
  children: type === 'object' ? [] : undefined,
  contentKey: type === 'flow' ? '动作内容' : undefined,
  contentAliases: type === 'flow' ? ['动作内容', '动作', '动作说明', '内容', '说明'] : undefined,
  itemFields: type === 'flow' ? [{ key: '动作内容', label: '动作内容', enabled: true, editable: true, maxLength: 800, value: '' }] : undefined,
});

const createTimeRule = (): VideoPromptTimePlanRule => ({
  minDuration: 1,
  maxDuration: 5,
  ratios: [0.2, 0.4, 0.4],
  segments: [
    { stage: '开场吸引', description: '快速吸引注意力' },
    { stage: '核心展示', description: '展示主体动作、核心卖点或主要视觉内容' },
    { stage: '收尾引导', description: '给出行动引导并稳定落版' },
  ],
});

const AdminVideoPromptSchemaConfig: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [enabled, setEnabled] = useState(true);
  const [usingDefault, setUsingDefault] = useState(false);
  const [config, setConfig] = useState<VideoPromptSchemaConfigData | null>(null);
  const [defaultConfig, setDefaultConfig] = useState<VideoPromptSchemaConfigData | null>(null);
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewResult, setPreviewResult] = useState<any>(null);
  const [previewForm] = Form.useForm();
  const importInputRef = useRef<HTMLInputElement | null>(null);

  const sections = config?.sections || [];
  const timePlanRules = config?.timePlanRules || [];

  const load = async () => {
    setLoading(true);
    try {
      const res = await getVideoPromptSchemaConfig();
      setEnabled(Boolean((res as any).isEnabled ?? (res as any).is_enabled ?? res.data?.enabled ?? false));
      setUsingDefault(Boolean((res as any).usingDefault ?? (res as any).using_default ?? false));
      setConfig(normalizeConfig(res.data));
      setDefaultConfig(normalizeConfig((res as any).defaultData ?? (res as any).default_data));
    } catch (error: any) {
      message.error(error?.message || '加载失败');
    } finally {
      setLoading(false);
    }
  };

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

  const updateConfig = (updater: (draft: VideoPromptSchemaConfigData) => void) => {
    setConfig(prev => {
      const next = normalizeConfig(clone(prev));
      updater(next);
      return next;
    });
  };

  const save = async () => {
    if (!config) return;
    setSaving(true);
    try {
      const res = await saveVideoPromptSchemaConfig({ is_enabled: enabled, data: toApiConfig(config, enabled) });
      setConfig(normalizeConfig(res.data));
      setEnabled(Boolean((res as any).isEnabled ?? (res as any).is_enabled ?? res.data?.enabled ?? false));
      setUsingDefault(Boolean((res as any).usingDefault ?? (res as any).using_default ?? false));
      message.success('保存成功');
    } catch (error: any) {
      message.error(error?.message || '保存失败');
    } finally {
      setSaving(false);
    }
  };

  const resetDefault = async () => {
    setSaving(true);
    try {
      const res = await resetVideoPromptSchemaConfig();
      setConfig(normalizeConfig(res.data));
      setDefaultConfig(normalizeConfig((res as any).defaultData ?? (res as any).default_data));
      setEnabled(Boolean((res as any).isEnabled ?? (res as any).is_enabled ?? res.data?.enabled ?? false));
      setUsingDefault(Boolean((res as any).usingDefault ?? (res as any).using_default ?? false));
      message.success('已恢复默认配置');
    } catch (error: any) {
      message.error(error?.message || '恢复默认失败');
    } finally {
      setSaving(false);
    }
  };

  const doExport = async () => {
    try {
      const res = await exportVideoPromptSchemaConfig();
      downloadJson('video_prompt_schema_config.json', res);
    } catch (error: any) {
      message.error(error?.message || '导出失败');
    }
  };

  const onImportFile = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    event.target.value = '';
    if (!file) return;
    try {
      const text = await file.text();
      const json = JSON.parse(text);
      const data = json.data || json;
      const isEnabled = json.isEnabled ?? json.is_enabled ?? enabled;
      const res = await importVideoPromptSchemaConfig({ is_enabled: !!isEnabled, data });
      setConfig(normalizeConfig(res.data));
      setEnabled(Boolean((res as any).isEnabled ?? (res as any).is_enabled ?? res.data?.enabled ?? false));
      setUsingDefault(Boolean((res as any).usingDefault ?? (res as any).using_default ?? false));
      message.success('导入成功');
    } catch (error: any) {
      message.error(error?.message || '导入失败，请检查 JSON 格式');
    }
  };

  const openPreview = () => {
    previewForm.setFieldsValue({ duration: 8, aspectRatio: '9:16', resolution: '1080p', frameRate: '30fps' });
    setPreviewResult(null);
    setPreviewOpen(true);
  };

  const doPreview = async () => {
    if (!config) return;
    const values = await previewForm.validateFields();
    try {
      const res = await previewVideoPromptSchemaConfig({
        is_enabled: enabled,
        data: toApiConfig(config, enabled),
        duration: Number(values.duration || 8),
        aspect_ratio: values.aspectRatio,
        resolution: values.resolution,
        frame_rate: values.frameRate,
      });
      setPreviewResult(res);
    } catch (error: any) {
      message.error(error?.message || '预览失败');
    }
  };

  const addSection = () => {
    updateConfig(draft => {
      draft.sections.push(createNode('object'));
    });
  };

  const updateSection = (index: number, patch: Partial<VideoPromptSchemaNode>) => {
    updateConfig(draft => {
      const current = draft.sections[index];
      if (isLockedVideoSpecSection(current?.key)) {
        delete patch.key;
        delete patch.type;
        delete patch.enabled;
      }
      draft.sections[index] = { ...draft.sections[index], ...patch };
      if (patch.type === 'object') {
        draft.sections[index].children = draft.sections[index].children || [];
      }
      if (patch.type === 'flow') {
        draft.sections[index].contentKey = draft.sections[index].contentKey || '动作内容';
        draft.sections[index].contentAliases = draft.sections[index].contentAliases || ['动作内容', '动作', '动作说明', '内容', '说明'];
        draft.sections[index].itemFields = draft.sections[index].itemFields || [{ key: '动作内容', label: '动作内容', enabled: true, editable: true, maxLength: 800, value: '' }];
      }
    });
  };

  const deleteSection = (index: number) => {
    updateConfig(draft => {
      draft.sections.splice(index, 1);
    });
  };

  const addChild = (sectionIndex: number) => {
    updateConfig(draft => {
      const section = draft.sections[sectionIndex];
      section.children = section.children || [];
      section.children.push(createNode('string'));
    });
  };

  const updateChild = (sectionIndex: number, childIndex: number, patch: Partial<VideoPromptSchemaNode>) => {
    updateConfig(draft => {
      const section = draft.sections[sectionIndex];
      const children = section.children || [];
      const child = children[childIndex];
      if (isLockedVideoSpecField(section?.key, child?.key)) {
        delete patch.key;
        delete patch.type;
        delete patch.enabled;
        patch.editable = false;
      }
      children[childIndex] = { ...children[childIndex], ...patch };
      draft.sections[sectionIndex].children = children;
    });
  };

  const deleteChild = (sectionIndex: number, childIndex: number) => {
    updateConfig(draft => {
      draft.sections[sectionIndex].children?.splice(childIndex, 1);
    });
  };

  const addFlowField = (sectionIndex: number) => {
    updateConfig(draft => {
      const section = draft.sections[sectionIndex];
      section.itemFields = section.itemFields || [];
      section.itemFields.push({ key: '新流程字段', label: '新流程字段', enabled: true, editable: true, maxLength: 800, value: '' });
    });
  };

  const updateFlowField = (sectionIndex: number, fieldIndex: number, patch: Partial<VideoPromptFlowItemField>) => {
    updateConfig(draft => {
      const fields = draft.sections[sectionIndex].itemFields || [];
      fields[fieldIndex] = { ...fields[fieldIndex], ...patch };
      draft.sections[sectionIndex].itemFields = fields;
    });
  };

  const deleteFlowField = (sectionIndex: number, fieldIndex: number) => {
    updateConfig(draft => {
      draft.sections[sectionIndex].itemFields?.splice(fieldIndex, 1);
    });
  };

  const addTimeRule = () => {
    updateConfig(draft => {
      draft.timePlanRules.push(createTimeRule());
    });
  };

  const updateTimeRule = (index: number, patch: Partial<VideoPromptTimePlanRule>) => {
    updateConfig(draft => {
      draft.timePlanRules[index] = { ...draft.timePlanRules[index], ...patch };
    });
  };

  const deleteTimeRule = (index: number) => {
    updateConfig(draft => {
      draft.timePlanRules.splice(index, 1);
    });
  };

  const updateSegment = (ruleIndex: number, segmentIndex: number, patch: Partial<{ stage: string; description: string; ratio: number }>) => {
    updateConfig(draft => {
      const rule = draft.timePlanRules[ruleIndex];
      if (patch.ratio !== undefined) rule.ratios[segmentIndex] = Number(patch.ratio || 0);
      if (patch.stage !== undefined) rule.segments[segmentIndex].stage = patch.stage;
      if (patch.description !== undefined) rule.segments[segmentIndex].description = patch.description;
    });
  };

  const addSegment = (ruleIndex: number) => {
    updateConfig(draft => {
      const rule = draft.timePlanRules[ruleIndex];
      rule.ratios.push(1);
      rule.segments.push({ stage: '新阶段', description: '阶段说明' });
    });
  };

  const deleteSegment = (ruleIndex: number, segmentIndex: number) => {
    updateConfig(draft => {
      const rule = draft.timePlanRules[ruleIndex];
      rule.ratios.splice(segmentIndex, 1);
      rule.segments.splice(segmentIndex, 1);
    });
  };

  const sectionItems = useMemo(() => sections.map((section, sectionIndex) => ({
    key: `section-${sectionIndex}`,
    label: (
      <Space>
        <Text strong>{section.label || section.key || '未命名分组'}</Text>
        {section.key && section.key !== section.label && <Tag color="blue">key: {section.key}</Tag>}
        <Tag>{section.type}</Tag>
        {isLockedVideoSpecSection(section.key) && <Tag color="red">系统锁定</Tag>}
        {!section.enabled && !isLockedVideoSpecSection(section.key) && <Tag color="default">已禁用</Tag>}
      </Space>
    ),
    children: (
      <Space direction="vertical" style={{ width: '100%' }} size="middle">
        <Row gutter={12} align="middle">
          <Col span={4}><Input addonBefore="key" value={section.key} maxLength={64} placeholder="传给 AI 的字段名" disabled={isLockedVideoSpecSection(section.key)} onChange={e => updateSection(sectionIndex, { key: e.target.value })} /></Col>
          <Col span={4}><Input addonBefore="label" value={section.label} maxLength={64} placeholder="后台显示名称" onChange={e => updateSection(sectionIndex, { label: e.target.value })} /></Col>
          <Col span={4}>
            <Select value={section.type as any} options={NODE_TYPES} style={{ width: '100%' }} disabled={isLockedVideoSpecSection(section.key)} onChange={value => updateSection(sectionIndex, { type: value })} />
          </Col>
          <Col span={3}><Space>启用<Switch checked={isLockedVideoSpecSection(section.key) ? true : section.enabled} disabled={isLockedVideoSpecSection(section.key)} onChange={checked => updateSection(sectionIndex, { enabled: checked })} /></Space></Col>
          <Col span={3}><Space>可编辑<Switch checked={section.editable} onChange={checked => updateSection(sectionIndex, { editable: checked })} /></Space></Col>
          <Col span={4}><InputNumber min={1} max={20000} value={section.maxLength} addonBefore="长度" style={{ width: '100%' }} onChange={value => updateSection(sectionIndex, { maxLength: Number(value || 1000) })} /></Col>
          <Col span={2} style={{ textAlign: 'right' }}>
            <Popconfirm title="确认删除该分组？" disabled={isLockedVideoSpecSection(section.key)} onConfirm={() => deleteSection(sectionIndex)}>
              <Button danger icon={<DeleteOutlined />} disabled={isLockedVideoSpecSection(section.key)} />
            </Popconfirm>
          </Col>
        </Row>

        {section.type === 'object' && (
          <Card size="small" title="对象字段" extra={<Button size="small" icon={<PlusOutlined />} onClick={() => addChild(sectionIndex)}>新增字段</Button>}>
            <Space direction="vertical" style={{ width: '100%' }}>
              {(section.children || []).map((child, childIndex) => (
                <Row gutter={8} align="middle" key={`child-${sectionIndex}-${childIndex}`}>
                  <Col span={4}><Input addonBefore="key" value={child.key} maxLength={64} placeholder="传给 AI 的字段名" disabled={isLockedVideoSpecField(section.key, child.key)} onChange={e => updateChild(sectionIndex, childIndex, { key: e.target.value })} /></Col>
                  <Col span={4}><Input addonBefore="label" value={child.label} maxLength={64} placeholder="后台显示名称" onChange={e => updateChild(sectionIndex, childIndex, { label: e.target.value })} /></Col>
                  <Col span={3}><Select value={child.type as any} options={NODE_TYPES.filter(item => item.value !== 'object' && item.value !== 'flow')} style={{ width: '100%' }} disabled={isLockedVideoSpecField(section.key, child.key)} onChange={value => updateChild(sectionIndex, childIndex, { type: value })} /></Col>
                  <Col span={2}><Space>启用<Switch checked={isLockedVideoSpecField(section.key, child.key) ? true : child.enabled} disabled={isLockedVideoSpecField(section.key, child.key)} onChange={checked => updateChild(sectionIndex, childIndex, { enabled: checked })} /></Space></Col>
                  <Col span={2}><Space>编辑<Switch checked={isLockedVideoSpecField(section.key, child.key) ? false : child.editable} disabled={isLockedVideoSpecField(section.key, child.key)} onChange={checked => updateChild(sectionIndex, childIndex, { editable: checked })} /></Space></Col>
                  <Col span={3}><InputNumber min={1} max={20000} value={child.maxLength} addonBefore="长度" style={{ width: '100%' }} onChange={value => updateChild(sectionIndex, childIndex, { maxLength: Number(value || 1000) })} /></Col>
                  <Col span={5}>
                    <Input value={Array.isArray(child.value) ? child.value.join('/') : String(child.value ?? '')} maxLength={child.maxLength || 1000} placeholder="默认值" onChange={e => updateChild(sectionIndex, childIndex, { value: child.type === 'array' ? e.target.value.split('/').filter(Boolean) : e.target.value })} />
                  </Col>
                  <Col span={1} style={{ textAlign: 'right' }}>
                    <Button danger size="small" icon={<DeleteOutlined />} disabled={isLockedVideoSpecField(section.key, child.key)} onClick={() => deleteChild(sectionIndex, childIndex)} />
                  </Col>
                </Row>
              ))}
            </Space>
          </Card>
        )}

        {section.type === 'flow' && (
          <Card size="small" title="流程数组对象字段" extra={<Button size="small" icon={<PlusOutlined />} onClick={() => addFlowField(sectionIndex)}>新增流程字段</Button>}>
            <Row gutter={12} style={{ marginBottom: 12 }}>
              <Col span={6}><Input addonBefore="内容字段" value={section.contentKey} maxLength={64} onChange={e => updateSection(sectionIndex, { contentKey: e.target.value })} /></Col>
              <Col span={18}><Input addonBefore="别名 / 分隔" value={(section.contentAliases || []).join('/')} onChange={e => updateSection(sectionIndex, { contentAliases: e.target.value.split('/').map(item => item.trim()).filter(Boolean) })} /></Col>
            </Row>
            <Space direction="vertical" style={{ width: '100%' }}>
              {(section.itemFields || []).map((field, fieldIndex) => (
                <Row gutter={8} align="middle" key={`flow-${sectionIndex}-${fieldIndex}`}>
                  <Col span={5}><Input addonBefore="key" value={field.key} maxLength={64} placeholder="流程对象字段名" onChange={e => updateFlowField(sectionIndex, fieldIndex, { key: e.target.value })} /></Col>
                  <Col span={5}><Input addonBefore="label" value={field.label} maxLength={64} placeholder="后台显示名称" onChange={e => updateFlowField(sectionIndex, fieldIndex, { label: e.target.value })} /></Col>
                  <Col span={3}><Space>启用<Switch checked={field.enabled} onChange={checked => updateFlowField(sectionIndex, fieldIndex, { enabled: checked })} /></Space></Col>
                  <Col span={3}><Space>编辑<Switch checked={field.editable} onChange={checked => updateFlowField(sectionIndex, fieldIndex, { editable: checked })} /></Space></Col>
                  <Col span={4}><InputNumber min={1} max={20000} value={field.maxLength} addonBefore="长度" style={{ width: '100%' }} onChange={value => updateFlowField(sectionIndex, fieldIndex, { maxLength: Number(value || 800) })} /></Col>
                  <Col span={3}><Input value={String(field.value ?? '')} maxLength={field.maxLength || 800} placeholder="默认值" onChange={e => updateFlowField(sectionIndex, fieldIndex, { value: e.target.value })} /></Col>
                  <Col span={1} style={{ textAlign: 'right' }}><Button danger size="small" icon={<DeleteOutlined />} onClick={() => deleteFlowField(sectionIndex, fieldIndex)} /></Col>
                </Row>
              ))}
            </Space>
          </Card>
        )}

        {section.type !== 'object' && section.type !== 'flow' && (
          <Card size="small" title="默认值">
            <TextArea rows={3} value={Array.isArray(section.value) ? section.value.join('\n') : String(section.value ?? '')} maxLength={section.maxLength || 1000} showCount onChange={e => updateSection(sectionIndex, { value: section.type === 'array' ? e.target.value.split('\n').filter(Boolean) : e.target.value })} />
          </Card>
        )}
      </Space>
    ),
  })), [sections]);

  if (loading || !config) {
    return <Spin />;
  }

  return (
    <div style={{ padding: 24 }}>
      <Card>
        <Space direction="vertical" style={{ width: '100%' }} size="large">
          <Row justify="space-between" align="middle">
            <Col>
              <Title level={3} style={{ margin: 0 }}>视频提词 Schema 配置</Title>
              <Paragraph type="secondary" style={{ marginBottom: 0 }}>
                配置会被爆款开头复刻和拆镜复刻第 4 步视频 AI 提词共同复用。传给 AI 时只保留纯键值 schema，不携带显示名、启用、可编辑等管理字段。
              </Paragraph>
            </Col>
            <Col>
              <Space>
                <Text>启用自定义配置</Text>
                <Switch checked={enabled} onChange={setEnabled} />
                {usingDefault && <Tag color="orange">当前使用默认配置兜底</Tag>}
                {defaultConfig && <Tag>默认分组 {defaultConfig.sections.length}</Tag>}
              </Space>
            </Col>
          </Row>

          <Alert
            type="info"
            showIcon
            message="长度限制策略"
            description="只对管理后台字段和用户可编辑字段做长度校验，不会自动裁剪 AI 生成结果或第 5 步最终视频 prompt。若供应商因为 prompt 过长拒绝，会按真实失败进入现有日志/退款/重试流程。"
          />

          <Alert
            type="warning"
            showIcon
            message="预览说明"
            description="预览会跟随右上角「启用自定义配置」开关。关闭时会按默认 CLIENT_SCHEMA_V1 兜底预览；打开后才会按当前页面编辑的 sections 和秒数切片规则预览。"
          />

          <Space wrap>
            <Button type="primary" icon={<SaveOutlined />} loading={saving} onClick={save}>保存配置</Button>
            <Button icon={<EyeOutlined />} onClick={openPreview}>预览运行时 Schema</Button>
            <Button icon={<DownloadOutlined />} onClick={doExport}>导出 JSON</Button>
            <Button icon={<UploadOutlined />} onClick={() => importInputRef.current?.click()}>导入 JSON</Button>
            <Popconfirm title="确认恢复默认配置？" description="会用 CLIENT_SCHEMA_V1 生成的默认配置覆盖当前配置。" onConfirm={resetDefault}>
              <Button icon={<ReloadOutlined />}>恢复默认</Button>
            </Popconfirm>
            <input ref={importInputRef} type="file" accept="application/json,.json" style={{ display: 'none' }} onChange={onImportFile} />
          </Space>

          <Tabs
            items={[
              {
                key: 'fields',
                label: 'Schema 字段配置',
                children: (
                  <Space direction="vertical" style={{ width: '100%' }} size="middle">
                    <Alert
                      type="warning"
                      showIcon
                      message="字段说明"
                      description="key 是最终传给 AI 和保存到 prompt_schema 的真实字段名，例如「素材理解」「动作流程」；label 只用于管理后台显示，帮助运营/管理员理解这个字段，不会传给 AI；启用关闭后该字段不会进入运行时 schema；可编辑关闭后用户在第 4 步修改时不能改这个字段。「画面属性」里的视频时长、视频比例、清晰度、帧率、推荐分辨率属于系统锁定参数，不能改 key、不能禁用、不能开放用户编辑。"
                    />
                    <Button icon={<PlusOutlined />} onClick={addSection}>新增一级分组</Button>
                    <Collapse items={sectionItems} />
                  </Space>
                ),
              },
              {
                key: 'time',
                label: '秒数切片规则',
                children: (
                  <Space direction="vertical" style={{ width: '100%' }} size="middle">
                    <Alert
                      type="info"
                      showIcon
                      message="切片规则说明"
                      description="这里决定指定视频时长会被拆成几段，以及每段的阶段名称和说明。运行时会同步生成「动态时间规划」「动作流程」「镜头流程」三个数组，三者时间段保持一致。"
                    />
                    <Button icon={<PlusOutlined />} onClick={addTimeRule}>新增秒数规则</Button>
                    {timePlanRules.map((rule, ruleIndex) => (
                      <Card
                        key={ruleIndex}
                        size="small"
                        title={`${rule.minDuration}-${rule.maxDuration} 秒：${rule.segments.length} 段`}
                        extra={<Button danger size="small" icon={<DeleteOutlined />} onClick={() => deleteTimeRule(ruleIndex)}>删除规则</Button>}
                      >
                        <Row gutter={12} style={{ marginBottom: 12 }}>
                          <Col span={4}><InputNumber min={1} value={rule.minDuration} addonBefore="最小秒" style={{ width: '100%' }} onChange={value => updateTimeRule(ruleIndex, { minDuration: Number(value || 1) })} /></Col>
                          <Col span={4}><InputNumber min={1} value={rule.maxDuration} addonBefore="最大秒" style={{ width: '100%' }} onChange={value => updateTimeRule(ruleIndex, { maxDuration: Number(value || 1) })} /></Col>
                          <Col span={16}><Button size="small" icon={<PlusOutlined />} onClick={() => addSegment(ruleIndex)}>新增片段</Button></Col>
                        </Row>
                        <Space direction="vertical" style={{ width: '100%' }}>
                          {rule.segments.map((segment, segmentIndex) => (
                            <Row gutter={8} align="middle" key={segmentIndex}>
                              <Col span={3}><InputNumber min={0.01} step={0.01} value={rule.ratios[segmentIndex]} addonBefore="比例" style={{ width: '100%' }} onChange={value => updateSegment(ruleIndex, segmentIndex, { ratio: Number(value || 0.01) })} /></Col>
                              <Col span={5}><Input value={segment.stage} maxLength={64} placeholder="阶段" onChange={e => updateSegment(ruleIndex, segmentIndex, { stage: e.target.value })} /></Col>
                              <Col span={15}><Input value={segment.description} maxLength={300} placeholder="说明" onChange={e => updateSegment(ruleIndex, segmentIndex, { description: e.target.value })} /></Col>
                              <Col span={1}><Button danger size="small" icon={<DeleteOutlined />} onClick={() => deleteSegment(ruleIndex, segmentIndex)} /></Col>
                            </Row>
                          ))}
                        </Space>
                      </Card>
                    ))}
                  </Space>
                ),
              },
              {
                key: 'json',
                label: 'JSON 高级查看',
                children: <TextArea rows={24} value={JSON.stringify(toApiConfig(config, enabled), null, 2)} readOnly />,
              },
            ]}
          />
        </Space>
      </Card>

      <Modal title="预览运行时 Schema" open={previewOpen} onCancel={() => setPreviewOpen(false)} width={980} footer={<Space><Button onClick={() => setPreviewOpen(false)}>关闭</Button><Button type="primary" onClick={doPreview}>生成预览</Button></Space>}>
        <Form form={previewForm} layout="inline" style={{ marginBottom: 16 }}>
          <Form.Item name="duration" label="时长" rules={[{ required: true }]}><InputNumber min={1} max={3600} /></Form.Item>
          <Form.Item name="aspectRatio" label="比例" rules={[{ required: true }]}><Input /></Form.Item>
          <Form.Item name="resolution" label="清晰度" rules={[{ required: true }]}><Input /></Form.Item>
          <Form.Item name="frameRate" label="帧率" rules={[{ required: true }]}><Input /></Form.Item>
        </Form>
        <Divider />
        {previewResult ? (
          <Tabs
            items={[
              {
                key: 'runtime',
                label: '运行时 Schema',
                children: <TextArea rows={24} value={JSON.stringify(runtimePreviewSchema(previewResult), null, 2)} readOnly />,
              },
              {
                key: 'timePlan',
                label: `动态时间规划（${runtimePreviewTimePlan(previewResult).length} 段）`,
                children: <TextArea rows={24} value={JSON.stringify(runtimePreviewTimePlan(previewResult), null, 2)} readOnly />,
              },
              {
                key: 'snapshot',
                label: '配置快照',
                children: <TextArea rows={24} value={JSON.stringify(runtimePreviewSnapshot(previewResult), null, 2)} readOnly />,
              },
            ]}
          />
        ) : (
          <Alert type="info" showIcon message="点击生成预览后，可以看到传给 AI 的纯 schema、动态时间规划和本次配置快照。" />
        )}
      </Modal>
    </div>
  );
};

export default AdminVideoPromptSchemaConfig;
