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

/**
 * AppointmentParser — `appointment_created` 等 appointment 类 action 的解析器
 *
 * **v2 设计**:产 1 个 `appointment_record`(原 appointment_plan)。
 *   - kind=planned:预约尚未发生(host status=scheduled)
 *   - kind=actual:预约已履约(host status=arrived)— 已到诊事件本身就是事实
 *
 * 状态机:
 *   scheduled → fact kind=planned, status=active
 *   arrived   → fact kind=actual,  status=fulfilled
 *   cancelled → fact kind=planned, status=cancelled
 *   no_show   → fact kind=planned, status=expired
 *
 * scenario #1 "已预约 crown" 负例查询通过 content->>'appointment_type' = 'crown_restoration'
 * + status='active' 实现(JSONB 路径)。
 */
@Injectable()
export class AppointmentParser implements Parser {
  readonly name = Action.APPOINTMENT_CREATED;
  private readonly logger = new Logger(AppointmentParser.name);

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

    const hostStatus = String(c.status ?? 'scheduled').toLowerCase();
    const factStatus = AppointmentParser.STATUS_MAP[hostStatus] ?? FactStatus.ACTIVE;
    // 到诊/接诊/结算 = 已发生事实(actual);其余(含已改约/取消/爽约)= planned
    const kind = AppointmentParser.ACTUAL_STATUSES.has(hostStatus)
      ? FactKind.ACTUAL
      : FactKind.PLANNED;

    const scheduledAt = c.scheduledAt ? new Date(c.scheduledAt as string) : null;
    const arrivedAt = c.arrivedAt ? new Date(c.arrivedAt as string) : null;
    const appointmentType = (c.appointmentType as string | undefined) ?? null;
    const doctorId = (c.doctorId as string | undefined) ?? null;

    return [
      {
        // subject_id 直接用 host appointment id(跨版本稳定)
        subjectId: `${FactType.APPOINTMENT_RECORD}:${externalId}`,
        kind,
        type: FactType.APPOINTMENT_RECORD,
        status: factStatus,
        clinicId: ctx.transaction.clinicId,
        // 时间语义(两列不同):
        //   scheduledAt ← appo_time(约定来诊"日期",Date,100% 有)
        //   arrivedAt   ← in_time(实际到诊"时刻",DateTime,仅到诊类填,且~25% 到诊缺失)
        // occurredAt(已发生):到诊时刻优先,缺失时兜底约定日(否则到诊无 in_time 会两时间皆 null 沉底)
        // plannedFor(约定):始终 = 约定日(预约固有属性,不因 kind 丢失)
        occurredAt: kind === FactKind.ACTUAL ? (arrivedAt ?? scheduledAt) : null,
        plannedFor: scheduledAt,
        validFrom: scheduledAt,
        title: appointmentType
          ? `预约 ${appointmentType}(${this.formatDate(scheduledAt)})`
          : `预约 ${this.formatDate(scheduledAt)}`,
        summary: arrivedAt
          ? `已到诊 ${this.formatDate(arrivedAt)}`
          : factStatus === FactStatus.CANCELLED
            ? '已取消'
            : factStatus === FactStatus.EXPIRED
              ? '应到未到(no_show)'
              : null,
        content: {
          appointment_external_id: externalId,
          scheduled_at: scheduledAt ? scheduledAt.toISOString() : null,
          arrived_at: arrivedAt ? arrivedAt.toISOString() : null,
          appointment_type: appointmentType,
          doctor_id: doctorId,
          complaint_category: (c.complaintCategory as string | undefined) ?? null,
          complaint_text: (c.complaintText as string | undefined) ?? null,
          duration_minutes:
            c.durationMinutes != null && c.durationMinutes !== ''
              ? Number(c.durationMinutes)
              : null,
          cancellation_reason:
            (c.cancellationReason as string | undefined) ?? null,
          staff_notes: (c.staffNotes as string | undefined) ?? null,
          // host 业务状态(8 态细分)— 跟 fact.status(PAC 版本流)互补
          status: AppointmentParser.HOST_STATUS_ENUM[hostStatus] ?? null,
        },
      },
    ];
  }

  // 已发生事实(actual)的 host 状态:到诊 / 接诊 / 结算 + walk-in 变更(已到店)
  private static readonly ACTUAL_STATUSES = new Set([
    'arrived',
    'in_treatment',
    'completed',
    'walk_in',
  ]);

  // host status(8 态)→ FactStatus(PAC 版本流状态)
  //   scheduled → active(唯一有效预约)
  //   rescheduled → superseded(已被改约取代的历史,不当有效预约,默认时间轴/召回不计)
  //   arrived/in_treatment/completed/walk_in → fulfilled(已发生)
  //   cancelled → cancelled / no_show → expired
  private static readonly STATUS_MAP: Record<string, FactStatus> = {
    scheduled: FactStatus.ACTIVE,
    rescheduled: FactStatus.SUPERSEDED,
    arrived: FactStatus.FULFILLED,
    in_treatment: FactStatus.FULFILLED,
    completed: FactStatus.FULFILLED,
    walk_in: FactStatus.FULFILLED,
    cancelled: FactStatus.CANCELLED,
    no_show: FactStatus.EXPIRED,
  };

  // host_status → content.status(8 态闭集,zod 强校验);未识别 → null
  private static readonly HOST_STATUS_ENUM: Record<string, string | null> = {
    scheduled: 'scheduled',
    rescheduled: 'rescheduled',
    arrived: 'arrived',
    in_treatment: 'in_treatment',
    completed: 'completed',
    walk_in: 'walk_in',
    cancelled: 'cancelled',
    no_show: 'no_show',
  };

  private formatDate(d: Date | null): string {
    return d ? d.toISOString().slice(0, 10) : '-';
  }
}
