import {
  DENTURE_FIRST_AGE,
  recommendedCategoriesForAge,
  treatmentCategoryNameZhFor,
  treatmentCategoryNameZhForTeeth,
  lookupDxTreatment,
} from '@pac/types';

/**
 * 建议治疗的年龄适配回归(源头层:诊断 → 建议治疗的**排序**)。
 *
 * 背景(2026-07 业务反馈):90 岁 / 78 岁患者的缺牙召回,界面目标一律「目标 · 种植」——
 * 因为 UI 取 expectedCategories[0],而 K08 的 categories 首项恒为 implant。
 *
 * 业务方口径(对齐后):**70-80 不是种植禁忌**,能否种植看骨量骨质 / 全身状况 / 患者意愿,
 * 由医生评估。PAC 该做的是**调整推荐顺序**(活动义齿在前、种植并行),不是禁推种植。
 *
 * 设计边界(三条红线,下面各有用例锁住):
 *   1. 只改顺序,不增删类目 —— 返回集合恒等于入参集合(种植不能被抹掉)
 *   2. 不碰排除闸(DiagnosisTreatmentMap[].categories 仍是完整候选集)
 *   3. 不碰"要不要召回"(缺牙影响咀嚼营养,高龄同样该管)
 */

describe('recommendedCategoriesForAge — 源头:建议治疗排序', () => {
  const K08 = lookupDxTreatment('K08')!.categories; // ['implant','prosthodontic']

  test('⭐ >70 岁缺牙 → 活动义齿在前,种植并行保留(不是二选一)', () => {
    const r = recommendedCategoriesForAge(K08, 90);
    expect(r[0]).toBe('prosthodontic'); // 义齿在前
    expect(r).toContain('implant'); // ⭐ 种植仍在 —— 高龄非禁忌,只是排后面
    expect(r).toHaveLength(K08.length); // 只挪位,不增删
  });

  test('边界:恰好 70 岁不变(口径是「大于 70」)', () => {
    expect(recommendedCategoriesForAge(K08, DENTURE_FIRST_AGE)[0]).toBe('implant');
    expect(recommendedCategoriesForAge(K08, DENTURE_FIRST_AGE + 1)[0]).toBe('prosthodontic');
  });

  test('未达线 / 无年龄 → 原顺序', () => {
    expect(recommendedCategoriesForAge(K08, 35)[0]).toBe('implant');
    expect(recommendedCategoriesForAge(K08, null)[0]).toBe('implant');
    expect(recommendedCategoriesForAge(K08, undefined)[0]).toBe('implant');
  });

  test('只在「种植 + 义齿」并存时排序;单一类目不受年龄影响', () => {
    // 龋齿 90 岁也还是补牙,不该被改写
    expect(recommendedCategoriesForAge(['restorative'], 90)).toEqual(['restorative']);
    expect(recommendedCategoriesForAge(['endodontic'], 92)).toEqual(['endodontic']);
    expect(recommendedCategoriesForAge(['periodontic'], 88)).toEqual(['periodontic']);
  });

  test('⭐ 红线①:永不增删类目 —— 任何年龄下集合恒等', () => {
    for (const age of [null, 30, 70, 71, 90, 120]) {
      const r = recommendedCategoriesForAge(K08, age);
      expect([...r].sort()).toEqual([...K08].sort());
    }
  });

  test('空候选 → 空', () => {
    expect(recommendedCategoriesForAge([], 90)).toEqual([]);
  });
});

describe('treatmentCategoryNameZhFor — 展示标签', () => {
  test('⭐ >70 岁的 prosthodontic → 「活动义齿」(而非泛化"修复 / 冠桥")', () => {
    // 冠桥需邻牙条件,高龄同样受限;说清是活动义齿更贴合实际推荐
    expect(treatmentCategoryNameZhFor('prosthodontic', null, 90)).toBe('活动义齿');
  });

  test('未达线 → 原标签', () => {
    expect(treatmentCategoryNameZhFor('prosthodontic', null, 40)).toBe(
      treatmentCategoryNameZhForTeeth('prosthodontic', null),
    );
  });

  test('高龄的种植标签不变(仍叫"种植",只是排在义齿后)', () => {
    expect(treatmentCategoryNameZhFor('implant', null, 90)).toBe(
      treatmentCategoryNameZhForTeeth('implant', null),
    );
  });

  test('乳牙口径不被破坏(既有行为保留)', () => {
    expect(treatmentCategoryNameZhFor('restorative', '51;52', 8)).toBe('充填');
    expect(treatmentCategoryNameZhFor('restorative', '51;52', null)).toBe('充填');
  });
});

describe('组合:高龄缺牙的完整展示串', () => {
  test('⭐ 90 岁 → 「活动义齿 / 种植」(并行,义齿在前)', () => {
    const K08 = lookupDxTreatment('K08')!.categories;
    const s = recommendedCategoriesForAge(K08, 90)
      .map((c) => treatmentCategoryNameZhFor(c, null, 90))
      .join(' / ');
    expect(s).toBe('活动义齿 / 种植');
  });

  test('40 岁 → 原样(种植在前)', () => {
    const K08 = lookupDxTreatment('K08')!.categories;
    const s = recommendedCategoriesForAge(K08, 40)
      .map((c) => treatmentCategoryNameZhFor(c, null, 40))
      .join(' / ');
    expect(s.startsWith('种植')).toBe(true);
  });
});

describe('红线②:排除闸不受年龄影响', () => {
  test('K08 的 categories 仍是完整候选集(做过任一都算已解决)', () => {
    // 年龄适配只改"建议",绝不能收窄这个集合 ——
    // 否则高龄患者做过种植反而排除不掉(会重复召回)。
    const cats = lookupDxTreatment('K08')!.categories;
    expect(cats).toContain('implant');
    expect(cats).toContain('prosthodontic');
  });
});
