import { ClickHouseSourceService } from '../src/modules/sync/cold-import/clickhouse-source.service';

/**
 * 增量空转探针回归。
 *
 * 探针职责:增量成功但拉 0 行时,反查 DW「比游标新的行数」,分辨
 *   「DW 真没新数据(静默)」vs「游标条件失效在空转(CRITICAL 告警)」。
 *
 * 2026-07-25 生产误报排查暴露两个 bug:
 *   ① 探针反查只拼游标、**不带业务过滤**,把"游标之后但会被业务条件过滤掉"的行也数进去
 *      —— 退费单(settlement_status≠1 / is_refund=1)首当其冲。实测 settlement 正/退表各 5788
 *      完全相等,正是这批全为退费单的铁证 → 真实拉取正确地不拉,探针却告警。
 *   ② 探针在 **失败轮** 上也跑(条件只看 tx+dup=0,没看 status),把瞬时网络失败
 *      ("unexpected end of file")误诊成"游标空转"。② 在 cold-import.service 的调用点修
 *      (加 status===success 守卫),① 在此处的 extractBusinessFilters 修。
 *
 * 本文件锁 ①:探针拼的 WHERE 必须与真实增量拉取同一套业务过滤。
 */

// extractBusinessFilters 是纯字符串逻辑、无构造依赖,直接实例化用 bracket 访问。
const svc = new ClickHouseSourceService();
const extract = (sql: string): string[] =>
  (svc as unknown as { extractBusinessFilters(s: string): string[] }).extractBusinessFilters(sql);

describe('extractBusinessFilters — 探针复用真实拉取的业务过滤', () => {
  test('⭐ 结算正表:保留 is_refund / settlement_status,去掉 cohort', () => {
    const sql = `
      SELECT id, patient_id, settlement_money
      FROM dw_group.fact_settlement_out
      WHERE (is_refund IS NULL OR is_refund = 0)
        AND settlement_status = 1
        AND (patient_id, brand) IN (
          SELECT patient_id, brand FROM dw_group.fact_client_out WHERE last_visit_time IS NOT NULL
        )`;
    const f = extract(sql);
    expect(f).toContain('settlement_status = 1');
    expect(f.some((c) => /is_refund/.test(c))).toBe(true);
    // cohort 子查询必须被剔除(否则探针 SQL 里嵌一坨子查询,且语义错)
    expect(f.some((c) => /\(patient_id\s*,\s*brand\)\s+IN/i.test(c))).toBe(false);
  });

  test('⭐ 结算退费表:保留退费判定,去掉 cohort', () => {
    const sql = `
      SELECT id, patient_id
      FROM dw_group.fact_settlement_out
      WHERE (is_refund = 1 OR settlement_status = 4)
        AND (patient_id, brand) IN (SELECT patient_id, brand FROM dw_group.fact_client_out WHERE last_visit_time IS NOT NULL)`;
    const f = extract(sql);
    expect(f.some((c) => /is_refund = 1 OR settlement_status = 4/.test(c))).toBe(true);
    expect(f.some((c) => /\(patient_id\s*,\s*brand\)\s+IN/i.test(c))).toBe(false);
  });

  test('结算方式表:保留 settlement_status=1', () => {
    const sql = `SELECT * FROM dw_group.fact_settlement_mode_out WHERE settlement_status = '1'
      AND (patient_id, brand) IN (SELECT patient_id, brand FROM dw_group.fact_client_out WHERE last_visit_time IS NOT NULL)`;
    expect(extract(sql)).toContain("settlement_status = '1'");
  });

  test('主档表:last_visit_time IS NOT NULL 被剔除(增量按 cursor 拉,该条冗余)', () => {
    const sql = `SELECT * FROM dw_group.fact_client_out WHERE last_visit_time IS NOT NULL`;
    expect(extract(sql)).toEqual([]);
  });

  test('预约/病历:整段 WHERE 只有 cohort → 探针无附加过滤(与真实拉取一致)', () => {
    const sql = `SELECT * FROM dw_group.fact_appointment_out
      WHERE (patient_id, brand) IN (SELECT patient_id, brand FROM dw_group.fact_client_out WHERE last_visit_time IS NOT NULL)`;
    expect(extract(sql)).toEqual([]);
  });

  test('括号内的 OR/AND 不被 AND 拆开(退费表 (a OR b) 整体保留)', () => {
    const sql = `SELECT * FROM t WHERE (is_refund = 1 OR settlement_status = 4) AND settlement_status = 1`;
    const f = extract(sql);
    expect(f).toContain('(is_refund = 1 OR settlement_status = 4)');
    expect(f).toContain('settlement_status = 1');
    expect(f).toHaveLength(2);
  });
});
