import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import * as yaml from 'js-yaml';

/**
 * DW 滞后监控只管 **pull/DW 宿主**,push / 文件宿主必须跳过。
 *
 * 踩过的坑(2026-07-31,测试服务器):
 *   dw-lag-monitor 原本 `host.findMany()` 遍历**所有** host 算"增量游标多久没推进"。
 *   friday 是 push 宿主(数据由宿主主动推,sync_logs 的 cursor 按设计恒为 null),
 *   却因为历史上误跑过一次增量、留下一条 fetched=0 的 incremental_bundle 记录,
 *   游标就永久停在那一刻 → 每小时告警一次「DW 数据滞后 37 小时」,**永不自愈**。
 *   而同期 friday 正常 push 了 614 批 10.79 万行,数据流毫无问题。
 *
 *   这类噪音的真正危害不是烦人,是**把真告警淹掉** —— 一个永远在响的黄灯,
 *   看的人很快就不看了。
 *
 * 判据用 `sql_source` 有无,而不是 `auto_sync`:
 *   sql_source 与 files **二选一**(manifest.schema 原话),是"数据从哪来"的定义,
 *   即摄入模式本身;auto_sync 只是"要不要自动跑",可以临时关掉,跟模式是两回事。
 */
describe('DW 滞后监控的适用范围', () => {
  const dataRoot = join(__dirname, '../data');
  const manifestOf = (host: string) =>
    yaml.load(readFileSync(join(dataRoot, host, 'manifest.yaml'), 'utf8')) as Record<string, unknown>;

  describe('宿主摄入模式判据(sql_source 有无)', () => {
    test('jvs-dw 是 pull/DW 宿主 —— 有 sql_source,该被监控', () => {
      expect(!!manifestOf('jvs-dw').sql_source).toBe(true);
    });

    test('⭐ friday 是 push 宿主 —— 无 sql_source,必须跳过', () => {
      expect(!!manifestOf('friday').sql_source).toBe(false);
    });
  });

  describe('监控源码闸', () => {
    const src = readFileSync(
      join(__dirname, '../src/queues/dw-lag-monitor.service.ts'),
      'utf8',
    );
    const code = src
      .split('\n')
      .filter((l) => !/^\s*(\/\/|\/\*|\*)/.test(l))
      .join('\n');

    test('⭐ 遍历宿主时按 hasSqlSource 短路', () => {
      expect(code).toMatch(/if\s*\(\s*!\s*ops\.hasSqlSource\s*\)/);
      expect(code).toContain('continue;');
    });

    test('⭐ 短路发生在「无 cursor」告警之前 —— 否则 push 宿主换个姿势继续刷日志', () => {
      const guardAt = code.indexOf('ops.hasSqlSource');
      const noCursorWarnAt = code.indexOf('还没跑过增量');
      expect(guardAt).toBeGreaterThan(-1);
      expect(noCursorWarnAt).toBeGreaterThan(-1);
      expect(`guard 在前: ${guardAt < noCursorWarnAt}`).toBe('guard 在前: true');
    });
  });

  describe('getHostOpsConfig 暴露 hasSqlSource', () => {
    const src = readFileSync(
      join(__dirname, '../src/modules/sync/cold-import/cold-import.service.ts'),
      'utf8',
    );
    test('从 manifest.sql_source 派生,读不到 manifest 时保守取 false(不误报)', () => {
      expect(src).toContain('hasSqlSource: !!m.sql_source');
      // empty 兜底必须是 false —— 读不到 manifest 时宁可不报,也不要对着未知宿主刷告警
      expect(src).toMatch(/hasSqlSource:\s*false/);
    });
  });
});
