export type JsonValue = any;
export type JsonRecord = Record<string, JsonValue>;

export interface VideoPromptSchemaFieldConfig {
  key: string;
  label: string;
  type?: string;
  enabled: boolean;
  editable: boolean;
  maxLength?: number;
}

export interface VideoPromptSchemaSectionConfig extends VideoPromptSchemaFieldConfig {
  contentKey?: string;
  itemFields: VideoPromptSchemaFieldConfig[];
  children: VideoPromptSchemaFieldConfig[];
}

function isRecord(value: unknown): value is JsonRecord {
  return !!value && typeof value === 'object' && !Array.isArray(value);
}

function readString(source: JsonRecord, ...keys: string[]): string {
  for (const key of keys) {
    const value = source[key];
    if (value !== undefined && value !== null && String(value).trim() !== '') return String(value);
  }
  return '';
}

function readBool(source: JsonRecord, defaultValue: boolean, ...keys: string[]): boolean {
  for (const key of keys) {
    const value = source[key];
    if (value === true || value === false) return value;
    if (value === 'true') return true;
    if (value === 'false') return false;
  }
  return defaultValue;
}

function readNumber(source: JsonRecord, ...keys: string[]): number | undefined {
  for (const key of keys) {
    const value = source[key];
    if (typeof value === 'number' && Number.isFinite(value) && value > 0) return value;
    if (typeof value === 'string' && value.trim()) {
      const parsed = Number(value);
      if (Number.isFinite(parsed) && parsed > 0) return parsed;
    }
  }
  return undefined;
}

function normalizeField(raw: unknown): VideoPromptSchemaFieldConfig | null {
  if (!isRecord(raw)) return null;
  const key = readString(raw, 'key');
  if (!key) return null;
  return {
    key,
    label: readString(raw, 'label') || key,
    type: readString(raw, 'type') || undefined,
    enabled: readBool(raw, true, 'enabled'),
    editable: readBool(raw, true, 'editable'),
    maxLength: readNumber(raw, 'maxLength', 'max_length'),
  };
}

export function getSchemaConfigData(snapshot: unknown): JsonRecord | null {
  if (!isRecord(snapshot)) return null;
  const data = snapshot.data;
  if (isRecord(data)) return data;
  if (Array.isArray(snapshot.sections)) return snapshot;
  return null;
}

export function hasSchemaConfigSnapshot(snapshot: unknown): boolean {
  return !!getSchemaConfigData(snapshot);
}

export function normalizeSchemaSections(snapshot: unknown): VideoPromptSchemaSectionConfig[] {
  const data = getSchemaConfigData(snapshot);
  const rawSections = Array.isArray(data?.sections) ? data.sections : [];
  return rawSections
    .map((raw): VideoPromptSchemaSectionConfig | null => {
      const base = normalizeField(raw);
      if (!base || !isRecord(raw)) return null;
      const children = Array.isArray(raw.children) ? raw.children.map(normalizeField).filter(Boolean) as VideoPromptSchemaFieldConfig[] : [];
      const itemFields = Array.isArray(raw.itemFields)
        ? raw.itemFields.map(normalizeField).filter(Boolean) as VideoPromptSchemaFieldConfig[]
        : Array.isArray(raw.item_fields)
          ? raw.item_fields.map(normalizeField).filter(Boolean) as VideoPromptSchemaFieldConfig[]
          : [];
      return {
        ...base,
        contentKey: readString(raw, 'contentKey', 'content_key') || undefined,
        children,
        itemFields,
      };
    })
    .filter((section): section is VideoPromptSchemaSectionConfig => !!section && section.enabled);
}

export function stringifySchemaValue(value: JsonValue): string {
  if (value === null || value === undefined) return '';
  if (typeof value === 'object') {
    try {
      return JSON.stringify(value, null, 2);
    } catch {
      return String(value);
    }
  }
  return String(value);
}

export function shouldUseSchemaTextArea(value: JsonValue): boolean {
  const text = stringifySchemaValue(value);
  return text.length > 40 || text.includes('\n') || text.includes('，') || text.includes('。') || text.includes(';') || text.includes('；');
}

export function clonePlain<T>(value: T): T {
  return value === undefined ? value : JSON.parse(JSON.stringify(value));
}

export function setObjectField(root: JsonRecord, sectionKey: string, fieldKey: string, value: JsonValue): JsonRecord {
  const next = clonePlain(root || {});
  if (!isRecord(next[sectionKey])) next[sectionKey] = {};
  (next[sectionKey] as JsonRecord)[fieldKey] = value;
  return next;
}

export function setArrayObjectField(root: JsonRecord, sectionKey: string, index: number, fieldKey: string, value: JsonValue): JsonRecord {
  const next = clonePlain(root || {});
  if (!Array.isArray(next[sectionKey])) next[sectionKey] = [];
  if (!isRecord(next[sectionKey][index])) next[sectionKey][index] = {};
  next[sectionKey][index][fieldKey] = value;
  return next;
}

export function validateVideoPromptSchemaByConfig(schema: unknown, snapshot: unknown): string | null {
  if (!isRecord(schema)) return '视频提示词不能为空';
  const sections = normalizeSchemaSections(snapshot);
  if (!sections.length) return '视频提词配置缺失，无法保存';

  for (const section of sections) {
    if (!section.editable) continue;
    const sectionValue = schema[section.key];
    if (section.type === 'object') {
      if (!isRecord(sectionValue)) continue;
      for (const child of section.children) {
        if (!child.enabled || !child.editable || !child.maxLength) continue;
        const text = stringifySchemaValue(sectionValue[child.key]);
        if (text.length > child.maxLength) {
          return `字段【${section.label}.${child.label}】长度不能超过 ${child.maxLength} 个字符`;
        }
      }
      continue;
    }
    if (section.type === 'flow') {
      if (!Array.isArray(sectionValue)) continue;
      for (let index = 0; index < sectionValue.length; index += 1) {
        const item = sectionValue[index];
        if (!isRecord(item)) continue;
        for (const field of section.itemFields) {
          if (!field.enabled || !field.editable || !field.maxLength) continue;
          const text = stringifySchemaValue(item[field.key]);
          if (text.length > field.maxLength) {
            return `字段【${section.label} 第 ${index + 1} 项.${field.label}】长度不能超过 ${field.maxLength} 个字符`;
          }
        }
      }
      continue;
    }
    if (section.editable && section.maxLength) {
      const text = stringifySchemaValue(sectionValue);
      if (text.length > section.maxLength) {
        return `字段【${section.label}】长度不能超过 ${section.maxLength} 个字符`;
      }
    }
  }
  return null;
}
