/**
 * Parser 接口 — transaction → fact 衍生
 *
 * 一条 transaction 经 parser 解析后产出 0/1/N 个 FactDraft;
 * 由 FactWriter 写入 patient_facts 版本流(active 对比 + supersede + 新版本)。
 *
 * 三个上游入口共用(对应 TransactionSynthesizer):
 *   - ColdImportService(W2,文件)
 *   - PullAdapter(W5+,HTTP 周期拉)
 *   - PushReceiver(W5+,HTTP webhook)
 *
 * 路由:按 `transaction.action` 查 ParserRegistry 拿到对应 Parser。
 */

import type { Action, FactKind, FactType, FactStatus } from '@pac/types';
import type { Prisma } from '@prisma/client';

/**
 * Parser 输出的事实草稿 — 一条 transaction 可产出多个。
 *
 * `subjectId` 是业务身份(跨版本稳定),由 Parser 自己合成,**必须保证同一事实在两次 import 中给出同一 subjectId**;
 * 否则版本流会断,产生重复 active。
 *
 * subjectId 命名约定(防类型间冲突):
 *   - 主体型(对应 SubjectType 的一一映射):`<fact_type>:<host_subject_id>`
 *     例:`encounter_record:enc_001`
 *   - 衍生型(parser 派生,host 无对应 id):`<fact_type>:<scope_keys...>`
 *     例:`treatment_record:enc_001:11:endodontic:root_canal`
 *         `review_plan:enc_001:11:crown_restoration`
 */
export interface FactDraft {
  /// 业务身份,跨版本稳定
  subjectId: string;
  kind: FactKind;
  type: FactType;
  /// 默认 active;允许 parser 直接产出 cancelled/expired 等终态(罕见)
  status?: FactStatus;

  clinicId?: string | null;
  occurredAt?: Date | null; // actual 应填
  plannedFor?: Date | null; // planned 推荐填
  validFrom?: Date | null;
  validUntil?: Date | null;

  title?: string | null;
  summary?: string | null;
  /// 结构化内容(per type schema 由应用层 zod 校验,Day 5 起步不强约束)
  content: Prisma.InputJsonValue;
}

/**
 * Parser 输入上下文 — 由 ParserPipeline 喂给具体 Parser。
 *
 * 注意:
 *   - `transaction` 是已经写库的 PatientTransaction(含 id,供 FactDraft.transactionIds 引证)
 *   - `canonicalRow` 是 fieldMapping 后的行(parser 主消费);**rawRow 由 transaction.rawPayload 拿,parser 一般不用**
 */
export interface ParserContext {
  transaction: {
    id: string;
    hostId: string;
    tenantId: string;
    patientId: string | null;
    action: Action;
    subjectType: string;
    subjectId: string;
    occurredAt: Date;
    clinicId: string;
  };
  canonicalRow: Record<string, unknown>;
}

export interface Parser {
  /// 标识用(日志 / 调试),通常等于 Action 字符串
  readonly name: string;
  parse(ctx: ParserContext): FactDraft[];
}
