/**
 * 质量组件协议（Quality Component Protocol）
 * <p>
 * 设计器只认这套协议，不认具体业务组件：新增质量组件＝注册一个新 definition，
 * 不需要改动 GrapesJS 集成代码，也不需要改动设计器页面（方案设计 §9）。
 */

/** 组件分类，顺序即设计器左侧面板的分组顺序 */
export const QUALITY_CATEGORY = {
  BASIC: '基础组件',
  HEADER: '报告组件',
  INSPECTION: '检验组件',
  RESULT: '结果组件',
} as const;

export type QualityCategory = (typeof QUALITY_CATEGORY)[keyof typeof QUALITY_CATEGORY];

/** 分类的展示顺序 */
export const QUALITY_CATEGORY_ORDER: QualityCategory[] = [
  QUALITY_CATEGORY.BASIC,
  QUALITY_CATEGORY.HEADER,
  QUALITY_CATEGORY.INSPECTION,
  QUALITY_CATEGORY.RESULT,
];

/** 属性字段的值类型，决定属性面板用什么控件 */
export type QualityFieldType =
  | 'boolean'
  | 'enum'
  | 'number'
  | 'string'
  | 'text';

/** 属性字段的可选项 */
export interface QualityFieldOption {
  label: string;
  value: number | string;
}

/**
 * 一个业务属性 / 可绑定数据字段的描述。
 * <p>
 * propertySchema 描述「设计期用户能改什么」，dataSchema 描述「渲染期能绑什么」，
 * 两者共用一个结构，区别只在用途。
 */
export interface QualityFieldSchema {
  /** 字段键，同时是写入画布 attributes 的 data-qc-<key> 名 */
  key: string;
  label: string;
  type: QualityFieldType;
  /** 默认值，必须与 type 对应 */
  defaultValue?: boolean | number | string;
  /** type 为 enum 时的候选项 */
  options?: QualityFieldOption[];
  placeholder?: string;
  /** 输入提示，展示在属性面板字段下方 */
  tip?: string;
  /** 是否必填（校验用） */
  required?: boolean;
  /**
   * 是否允许绑定数据源表达式（{{path}}）。
   * 为 false 时属性面板不提供「绑定数据」入口。
   */
  bindable?: boolean;
  /**
   * bindable 为 true 时，从数据字段里挑中后写回属性值的形式。
   * <p>
   * - text（默认）：写成 {{path}}，渲染期按绑定协议替换成数据值，适用于标题、文本、结论等；
   * - path：直接写裸路径，渲染期把它当作结构化路径用（如按数组逐行生成的检验项数据源），
   *   包上 {{}} 反而会让渲染期找不到数组。
   */
  bindAs?: 'path' | 'text';
}

/** 业务属性的运行时取值 */
export type QualityProps = Record<string, boolean | number | string | undefined>;

/** GrapesJS 组件内容，等价于 BlockProperties['content'] 的常用子集 */
export interface QualityComponentContent {
  tagName?: string;
  /** 子组件：HTML 字符串或组件描述对象数组 */
  components?: QualityComponentContent[] | string;
  content?: string;
  attributes?: Record<string, string>;
  style?: Record<string, string>;
}

/**
 * 质量组件定义：注册进 registry 的唯一协议。
 */
export interface QualityComponentDefinition {
  /** 唯一类型标识，写入画布的 data-quality-type，也是 Schema.components[].qualityType */
  type: string;
  /** 英文名，用于代码内引用 */
  name: string;
  /** 设计器左侧面板与属性面板的显示名 */
  label: string;
  category: QualityCategory;
  /** 左侧面板的图标（内联 SVG 字符串） */
  icon: string;
  /** 新组件落到画布时的初始业务属性 */
  defaults: QualityProps;
  /** 设计期可编辑的业务属性 */
  propertySchema: QualityFieldSchema[];
  /** 渲染期可绑定的数据字段 */
  dataSchema: QualityFieldSchema[];
  /**
   * 组件的可见文本对应的属性 key。
   * <p>
   * 声明后，用户在画布内直接改文字会同步回该属性，属性面板改值也会同步回画布；
   * 内容由多个元素拼成的组件（页眉、表格）不声明，避免整块 HTML 被当成文本。
   */
  contentKey?: string;
  /**
   * 给 AI 导入用的选型说明：这个组件用来放什么、不要用来放什么。
   * <p>
   * 不进设计器界面，只随积木清单进提示词。写它是因为清单里只有 label 时，
   * 模型面对「报告抬头」这类内容会在 Heading / Text / ReportHeader 之间瞎猜，
   * 而只会看到中文标签的它没有任何理由不挑最通用的那个。
   * <p>
   * 必须包含「不要用来放什么」：只讲用途挡不住误用，讲清边界才有用。
   */
  aiHint?: string;
  /**
   * 生成画布内容。properties 已经收敛过默认值，实现里可以直接用。
   */
  buildContent: (properties: QualityProps) => QualityComponentContent;
  /**
   * 校验业务属性，返回错误信息数组；空数组表示通过。
   * 仅在保存/发布前调用，正常设计过程不应触发。
   */
  validate?: (properties: QualityProps) => string[];
}