/**
 * Plan Scenario 插件接口
 *
 * 每个 scenario 自己跑 selector(SQL on patient_facts.content JSONB),返回命中清单。
 * PlanEngine 汇总跨 scenario 的命中 → 按 patient 合并 → 写 FollowupPlan + PlanReason(plan 1:N reason)。
 *
 * 设计纪律:
 *   - shouldInclude / produce 不分开,直接 selectHits 一次出结果(SQL 高效)
 *   - 通用过滤(active / dnc / deceased / no-phone)由各 scenario SQL 自己写(共用 SQL 片段后续抽)
 *   - 子场景信息进 hit.reason 文本(不立 sub_scenario 字段;db-review-confirm §3.5)
 */
export interface PlanScenarioPlugin {
  readonly key: string;
  selectHits(scope: ScenarioScope): Promise<ScenarioHit[]>;
}

export interface ScenarioScope {
  hostId: string;
  tenantId: string;
  now: Date;
  /// 可选:只评估单个 patient(详情页"刷新"单刷场景)。
  /// 设了 → selectHits SQL 加 `AND p.id = patientId`,从全租户扫降为单患者扫(O(1))。
  patientId?: string;
}

export interface ScenarioHit {
  /// PAC 内部 patient.id(uuid)
  patientId: string;
  /// host 侧 external id(诊断展示用)
  patientExternalId: string;

  /// 召回理由自然语言(包含子场景 + 关键事实)— 客服直接看
  reason: string;
  /// 优先级分(0-100;plan 维度 MAX 聚合)
  priorityScore: number;
  /// scenario 维度业务目标(可空,plan 级)
  goal?: string;

  /// 推荐触达时间 / 角色 / 渠道(可空)
  recommendedAt?: Date | null;
  recommendedRole?: string | null;
  recommendedChannel?: string | null;
  /// 期望执行诊所(null = 集团池)
  targetClinicId?: string | null;

  /// 证据 fact.ids(plan_reasons.evidence JSON 落库,W3 末从 UUID[] 改 jsonb 统一跟 PersonaFeature 对齐)
  /// scenario 输出 { factIds[] };后端 plan-engine 写入时包成 { factIds: [...] } JSON
  evidence: {
    factIds: string[];
  };

  /// 子场景标识(reason 文本内已含,落 plan_reasons.breakdown.subKey 便于 metrics 检索)
  subKey?: string;

  /// cluster 内**最新**信号发生时间(时间锚抑制逃逸用,与 signals.signalOccurredAt 的"最早"锚相反):
  /// 终态抑制(外院/拒绝的"永久" snooze)只压"结案时已知的问题" —— 结案后新发的同类诊断
  /// (同 subKey 新 fact)应放行复活。引擎按 latest > 结案锚点 判断逃逸;缺省(旧 scenario)= 不逃逸。
  latestSignalOccurredAt?: Date | null;

  /// **W3 末新增**:结构化召回信号(plan_reasons.signals JSON 落库)。
  /// DB 存原始 enum / canonical code(不语义化),前端用 @pac/types 字典翻译富文本渲染。
  /// 详见 packages/types/src/schemas/reason-signals.ts
  signals?: import('@pac/types').ReasonSignals;

  /// 6 因子优先级 breakdown(算法 v2);可空兼容旧 scenario
  /// 详情页用本字段渲染"客服可解释性"。
  priorityBreakdown?: import('./priority-scorer').PriorityBreakdown;
}
