import { readFileSync } from 'node:fs';
import { join } from 'node:path';

/**
 * 摄入侧的 per-request 解析器**不许挂单例实例字段**。
 *
 * 踩过的坑(2026-07-23 → 07-29,测试服务器):
 *   ColdImportService 是 Nest 单例,却把 source_unit 解析器存成实例字段
 *   `private sourceUnitResolver`,每次摄入开头覆写、然后在长 async 循环里读。
 *   当时的注释写着「cold-import 按 host 串行,实例字段安全」—— 这个前提在 push
 *   (webhook,按请求并发)接入后就失效了:
 *
 *     friday   identity_namespace_field = tenant_id
 *     jvs-dw   identity_namespace_field = brand
 *
 *   两个 host 并发摄入时互相覆写 resolver,对方的行解析不出命名空间列 → source_unit=''
 *   → 患者索引 `(source_unit, external_id)` 未命中 → 建出空命名空间的**重复主档**。
 *   friday 首次 push 是 07-23 16:24:26,jvs-dw 第一个空品牌患者出现在 16:24:31(5 秒内),
 *   此前 39 万条 jvs-dw 患者零个空品牌。到 07-29 累计 5.1 万条,其中 99.95% 与真主档
 *   同 external_id —— 纯污染。
 *
 * 单测抓不到这类 bug(单跑任何一条路径都正确,只有并发交错才炸),所以在源码层设闸:
 * 解析器一律**局部构建 + 逐层传参**(tenantResolver 从一开始就是这么做的,照抄它)。
 */
describe('摄入解析器不得存为单例实例状态', () => {
  const file = join(__dirname, '../src/modules/sync/cold-import/cold-import.service.ts');
  const src = readFileSync(file, 'utf8');
  // 注释行不算(类头就写着这段事故说明,里面必然出现这些词)
  const code = src
    .split('\n')
    .filter((l) => !/^\s*(\/\/|\/\*|\*|\/\/\/)/.test(l))
    .join('\n');

  test('⭐ 不存在 `this.<x>Resolver = ...` 赋值(per-request 状态写进单例)', () => {
    const hits = code.match(/this\.\w*[Rr]esolver\s*=[^=]/g) ?? [];
    expect(hits).toEqual([]);
  });

  test('⭐ 不存在 `this.sourceUnitResolver` 读取(必须走入参)', () => {
    const hits = code.match(/this\.sourceUnitResolver/g) ?? [];
    expect(hits).toEqual([]);
  });

  test('每个读 source_unit 的 process* 方法都把 resolver 声明为入参', () => {
    const readers = [
      'processPatients',
      'processPatientRelations',
      'processPatientReturnVisits',
      'processSubject',
      'hydratePushLookupTables',
    ];
    for (const m of readers) {
      const sig = code.slice(code.indexOf(`private async ${m}(`));
      const params = sig.slice(0, sig.indexOf('): Promise<'));
      expect(`${m}: ${params.includes('sourceUnitResolver')}`).toBe(`${m}: true`);
    }
  });
});
