/**
 * 质量组件注册表 → AI 积木清单
 * <p>
 * 清单是注册表的**派生视图**：剥掉 icon / buildContent / validate 这些不可序列化的成员，
 * 只留下模型需要知道的「有哪些组件、每个组件能填哪些字段」。
 * <p>
 * 这份清单随请求传给后端拼进提示词，但它<b>不是</b>合法性的判据：真正把关的是装配器
 * 对着活注册表查 getQualityComponent。模型即便编出清单外的 type，也只会被跳过，
 * 永远变不成任意 HTML（清单里不含任何 HTML 能力的描述）。
 */
import type { QualityFieldSchema } from './types';

import { listQualityComponents } from './registry';

/** 清单里的一个可填字段，与后端 QcReportComponentSpecVO.Field 一一对应 */
export interface QualityCatalogField {
  key: string;
  label: string;
  type: QualityFieldSchema['type'];
  required?: boolean;
  bindable?: boolean;
  /**
   * 枚举候选项。
   * <p>
   * 用 {label, value} 成对给出：只给 label 模型会照着输出中文标签，
   * 只给 value 又不知道含义。成对给出，它才知道该输出哪个字面量。
   */
  enumOptions?: { label: string; value: number | string }[];
}

/** 一个组件积木 */
export interface QualityComponentCatalog {
  type: string;
  label: string;
  /** 组件分类的中文显示名，帮模型理解组件用途 */
  category: string;
  /**
   * 组件的选型说明，来自注册表的 aiHint。
   * <p>
   * 只有 label 时，模型面对「报告抬头」这类内容会在 Heading / Text / ReportHeader 之间瞎猜，
   * 且总会挑字段最简单的基础组件。这段文字就是给它划边界的，不是给人看的。
   */
  hint?: string;
  fields: QualityCatalogField[];
}

/** 从活注册表生成积木清单，顺序与设计器左侧面板一致 */
export function buildQualityComponentCatalog(): QualityComponentCatalog[] {
  const definitions = listQualityComponents();
  // 注册表要显式调用 registerAllQualityComponents() 才有内容（设计器在 init 时做）。
  // 空清单会被后端判为入参非法，报出来的错和真实原因隔了好几层，所以在这里就说清楚。
  if (definitions.length === 0) {
    throw new Error('质量组件注册表为空，请先调用 registerAllQualityComponents()');
  }
  return definitions.map((definition) => {
    const item: QualityComponentCatalog = {
      type: definition.type,
      label: definition.label,
      category: definition.category,
      fields: definition.propertySchema.map(toCatalogField),
    };
    // 缺席即省略，与 toCatalogField 同一风格：省掉的字段能明显缩小提示词
    if (definition.aiHint) {
      item.hint = definition.aiHint;
    }
    return item;
  });
}

function toCatalogField(field: QualityFieldSchema): QualityCatalogField {
  const item: QualityCatalogField = {
    key: field.key,
    label: field.label,
    type: field.type,
  };
  // 缺席即「否」，省掉的字段能明显缩小提示词
  if (field.required) {
    item.required = true;
  }
  if (field.bindable) {
    item.bindable = true;
  }
  if (field.options?.length) {
    item.enumOptions = field.options.map((option) => ({
      label: option.label,
      value: option.value,
    }));
  }
  return item;
}
