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 inferSchemaSections(schema: unknown): VideoPromptSchemaSectionConfig[] {
  if (!isRecord(schema)) return [];
  return Object.entries(schema)
    .filter(([key]) => !['schemaVersion', 'schemaUsage', 'schema_version', 'schema_usage'].includes(key))
    .map(([key, value]) => {
      if (Array.isArray(value) && value.every(isRecord)) {
        const fields = Array.from(new Set(value.flatMap((item) => Object.keys(item))));
        return {
          key,
          label: key,
          type: 'flow',
          enabled: true,
          editable: false,
          itemFields: fields.filter((field) => field !== '时间段').map((field) => ({ key: field, label: field, enabled: true, editable: false })),
          children: [],
        } as VideoPromptSchemaSectionConfig;
      }
      if (isRecord(value)) {
        return {
          key,
          label: key,
          type: 'object',
          enabled: true,
          editable: false,
          children: Object.keys(value).map((field) => ({ key: field, label: field, enabled: true, editable: false })),
          itemFields: [],
        } as VideoPromptSchemaSectionConfig;
      }
      return {
        key,
        label: key,
        type: 'text',
        enabled: true,
        editable: false,
        children: [],
        itemFields: [],
      } as VideoPromptSchemaSectionConfig;
    });
}

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);
}
