/**
 * BullMQ 队列名常量 — 单一真理源。
 *
 * 命名规则:`<domain>-<verb>`,小写连字符。
 *   - persona-recompute:   重算单 patient persona 版本(jobName = patientId 串行)
 *   - plan-recompute:      重算单 patient followup plans(jobName = patientId 串行)
 *   - plan-asset-generate: 生成 PlanScript + PlanSummary(jobName = planId 串行)
 *
 * 三个队列各自 jobName 锁 per-queue,跨队列允许并发(数据依赖天然)。
 * 详见 apps/pac-docs/content/docs/architecture/three-layer-model.mdx "事件驱动主路径"。
 */
export const QueueName = {
  PERSONA_RECOMPUTE: 'persona-recompute',
  PLAN_RECOMPUTE: 'plan-recompute',
  PLAN_ASSET_GENERATE: 'plan-asset-generate',
  /// 执行结果回执投递(PAC → 宿主 callbackUrl,HMAC 签名 + 退避重试;jobName = executionId)
  EXECUTION_CALLBACK: 'execution-callback',
  /// 网页上传压缩包触发的整包 cold-import(长任务,jobName = jobId;concurrency=1 串行)
  COLD_IMPORT: 'cold-import',
} as const;
export type QueueName = (typeof QueueName)[keyof typeof QueueName];

/**
 * 各队列默认重试 / 退避策略。
 */
export const QueueDefaults = {
  [QueueName.PERSONA_RECOMPUTE]: {
    attempts: 3,
    backoff: { type: 'exponential', delay: 1_000 }, // 1s / 5s / 25s
    removeOnComplete: { count: 200 },
    removeOnFail: { count: 1_000 },
  },
  [QueueName.PLAN_RECOMPUTE]: {
    attempts: 3,
    backoff: { type: 'exponential', delay: 1_000 },
    removeOnComplete: { count: 200 },
    removeOnFail: { count: 1_000 },
  },
  [QueueName.PLAN_ASSET_GENERATE]: {
    /**
     * AI 调用贵,只重试 2 次;还失败则 fallback 到模板兜底(processor 内部处理)
     */
    attempts: 2,
    backoff: { type: 'exponential', delay: 5_000 }, // 5s / 25s
    removeOnComplete: { count: 200 },
    removeOnFail: { count: 1_000 },
  },
  [QueueName.EXECUTION_CALLBACK]: {
    /**
     * 网络投递:多试几次熬过宿主短暂抖动。6 次指数退避 ≈ 2s/4s/8s/16s/32s(约 1 分钟);
     * 耗尽仍失败 → 留在 failed 集(Bull Board 可见 = 死信),removeOnFail 保留大量供排查。
     */
    attempts: 6,
    backoff: { type: 'exponential', delay: 2_000 },
    removeOnComplete: { count: 500 },
    removeOnFail: { count: 5_000 },
  },
  [QueueName.COLD_IMPORT]: {
    /**
     * 整包导入是几十分钟的重任务,且 importDirectory 有 partial UNIQUE(host_id) WHERE status='running'
     * 并发锁(重试会撞锁)→ **不自动重试**(attempts:1),失败就留 failed 供人工排查。
     * 完成的 job 保留久一点(前端靠 jobId 轮询进度,别在读到前被清)。
     */
    attempts: 1,
    removeOnComplete: { age: 24 * 3_600, count: 100 },
    removeOnFail: { count: 1_000 },
  },
} as const;
