/**
 * Backfill Plan Labels CLI —— 回填 / 重算 `plan_reasons.potential_labels`。
 *
 * 初选矩阵靠这一列（改造后不再回查 `patient_facts`，958ms → 110ms）。
 *
 * 🔴 **上线后必须立刻跑一次**：迁移只是加了列，全表都是 NULL，而矩阵
 *   `unnest(potential_labels)` 遇到 NULL 什么都不出 ⇒ **这段时间矩阵会全是 0**。
 *   ⛔ 别指望夜间任务兜 —— 那要等到次日 03:30。
 *
 * ⚠️ **重算 plan 也能补齐，而且是安全的** —— ⛔ 别被"会释放客服"吓住（那是错的）：
 *   `auto_release` 只在「本轮该患者 0 命中（信号真没了）」或「最后到诊诊所变了」时触发，
 *   两者都是真实业务变化，不是重算这个动作造成的；这套逻辑本来就跟着增量同步每天在跑，
 *   该释放的早已释放，再跑一次不会多释放任何人。
 * ⇒ 日常维护**本来就靠原机制**：plan 生成收尾会调 `backfillMissing()`。
 *   这个 CLI 只解决一件事：**上线那一刻的空窗** —— 迁移后全表 NULL，
 *   等下一次增量同步（最长两小时）或夜间刷新（03:30）才自愈，
 *   而 CLI 把这个窗口压到约一分钟。⛔ 别拿它当日常手段。
 *
 * Usage:
 *   pnpm backfill-plan-labels              # 只补没算过的（上线后跑这个）
 *   pnpm backfill-plan-labels -- --all     # 连算过的一起重算（改了标签规则后跑）
 *   pnpm backfill-plan-labels -- --check   # 只报还差多少，不写库
 */
import { NestFactory } from '@nestjs/core';
import { Logger } from '@nestjs/common';
import { AppModule } from '../app.module';
import { PlanLabelService } from '../modules/plan/plan-label.service';

async function main(): Promise<void> {
  const log = new Logger('backfill-plan-labels');
  const argv = process.argv.slice(2);
  const all = argv.includes('--all');
  const checkOnly = argv.includes('--check');

  const app = await NestFactory.createApplicationContext(AppModule, {
    logger: ['error', 'warn', 'log'],
  });
  try {
    const svc = app.get(PlanLabelService);
    const before = await svc.countMissing();
    log.log(`还没算过的依据：${before} 条`);
    if (checkOnly) return;

    const t0 = Date.now();
    const written = all ? await svc.refreshAll() : await svc.backfillMissing();
    const after = await svc.countMissing();
    log.log(
      `${all ? '全量重算' : '回填'}完成：写入 ${written} 条，` +
        `耗时 ${((Date.now() - t0) / 1000).toFixed(1)}s，剩余未算 ${after} 条`,
    );
    // ⚠️ 回填完还有剩 = 有条写入路径没被覆盖到，值得当场查，⛔ 别等矩阵少人了才发现
    if (!all && after > 0) {
      log.error(`⚠️ 回填后仍有 ${after} 条没算过 —— 检查是否有新写入路径没接上补齐`);
      process.exitCode = 1;
    }
  } finally {
    await app.close();
  }
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});
