import { Injectable } from '@nestjs/common';
import { PersonaFeatureKey, FactType, FactKind } from '@pac/types';
import type {
  ActiveFact,
  FeatureExtractor,
  FeatureExtractorContext,
  PersonaFeatureDraft,
} from './feature.interface';

/**
 * treatment_history 治疗史(C.3.1)— 规则层,snapshot · 多标签(允许并列)
 *
 * 标签:种植史 / 正畸史 / 修复史 / 牙周治疗史。历史核心治疗类型,影响后续推荐与维护。
 *
 * ⭐ spec 用"病历处置/结算关键词"匹配,因数仓是原始文本;PAC canonical 层已把治疗归一成
 *   treatment_record.content.category(单一收口)→ 直接读 category,无需关键词/新摄入:
 *     implant→种植史 / orthodontic→正畸史 / prosthodontic·cosmetic→修复史(冠桥/贴面/嵌体)/
 *     periodontic→牙周治疗史。
 *   不标记:surgical(拔牙)/ restorative(充填)/ endodontic(根管)/ preventive·review·pediatric
 *     —— 基础治疗或非核心,对后续推荐影响有限(同 spec)。
 *   仅看 actual(已做);四类全不命中 → 不打标签。
 */
@Injectable()
export class TreatmentHistoryFeatureExtractor implements FeatureExtractor {
  readonly key = PersonaFeatureKey.TREATMENT_HISTORY;

  // category → { 标签 code, 中文 };一个 code 可由多 category 命中(修复史=修复+美学)
  private static readonly MAP: Record<string, { code: string; zh: string }> = {
    implant: { code: 'implant_history', zh: '种植史' },
    orthodontic: { code: 'ortho_history', zh: '正畸史' },
    prosthodontic: { code: 'prostho_history', zh: '修复史' },
    cosmetic: { code: 'prostho_history', zh: '修复史' },
    periodontic: { code: 'perio_history', zh: '牙周治疗史' },
  };
  // 输出稳定顺序
  private static readonly ORDER = ['implant_history', 'ortho_history', 'prostho_history', 'perio_history'];
  private static readonly ZH: Record<string, string> = {
    implant_history: '种植史',
    ortho_history: '正畸史',
    prostho_history: '修复史',
    perio_history: '牙周治疗史',
  };

  extract(ctx: FeatureExtractorContext): PersonaFeatureDraft | null {
    const txs = (ctx.factsByType.get(FactType.TREATMENT_RECORD) ?? []) as ActiveFact[];
    const hit = new Set<string>();
    const evidenceIds: string[] = [];
    for (const f of txs) {
      if (f.kind !== FactKind.ACTUAL) continue;
      const cat = String((f.content as Record<string, unknown>).category ?? '');
      const m = TreatmentHistoryFeatureExtractor.MAP[cat];
      if (!m) continue;
      hit.add(m.code);
      evidenceIds.push(f.id);
    }
    if (hit.size === 0) return null;

    const codes = TreatmentHistoryFeatureExtractor.ORDER.filter((c) => hit.has(c));
    const labels = codes.map((c) => TreatmentHistoryFeatureExtractor.ZH[c]!);
    return {
      key: this.key,
      description: labels.join(' / '),
      score: null,
      data: { types: codes, labels },
      evidence: { factIds: evidenceIds },
    };
  }
}
