/**
 * Scenario Selector Verifier — ⚠️ DEPRECATED(v2.1)
 *
 * 本 CLI 基于 v2.0 嵌套 encounter_record.content.treatments[] 设计;
 * v2.1 已拆出独立 diagnosis_record / treatment_record / recommendation_record,SQL 已过时。
 *
 * 当前 PAC v2.1 一期只跑 treatment_initiation_recall(潜在治疗新链召回);
 * aftercare 系列 4 子场景留后续。
 *
 * **不要再跑本 CLI**(SQL 永远命中 0 行);文件保留作为 v2.0 基线参考。
 * 真实验证用 plan-engine 直接跑 initiation scenario(待 W3 加 CLI 入口)。
 */
import { PrismaClient } from '@prisma/client';

const p = new PrismaClient();

// 锚点跟 gen.py 一致
const TODAY = new Date('2026-05-14T14:00:00+08:00');
const days = (n: number) => new Date(TODAY.getTime() - n * 86400_000);

async function scenario1_endoNoCrown(): Promise<string[]> {
  // 时间窗 30 天 - 18 个月
  // 命中:encounter_record.content.treatments[] 含 endodontic+expected_next_step=crown_restoration,
  //       且无后续 crown treatment,无未来 crown 预约。
  const rows: Array<{ external_id: string }> = await p.$queryRaw`
    SELECT DISTINCT p.external_id
    FROM patients p
    JOIN patient_profiles pp ON pp.patient_id = p.id
    JOIN patient_facts pf_endo ON pf_endo.patient_id = p.id
    WHERE pf_endo.status = 'active'
      AND pf_endo.type = 'encounter_record'
      AND pf_endo.kind = 'actual'
      AND pf_endo.occurred_at BETWEEN ${days(540)} AND ${days(30)}
      AND EXISTS (
        SELECT 1 FROM jsonb_array_elements(pf_endo.content->'treatments') t
        WHERE t->>'treatment_category' = 'endodontic'
          AND t->>'status' = 'completed'
          AND t->>'expected_next_step' = 'crown_restoration'
      )
      AND p.active = true
      AND pp.do_not_contact = false
      AND pp.deceased = false
      AND p.phone IS NOT NULL AND p.phone <> ''
      -- 无后续 crown 治疗(treatment_subtype = crown 在某次 encounter 内)
      AND NOT EXISTS (
        SELECT 1 FROM patient_facts pf_crown
        WHERE pf_crown.patient_id = p.id
          AND pf_crown.status = 'active'
          AND pf_crown.type = 'encounter_record'
          AND pf_crown.occurred_at > pf_endo.occurred_at
          AND EXISTS (
            SELECT 1 FROM jsonb_array_elements(pf_crown.content->'treatments') t2
            WHERE t2->>'treatment_subtype' = 'crown'
          )
      )
      -- 无未来 crown_restoration 预约(appointment_record kind=planned active)
      AND NOT EXISTS (
        SELECT 1 FROM patient_facts pf_apt
        WHERE pf_apt.patient_id = p.id
          AND pf_apt.status = 'active'
          AND pf_apt.type = 'appointment_record'
          AND pf_apt.kind = 'planned'
          AND pf_apt.content->>'appointment_type' = 'crown_restoration'
      )
    ORDER BY p.external_id
  `;
  return rows.map((r) => r.external_id);
}

async function scenario2_orthoRetention(): Promise<string[]> {
  // 时间窗 6-24 个月,encounter 内有正畸治疗 completed,近 6 月无 ortho 相关活动
  const rows: Array<{ external_id: string }> = await p.$queryRaw`
    SELECT DISTINCT p.external_id
    FROM patients p
    JOIN patient_profiles pp ON pp.patient_id = p.id
    JOIN patient_facts pf_ortho ON pf_ortho.patient_id = p.id
    WHERE pf_ortho.status = 'active'
      AND pf_ortho.type = 'encounter_record'
      AND pf_ortho.kind = 'actual'
      AND pf_ortho.occurred_at BETWEEN ${days(720)} AND ${days(180)}
      AND EXISTS (
        SELECT 1 FROM jsonb_array_elements(pf_ortho.content->'treatments') t
        WHERE t->>'treatment_category' = 'orthodontic'
          AND t->>'status' = 'completed'
      )
      AND p.active = true
      AND pp.do_not_contact = false AND pp.deceased = false
      AND p.phone IS NOT NULL AND p.phone <> ''
      AND NOT EXISTS (
        SELECT 1 FROM patient_facts pf_recent
        WHERE pf_recent.patient_id = p.id
          AND pf_recent.occurred_at >= ${days(180)}
          AND (
            pf_recent.content->>'related_treatment_category' = 'orthodontic'
            OR EXISTS (
              SELECT 1 FROM jsonb_array_elements(pf_recent.content->'treatments') t2
              WHERE t2->>'treatment_category' = 'orthodontic'
            )
          )
      )
    ORDER BY p.external_id
  `;
  return rows.map((r) => r.external_id);
}

async function scenario3_implantAnnual(): Promise<string[]> {
  // 时间窗 330-540 天,encounter 内有 implant 治疗 completed,自该次 encounter 后 >300 天无 review encounter
  const rows: Array<{ external_id: string }> = await p.$queryRaw`
    SELECT DISTINCT p.external_id
    FROM patients p
    JOIN patient_profiles pp ON pp.patient_id = p.id
    JOIN patient_facts pf_impl ON pf_impl.patient_id = p.id
    WHERE pf_impl.status = 'active'
      AND pf_impl.type = 'encounter_record'
      AND pf_impl.kind = 'actual'
      AND pf_impl.occurred_at BETWEEN ${days(540)} AND ${days(330)}
      AND EXISTS (
        SELECT 1 FROM jsonb_array_elements(pf_impl.content->'treatments') t
        WHERE t->>'treatment_category' = 'implant'
          AND t->>'status' = 'completed'
      )
      AND p.active = true
      AND pp.do_not_contact = false AND pp.deceased = false
      AND p.phone IS NOT NULL AND p.phone <> ''
      AND NOT EXISTS (
        SELECT 1 FROM patient_facts pf_review
        WHERE pf_review.patient_id = p.id
          AND pf_review.type = 'encounter_record'
          AND pf_review.content->>'related_treatment_subject_id' = pf_impl.subject_id
          AND pf_review.occurred_at > pf_impl.occurred_at + INTERVAL '300 days'
      )
    ORDER BY p.external_id
  `;
  return rows.map((r) => r.external_id);
}

async function scenario4_perioMaintenance(): Promise<string[]> {
  // 时间窗 150-360 天,encounter 内有 periodontic 治疗 completed,后续无更新的 periodontic
  const rows: Array<{ external_id: string }> = await p.$queryRaw`
    SELECT DISTINCT p.external_id
    FROM patients p
    JOIN patient_profiles pp ON pp.patient_id = p.id
    JOIN patient_facts pf_perio ON pf_perio.patient_id = p.id
    WHERE pf_perio.status = 'active'
      AND pf_perio.type = 'encounter_record'
      AND pf_perio.kind = 'actual'
      AND pf_perio.occurred_at BETWEEN ${days(360)} AND ${days(150)}
      AND EXISTS (
        SELECT 1 FROM jsonb_array_elements(pf_perio.content->'treatments') t
        WHERE t->>'treatment_category' = 'periodontic'
          AND t->>'status' = 'completed'
      )
      AND p.active = true
      AND pp.do_not_contact = false AND pp.deceased = false
      AND p.phone IS NOT NULL AND p.phone <> ''
      AND NOT EXISTS (
        SELECT 1 FROM patient_facts pf_recent_perio
        WHERE pf_recent_perio.patient_id = p.id
          AND pf_recent_perio.type = 'encounter_record'
          AND pf_recent_perio.occurred_at > pf_perio.occurred_at
          AND EXISTS (
            SELECT 1 FROM jsonb_array_elements(pf_recent_perio.content->'treatments') t2
            WHERE t2->>'treatment_category' = 'periodontic'
          )
      )
    ORDER BY p.external_id
  `;
  return rows.map((r) => r.external_id);
}

function assertEqual(label: string, got: string[], expected: string[]): boolean {
  const sortedGot = [...got].sort();
  const sortedExp = [...expected].sort();
  const ok =
    sortedGot.length === sortedExp.length &&
    sortedGot.every((v, i) => v === sortedExp[i]);
  const tag = ok ? '✅' : '❌';
  console.log(`${tag} ${label}`);
  console.log(`   expected (${sortedExp.length}): ${sortedExp.join(', ')}`);
  console.log(`   got      (${sortedGot.length}): ${sortedGot.join(', ')}`);
  if (!ok) {
    const missing = sortedExp.filter((x) => !sortedGot.includes(x));
    const extra = sortedGot.filter((x) => !sortedExp.includes(x));
    if (missing.length) console.log(`   missing: ${missing.join(', ')}`);
    if (extra.length) console.log(`   extra:   ${extra.join(', ')}`);
  }
  return ok;
}

(async () => {
  let allOk = true;

  console.log(`\nScenario hit verification — TODAY = ${TODAY.toISOString().slice(0, 10)}`);
  console.log('────────────────────────────────────────────────────────');

  const s1 = await scenario1_endoNoCrown();
  allOk = assertEqual(
    '#1 根管未戴冠',
    s1,
    ['P001', 'P002'],
  ) && allOk;

  const s2 = await scenario2_orthoRetention();
  allOk = assertEqual(
    '#2 正畸保持器期',
    s2,
    ['P003', 'P004'],
  ) && allOk;

  const s3 = await scenario3_implantAnnual();
  allOk = assertEqual(
    '#3 种植年度复查',
    s3,
    ['P005', 'P006'],
  ) && allOk;

  const s4 = await scenario4_perioMaintenance();
  allOk = assertEqual(
    '#4 牙周维护期',
    s4,
    ['P007', 'P008'],
  ) && allOk;

  console.log('────────────────────────────────────────────────────────');
  console.log(allOk ? '\n🎉 ALL SCENARIO SELECTORS PASS' : '\n⚠️  SOME SCENARIOS FAILED');

  await p.$disconnect();
  process.exit(allOk ? 0 : 1);
})();
