import { benefitBlock } from '../src/modules/ai/calls/draft-plan-script/shared/fact-block';

/**
 * 福利进话术的护栏回归。
 *
 * 🔴 这是整个分配功能里**唯一一条「做错了会对患者做出虚假承诺」**的路:
 * 模型拿到一句「8 月种植体检免费」,极容易顺手补成「限本月前 20 名」「老客户专享」
 * 「可叠加其他折扣」—— 患者按它上门,前台兑现不了。
 *
 * 护栏本身是提示词,单测拦不住 LLM 的自由发挥;这里锁的是**护栏必须在场**、
 * 以及**没配福利时整段不出现**(留个空钩子模型就会自己编一个)。
 */

describe('福利进话术 —— 护栏必须在场', () => {
  const block = benefitBlock({ text: '8 月种植体检免费' });

  test('⭐ 福利原文原样出现,且标明「只有这一句是真的」', () => {
    expect(block).toContain('8 月种植体检免费');
    expect(block).toContain('只有这一句是真的');
  });

  test('⭐⭐ 四条禁令一条都不能少 —— 少哪条模型就会在哪条上自由发挥', () => {
    // 每一条都对应一种真实会发生的编造:
    expect(block).toContain('不得追加任何条件、期限、名额、人群限定'); // "限本月前20名"
    expect(block).toContain('不得改写金额/折扣/项目'); // 把"免费"说成"5折"或反之
    expect(block).toContain('不得夸大'); // "史上最低"
    expect(block).toContain('原文没写的一律不说'); // 兜底
  });

  test('⭐ 追问细节要有出口,否则模型会现编一个条款', () => {
    expect(block).toContain('以到院时前台说明为准');
  });

  test('标成硬约束,与「高龄不主推种植」同级 —— 不是可选修饰', () => {
    expect(block).toContain('本次福利(硬约束)');
  });
});

describe('福利进话术 —— 没配就整段不生成', () => {
  test('⭐⭐ 不留空钩子:留了模型会自己编一个福利出来', () => {
    for (const empty of [undefined, null, { text: '' }, { text: '   ' }]) {
      expect(benefitBlock(empty)).toBe('');
    }
  });
});

describe('两档共用同一份护栏', () => {
  test('⭐ 稳健档与标准/深度档用的是**同一个函数** —— 各写一份必然漂', () => {
    // 这条断言看着废,实际拦的是"有人为了图省事在 stable/prompt 里再抄一份"。
    // 抄了之后改护栏只会改到一处,而"哪一档漏了哪条禁令"要等客服念出去才发现。
    const stableSrc = require('node:fs').readFileSync(
      require('node:path').join(__dirname, '../src/modules/ai/calls/draft-plan-script/tiers/stable/prompt.ts'),
      'utf-8',
    ) as string;
    expect(stableSrc).toContain('benefitBlock');
    expect(stableSrc).not.toContain('本次福利(硬约束)'); // ⛔ 不许内联再写一份
  });
});
