import {
  CLOSE_REASON_META,
  CloseReason,
  EXECUTION_OUTCOME_META,
  ExecutionOutcome,
  BREAKER_SUPPRESS_DAYS,
} from '@pac/types';

const DAY_MS = 86_400_000;

/**
 * 计算 execution 回写后的 snoozedUntil(召回冷静期 / 终态抑制窗)—— 纯函数,便于单测。
 *
 * 优先级(高 → 低):
 *   1. 熔断(breakerTripped):连续未接通累计达上限强制 abandoned → 固定短冷静期(30d),
 *      不是"拒绝",换天再试 / 后续可接换渠道。优先于 outcome 自身策略。
 *   2. 关闭机会覆写(closeReason → CLOSE_REASON_META.suppressDaysOverride):
 *      弱语义关闭(识别不准/已治/其他)统一 14d 短档 —— 等 DW 同步 + 排除闸接手,
 *      不套 outcome 的重抑制(如 marked_invalid 自带永久,识别不准是 PAC 的错,不罚患者)。
 *   3. outcome 固定抑制窗(EXECUTION_OUTCOME_META.suppressDays):
 *      明确拒绝/近期不考虑=90d、成功转化/客服放弃=60d、外院/无效=永久。
 *   4. keep 类无固定抑制窗但带了 scheduledNextAt(约定回访/考虑中等)→ 到该时间前 snooze。
 *   5. 其余(no_answer / sms_sent 等)→ null,不 snooze,维持现状很快再试。
 *
 * @returns snoozedUntil Date,或 null(不抑制)
 */
export function resolveSnoozedUntil(params: {
  outcome: string;
  breakerTripped: boolean;
  scheduledNextAt?: string | null;
  now: Date;
  closeReason?: string | null;
}): Date | null {
  const { outcome, breakerTripped, scheduledNextAt, now, closeReason } = params;

  if (breakerTripped) {
    return new Date(now.getTime() + BREAKER_SUPPRESS_DAYS * DAY_MS);
  }

  const closeOverride = closeReason
    ? CLOSE_REASON_META[closeReason as CloseReason]?.suppressDaysOverride
    : undefined;
  if (closeOverride != null) {
    return new Date(now.getTime() + closeOverride * DAY_MS);
  }

  const meta = EXECUTION_OUTCOME_META[outcome as ExecutionOutcome];
  if (meta?.suppressDays != null) {
    return new Date(now.getTime() + meta.suppressDays * DAY_MS);
  }

  if (scheduledNextAt) {
    return new Date(scheduledNextAt);
  }

  return null;
}
