import { z } from 'zod';

/**
 * ReasonSignals — plan_reasons.signals JSON 字段的强校验 schema。
 *
 * 设计原则(W3 末):
 *   - DB 存 **原始 enum / canonical code**,不存中文(name_zh 翻译归前端 i18n)
 *   - 字段命名 PAC 标准 camelCase,跨 scenario 通用
 *   - triggers 是**数组**(留多信号源融合余地;当前 scenario 单源 → 长度 1)
 *   - factId 不存这里 — 走 plan_reasons.evidence JSON(`{ factIds[] }`,跟 PersonaFeature.evidence 同形),避免重复
 *
 * 前端用 PACScenarioSubLabels / PACTriggerTypeLabels / diagnosisCodeNameZh /
 * treatmentCategoryNameZh 翻译展示。
 */
export const ReasonSignalsSchema = z.object({
  /// 子规则 key(对齐 scenario 内 subKey:missing_tooth / caries_no_filling / perio_no_srp / endo_no_rct …)
  subKey: z.string().min(1),

  /// 触发信号数组(多信号源融合留余地)
  /// 当前 scenario 单源命中 → 长度 1;未来 K08 + IMPLANT_RECOMMENDED + CBCT 三源合并 → 长度 3
  triggers: z
    .array(
      z.object({
        /// 触发类型 enum:diagnosis / recommendation / image_finding / emr_signal / visit_gap / ...
        /// 留 z.string() 不强 enum,未来扩展不动 schema(canonical labels 字典翻译)
        type: z.string().min(1),
        /// 触发码(PAC canonical):K08 / IMPLANT_RECOMMENDED 等;visit_gap 等无 code 场景为 null
        code: z.string().nullable().optional(),
      }),
    )
    .min(1),

  /// 牙位原文(可空 — 全口治疗 / 沉睡客户激活 等场景无牙位)
  toothPosition: z.string().nullable().optional(),

  /// 紧迫维度:触发信号距今多少天(跨场景通用)
  daysSince: z.number().int().nonnegative(),

  /// 期望待启动类别(raw PAC treatment category enum;前端用 treatmentCategoryNameZh 翻译)
  /// 不同场景含义:
  ///   - 召回类:期望启动哪类治疗(种植 / 充填 / 牙周基础 / 根管)
  ///   - 沉睡激活:可能是 [recall_visit] 等
  expectedCategories: z.array(z.string()),
});
export type ReasonSignals = z.infer<typeof ReasonSignalsSchema>;
