import { parsePatientsFile, splitPatientTokens } from "../src/cli/reparse-patients-file";

/**
 * `--patients-file` 解析回归 —— 这个参数决定 reparse 跑 2 分钟还是 4.5 小时。
 *
 * 背景(2026-07-27 测试服实测):全量 reparse = 260,434 患者 / 87 批 / ~4.5 小时,
 * 而时间几乎全花在"证明没变"上 —— 真正会变的:
 *   · 改 clinical-signals 字典  → 约 4 万患者(15%)
 *   · 改 planned「二期」归类规则 → 1,017 患者(0.4%)→ 收窄后 2 分钟跑完
 *
 * ⭐ 最要紧的一条不在本文件而在 CLI:解析结果为空必须**报错退出**。
 *   服务侧 `if (!scopePatientIds?.length)` 把空数组当"不限定" →
 *   一个路径写错的收窄命令会静默变成 4.5 小时全量,且日志上看不出异常。
 *   这里先把"什么算解析出来了"钉死。
 */
describe('parsePatientsFile — 宽容但不猜', () => {
  it('一行一个,去空行去首尾空格', () => {
    expect(parsePatientsFile('a\n  b  \n\n\nc\n')).toEqual(['a', 'b', 'c']);
  });

  it('# 注释整行忽略', () => {
    expect(parsePatientsFile('# 受影响患者\na\n#b\nc')).toEqual(['a', 'c']);
  });

  it('⭐ 行尾注释也剥掉 —— 圈人清单常顺手标注是谁', () => {
    expect(parsePatientsFile('a  # 张三 缺牙\nb\t# 李四')).toEqual(['a', 'b']);
  });

  it('去重(psql dump 混着几次查询很常见)', () => {
    expect(parsePatientsFile('a\nb\na\nb\nc')).toEqual(['a', 'b', 'c']);
  });

  it('剥行尾逗号/分号 —— 从 SQL IN 列表直接拷出来的形态', () => {
    expect(parsePatientsFile('a,\nb;\nc')).toEqual(['a', 'b', 'c']);
  });

  it('CRLF(Windows / 某些导出工具)', () => {
    expect(parsePatientsFile('a\r\nb\r\n')).toEqual(['a', 'b']);
  });

  it('全是空白/注释 → 空数组(CLI 据此报错,不退化成全量)', () => {
    expect(parsePatientsFile('\n\n  \n# 只有注释\n')).toEqual([]);
    expect(parsePatientsFile('')).toEqual([]);
  });

  it('认不出的原样保留 —— 不做猜测性纠错,交给库里查、查不到再报', () => {
    expect(parsePatientsFile('BJ0A094257\n不是id\n123')).toEqual(['BJ0A094257', '不是id', '123']);
  });
});

describe('splitPatientTokens — uuid 走 patient.id,其余当 externalId', () => {
  const UUID = 'f5ac71d5-c8b8-4f39-8090-ec3478810aa0'; // 生产真实患者 陈芃霖

  it('标准 uuid 归 ids', () => {
    expect(splitPatientTokens([UUID])).toEqual({ ids: [UUID], externalIds: [] });
  });

  it('大写 uuid 也认(psql / Excel 可能改大小写)', () => {
    const up = UUID.toUpperCase();
    expect(splitPatientTokens([up]).ids).toEqual([up]);
  });

  it('病历号 / 数字 externalId 归 externalIds', () => {
    expect(splitPatientTokens(['BJ0A094257', '1551051'])).toEqual({
      ids: [],
      externalIds: ['BJ0A094257', '1551051'],
    });
  });

  it('⭐ 混写 —— 手上有什么用什么,两类都要能收', () => {
    const r = splitPatientTokens([UUID, 'BJ0A094257', 'f5ac71d5-c8b8-4f39-8090-ec3478810aa1']);
    expect(r.ids).toHaveLength(2);
    expect(r.externalIds).toEqual(['BJ0A094257']);
  });

  it('长得像但不是 uuid(缺段/多段)→ 当 externalId,不冒充 id', () => {
    expect(splitPatientTokens(['f5ac71d5-c8b8-4f39-8090']).externalIds).toHaveLength(1);
    expect(splitPatientTokens(['f5ac71d5c8b84f398090ec3478810aa0']).externalIds).toHaveLength(1);
  });
});
