import { Injectable, Logger } from '@nestjs/common';
import { Action, FactKind, FactStatus, FactType } from '@pac/types';
import type { Parser, ParserContext, FactDraft } from './parser.interface';
import { normalizeToothPosition } from './tooth-position.util';

/**
 * TreatmentParser — 治疗类 action 共用解析器(v2.1 新)
 *
 * 处理 4 个 action(共用 parser,kind/status 由 transaction.action 推):
 *   - TREATMENT_PLANNED     → kind=planned, status=active
 *   - TREATMENT_STARTED     → kind=actual,  status=active   (in_progress)
 *   - TREATMENT_COMPLETED   → kind=actual,  status=fulfilled(completed)
 *   - TREATMENT_CANCELLED   → kind=actual,  status=cancelled(暂未独立 action,sourced from row.status)
 *
 * **合并旧 treatment_plan / review_plan**:
 *   - 旧 treatment_plan(planned) → 本 parser kind=planned + content.category=任意治疗
 *   - 旧 review_plan(planned)    → 本 parser kind=planned + content.category=review_*(子类) +
 *                                  content.review_window_days
 *
 * subject_id 形态:
 *   `treatment_record:<externalId>` — host 给治疗 id 直接用
 *   否则合成:`treatment_record:<encounter>:<tooth>:<category>:<subtype>`(parser 自合 host 没给)
 *
 * **必填**:`category` ∈ PACTreatmentCategorySchema(yaml enum_mapping 完成翻译)。
 */
@Injectable()
export class TreatmentParser implements Parser {
  readonly name = 'treatment'; // 多 action 共用,name 字段仅日志用
  private readonly logger = new Logger(TreatmentParser.name);

  parse(ctx: ParserContext): FactDraft[] {
    const c = ctx.canonicalRow;
    const externalId = String(c.externalId ?? ctx.transaction.subjectId).trim();
    if (!externalId) {
      this.logger.warn(
        `treatment parser: missing externalId for transaction=${ctx.transaction.id};skip`,
      );
      return [];
    }

    const category = String(c.category ?? '').trim();
    if (!category) {
      this.logger.warn(
        `treatment parser: missing category for externalId=${externalId};skip ` +
          `(yaml enum_mapping 是否漏配?)`,
      );
      return [];
    }

    const { kind, status, contentStatus } = this.deriveKindStatus(
      ctx.transaction.action,
      String(c.status ?? '').toLowerCase(),
    );

    const toothPosition = normalizeToothPosition(c.toothPosition as string | undefined);
    const subtype = (c.subtype as string | undefined) ?? null;
    // W4 末:treat_stages — host stage 词已在 assembler enum_mapping 翻译到 PAC 标准 enum
    // applyEnum array 支持已加;这里只需做 array filter(去除空字符串/非字符串元素)
    const treatStagesRaw = c.treatStages;
    const treatStages = Array.isArray(treatStagesRaw)
      ? treatStagesRaw
          .filter((s): s is string => typeof s === 'string' && s.length > 0)
      : null;
    const startedAt = c.startedAt ? new Date(c.startedAt as string) : null;
    const completedAt = c.completedAt ? new Date(c.completedAt as string) : null;
    const doctorId = c.doctorId ? String(c.doctorId) : null; // host Int64,0/null → null
    const sourceEncounter = (c.sourceEncounterExternalId as string | undefined) ?? null;
    const relatedDx = (c.relatedDiagnosisExternalId as string | undefined) ?? null;
    const reviewWindow =
      typeof c.reviewWindowDays === 'number'
        ? c.reviewWindowDays
        : c.reviewWindowDays
          ? Number(c.reviewWindowDays)
          : null;

    return [
      {
        subjectId: `${FactType.TREATMENT_RECORD}:${externalId}`,
        kind,
        type: FactType.TREATMENT_RECORD,
        status,
        clinicId: ctx.transaction.clinicId,
        occurredAt: kind === FactKind.ACTUAL ? ctx.transaction.occurredAt : null,
        plannedFor: kind === FactKind.PLANNED ? ctx.transaction.occurredAt : null,
        title:
          `治疗 ${category}` +
          (subtype ? ` · ${subtype}` : '') +
          (toothPosition ? ` · 牙位 ${toothPosition}` : ''),
        summary: null,
        content: {
          category,
          subtype,
          tooth_position: toothPosition,
          status: contentStatus,
          started_at: startedAt ? startedAt.toISOString() : null,
          completed_at: completedAt ? completedAt.toISOString() : null,
          doctor_id: doctorId,
          doctor_name: (c.doctorName as string | undefined) ?? null,
          quantity:
            c.quantity != null && c.quantity !== ''
              ? Number(c.quantity)
              : null,
          unit_name: (c.unitName as string | undefined) ?? null,
          treat_stages: treatStages && treatStages.length > 0 ? treatStages : null,
          source_encounter_external_id: sourceEncounter,
          related_diagnosis_subject_id: relatedDx,
          review_window_days: reviewWindow,
        },
      },
    ];
  }

  /**
   * 根据 transaction.action 推 fact.kind 和 fact.status,以及 content.status 三值:
   *   kind         — actual / planned
   *   fact.status  — 版本流状态(active / fulfilled / cancelled / expired)
   *   contentStatus — content.status 字段(planned / in_progress / completed / cancelled / failed)
   */
  private deriveKindStatus(
    action: string,
    rowStatusLower: string,
  ): { kind: FactKind; status: FactStatus; contentStatus: string } {
    switch (action) {
      case Action.TREATMENT_PLANNED:
        return {
          kind: FactKind.PLANNED,
          status: FactStatus.ACTIVE,
          contentStatus: 'planned',
        };
      case Action.TREATMENT_STARTED:
        return {
          kind: FactKind.ACTUAL,
          status: FactStatus.ACTIVE,
          contentStatus: 'in_progress',
        };
      case Action.TREATMENT_COMPLETED:
        return {
          kind: FactKind.ACTUAL,
          status: FactStatus.FULFILLED,
          contentStatus: 'completed',
        };
      default:
        // 兜底:读 row.status
        if (rowStatusLower === 'cancelled') {
          return {
            kind: FactKind.ACTUAL,
            status: FactStatus.CANCELLED,
            contentStatus: 'cancelled',
          };
        }
        if (rowStatusLower === 'completed') {
          return {
            kind: FactKind.ACTUAL,
            status: FactStatus.FULFILLED,
            contentStatus: 'completed',
          };
        }
        return {
          kind: FactKind.PLANNED,
          status: FactStatus.ACTIVE,
          contentStatus: 'planned',
        };
    }
  }
}
