/**
 * Import Patient CLI —— 单患者精确摄入 + 重算画像/计划
 *
 * `runPullForPatient`(详情页"刷新"按钮)要求患者已存在 PG,对**尚未摄入**的新患者是死结。
 * 本 CLI 直接调 ColdImportService.importPatient(SQL 注入 patient_id+brand,upsert 患者),
 * 再顺手 persona.recompute + planEngine.recomputeForPatient —— 等价 runPullForPatient 的
 * 摄入→重算链路,但去掉"患者须预先存在"的前置,用于本地按单患者复现/调试。
 *
 * cursor 隔离:importPatient 用 resource='patient_refresh',不读/写增量游标,不扰 daily cron。
 *
 * Usage:
 *   pnpm import-patient -- --host=jvs-dw --pid=3275018 --brand=瑞泰
 *   pnpm import-patient -- --host=jvs-dw --pid=3275018 --brand=瑞泰 --no-recompute  # 只摄入
 */
import { NestFactory } from '@nestjs/core';
import { Logger } from '@nestjs/common';
import { AppModule } from '../app.module';
import { PrismaService } from '../prisma/prisma.service';
import { ColdImportService } from '../modules/sync/cold-import/cold-import.service';
import { PersonaService } from '../modules/persona/persona.service';
import { PlanEngineService } from '../modules/plan/engine/plan-engine.service';
import * as path from 'node:path';

interface Args {
  host: string;
  pid?: string; // DW patient_id(host 内 externalId)
  brand?: string; // 多 brand host(如 jvs-dw)的品牌名 = source_unit 消歧;单 brand host 可省
  recompute: boolean;
  help: boolean;
}

function parseArgs(argv: string[]): Args {
  const args: Args = { host: 'jvs-dw', recompute: true, help: false };
  for (const a of argv) {
    if (a === '--help' || a === '-h') args.help = true;
    else if (a === '--no-recompute') args.recompute = false;
    else if (a.startsWith('--host=')) args.host = a.slice('--host='.length);
    else if (a.startsWith('--pid=')) args.pid = a.slice('--pid='.length).trim();
    else if (a.startsWith('--brand=')) args.brand = a.slice('--brand='.length).trim();
  }
  return args;
}

function printHelp() {
  // eslint-disable-next-line no-console
  console.log(
    [
      '',
      'Import Patient CLI —— 单患者精确摄入 + 重算画像/计划',
      '',
      'Usage:',
      '  pnpm import-patient -- --host=<hostName> --pid=<externalId> [--brand=<brand>] [--no-recompute]',
      '',
      'Options:',
      '  --host=<name>     宿主名(默认 jvs-dw)',
      '  --pid=<id>        必填,DW patient_id(host 内 externalId)',
      '  --brand=<brand>   多 brand host 的品牌名(= source_unit 消歧);单 brand host 可省',
      '  --no-recompute    只摄入,不重算 persona/plan',
      '  --help, -h        显示本帮助',
      '',
      'Example:',
      '  pnpm import-patient -- --host=jvs-dw --pid=3275018 --brand=瑞泰',
      '',
    ].join('\n'),
  );
}

async function bootstrap() {
  const args = parseArgs(process.argv.slice(2));
  if (args.help || !args.pid) {
    printHelp();
    process.exit(args.help ? 0 : 1);
  }

  const logger = new Logger('import-patient');
  const app = await NestFactory.createApplicationContext(AppModule, {
    logger: ['log', 'warn', 'error'],
  });

  try {
    const prisma = app.get(PrismaService);
    const coldImport = app.get(ColdImportService);
    const persona = app.get(PersonaService);
    const planEngine = app.get(PlanEngineService);

    const host = await prisma.host.findUnique({ where: { name: args.host } });
    if (!host) throw new Error(`Host '${args.host}' not found(先 seed / admin API 建 host)`);

    const dataDir = path.join(
      process.env.PAC_INCREMENTAL_DATA_DIR ?? path.resolve(process.cwd(), 'data'),
      args.host,
    );

    // 1. 单患者摄入(SQL 注入 WHERE patient_id+brand;upsert 患者 + 衍生 fact)
    logger.log(
      `▶ 摄入 host=${args.host} pid=${args.pid}${args.brand ? ` brand=${args.brand}` : ''} dir=${dataDir}`,
    );
    const r = await coldImport.importPatient(dataDir, {
      patientExternalId: args.pid!,
      brand: args.brand ?? '',
      triggeredBy: `import-patient-cli:${args.pid}`,
    });
    logger.log(
      `  摄入 status=${r.status} patients=${r.totals.patientsUpserted} ` +
        `txns=${r.totals.transactionsWritten} dups=${r.totals.duplicates} ` +
        `facts(c=${r.totals.factsCreated} s=${r.totals.factsSuperseded} u=${r.totals.factsUnchanged}) ` +
        `failed=${r.totals.failed}`,
    );

    // 2. 定位刚 upsert 的患者(hostId + externalId;多 brand 时按 source_unit=brand 收窄)
    const patient = await prisma.patient.findFirst({
      where: {
        hostId: host.id,
        externalId: args.pid!,
        ...(args.brand ? { sourceUnit: args.brand } : {}),
      },
      orderBy: { updatedAt: 'desc' },
      select: { id: true, externalId: true, name: true, tenantId: true, sourceUnit: true },
    });
    if (!patient) {
      throw new Error(
        `摄入后未找到患者(hostId=${host.id} externalId=${args.pid}` +
          `${args.brand ? ` sourceUnit=${args.brand}` : ''})— 摄入是否成功?`,
      );
    }
    logger.log(
      `  患者:${patient.name ?? '(无名)'} id=${patient.id} tenant=${patient.tenantId} unit=${patient.sourceUnit}`,
    );

    if (!args.recompute) {
      logger.log('▶ --no-recompute:跳过 persona/plan 重算');
      return;
    }

    // 3. Persona 重算(force:跳过水位幂等,确保产新版本)
    logger.log('▶ 重算 Persona ...');
    const pr = await persona.recompute({
      patientId: patient.id,
      source: `import-patient-cli:${r.runId}`,
      force: true,
    });
    logger.log(`  Persona: ${JSON.stringify(pr)}`);

    // 4. Plan 重算(scenario SQL 带 patientId 收窄,只 upsert 该患者 plan)
    logger.log('▶ 重算 Plan ...');
    const r2 = await planEngine.recomputeForPatient({
      hostId: host.id,
      tenantId: patient.tenantId,
      patientId: patient.id,
    });
    logger.log(
      `  Plan: outcome=${r2.outcome} plansCreated=${r2.plansCreated} ` +
        `plansClosed=${r2.plansClosed} currentPlanId=${r2.currentPlanId ?? '(none)'}`,
    );

    logger.log('─────────────────────────────────────────');
    logger.log(`✓ DONE — patient=${patient.name ?? args.pid}(${patient.id})`);
    logger.log('─────────────────────────────────────────');
  } catch (err) {
    logger.error('import-patient failed:');
    logger.error(err instanceof Error ? err.stack ?? err.message : String(err));
    process.exitCode = 2;
  } finally {
    await app.close();
  }
}

bootstrap().catch((err) => {
  // eslint-disable-next-line no-console
  console.error(err);
  process.exit(3);
});
