/* 边界情况自动化测试（V1.1 健壮性修复回归）
 * 运行：node tests/edge_test.js
 * 覆盖：否定句检测 / 触发词扩充 / 游戏别名扩充 / 无意义输入兜底
 */
const fs = require('fs');
const vm = require('vm');
const path = require('path');
const store = {};
globalThis.localStorage = {
    getItem: k => (k in store ? store[k] : null),
    setItem: (k, v) => { store[k] = String(v); },
    removeItem: k => { delete store[k]; }
};
globalThis.document = { addEventListener: () => {}, querySelectorAll: () => [] };
vm.runInThisContext(fs.readFileSync(path.join(__dirname, '..', 'app.js'), 'utf8'));

let pass = 0, fail = 0;
function assert(name, cond, detail) {
    const ok = !!cond;
    console.log(`${ok ? '✅' : '❌'} ${name}${detail ? '  →  ' + detail : ''}`);
    ok ? pass++ : fail++;
}

console.log('════════ 否定句检测 ════════');
{
    const p = analyzeInput('我不是想找队友，只想看看装备攻略');
    assert('否定语境下不再误判为「组队」', p.intent !== '组队');
    assert('正确识别为「攻略」意图', p.intent === '攻略', `实际意图=${p.intent}`);
}
{
    const p = analyzeInput('原神不想打深渊了，就随便探索');
    assert('否定语境下不标记为进阶玩家', p.stage !== '进阶玩家', `实际阶段=${p.stage}`);
    assert('否定语境下的「深渊」不进入标签', !p.tags.includes('深渊'), `标签=[${p.tags.join(',')}]`);
}
{
    const p = analyzeInput('我不玩原神，想玩王者');
    assert('否定语境下的游戏名不被识别（原神）', p.game !== '原神');
    assert('肯定语境下的游戏名正常识别（王者荣耀）', p.game === '王者荣耀', `实际游戏=${p.game}`);
}

console.log('');
console.log('════════ 触发词扩充 ════════');
{
    const p = analyzeInput('逆水寒守游有人带吗');
    assert('「有人带吗」识别为组队意图', p.intent === '组队', `实际意图=${p.intent}`);
    assert('错别字不影响游戏识别（逆水寒）', p.game === '逆水寒手游');
}
{
    const p = analyzeInput('有人玩LOL吗');
    assert('「有人玩」识别为组队意图', p.intent === '组队', `实际意图=${p.intent}`);
    assert('英文名 LOL 识别为英雄联盟', p.game === '英雄联盟');
}

console.log('');
console.log('════════ 游戏别名扩充 ════════');
{
    const p = analyzeInput('最近在玩三角洲行动，想找人开黑');
    assert('三角洲行动被识别（V1.1 新增别名）', p.game === '三角洲行动', `实际游戏=${p.game}`);
    const m = matchChannels(p);
    assert('有频道后正常推荐「三角洲行动｜组队开黑」', m.status === 'ok' && m.best.channel.name === '三角洲行动｜组队开黑',
        `推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}
{
    const p = analyzeInput('CF 有人玩吗');
    assert('CF 别名识别为穿越火线', p.game === '穿越火线', `实际游戏=${p.game}`);
    const m = matchChannels(p);
    assert('推荐「穿越火线｜组队开黑」', m.status === 'ok' && m.best.channel.name === '穿越火线｜组队开黑',
        `推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}

console.log('');
console.log('════════ 赛事观赛（V1.2 新增意图与频道）════════');
{
    const p = analyzeInput('去哪里看go职业选手打比赛呀');
    assert('「go职业选手打比赛」识别游戏 CS:GO', p.game === 'CS:GO', `实际游戏=${p.game}`);
    assert('「打比赛」识别为赛事观赛意图', p.intent === '赛事观赛', `实际意图=${p.intent}`);
    const m = matchChannels(p);
    assert('推荐「CS:GO｜赛事观赛」频道', m.status === 'ok' && m.best.channel.name === 'CS:GO｜赛事观赛',
        `推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}
{
    const p = analyzeInput('CSGO 有哪些比赛直播能看');
    assert('CSGO 写法也能识别', p.game === 'CS:GO', `实际游戏=${p.game}`);
    assert('「比赛直播」识别为赛事观赛', p.intent === '赛事观赛', `实际意图=${p.intent}`);
    const m = matchChannels(p);
    assert('推荐 CS:GO 赛事频道', m.status === 'ok' && m.best.channel.name === 'CS:GO｜赛事观赛');
}
{
    const p = analyzeInput('英雄联盟 LPL 有直播看吗');
    assert('英雄联盟赛事需求 → 推荐赛事观赛频道', p.intent === '赛事观赛', `实际意图=${p.intent}`);
    const m = matchChannels(p);
    assert('推荐「英雄联盟｜赛事观赛」', m.status === 'ok' && m.best.channel.name === '英雄联盟｜赛事观赛',
        `推荐=${m.best ? m.best.channel.name : '无'}`);
}
{
    // LLM 提示词需包含新增意图，保证真实 AI 模式下模型输出被归一化接受
    const prompt = buildAnalysisPrompt('测试');
    assert('LLM 提示词已包含「赛事观赛」意图', prompt.includes('赛事观赛'));
}

console.log('');
console.log('════════ V1.3 频道扩充覆盖 ════════');
{
    const p = analyzeInput('和平精英有没有一起吃鸡的');
    const m = matchChannels(p);
    assert('吃鸡组队 → 推荐「和平精英｜组队吃鸡」', p.game === '和平精英' && m.status === 'ok' && m.best.channel.name === '和平精英｜组队吃鸡',
        `推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}
{
    const p = analyzeInput('原神这个月抽卡又氪了好多钱');
    const m = matchChannels(p);
    assert('氪金意图 → 推荐「原神｜抽卡氪金」', p.intent === '氪金/商业化' && m.status === 'ok' && m.best.channel.name === '原神｜抽卡氪金',
        `意图=${p.intent} 推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}
{
    const p = analyzeInput('光遇想找几个朋友一起玩');
    const m = matchChannels(p);
    assert('光遇社交 → 推荐光遇频道', p.game === '光遇' && m.status === 'ok' && m.best.channel.name.startsWith('光遇'),
        `推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}
{
    const p = analyzeInput('王者荣耀最近有什么活动福利');
    const m = matchChannels(p);
    assert('活动意图 → 推荐「王者荣耀｜活动福利」', p.intent === '活动讨论' && m.status === 'ok' && m.best.channel.name === '王者荣耀｜活动福利',
        `意图=${p.intent} 推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}
{
    // AI Discovery 演示场景保留：幻塔仍无频道（README 场景 C）
    const p = analyzeInput('最近在玩一个叫幻塔的游戏，想交流一下');
    const cov = checkChannelCoverage(p);
    assert('幻塔保持无频道状态（AI Discovery 演示场景）', cov.coverage === 'not_found' && cov.shouldExpand);
}

console.log('');
console.log('════════ 兜底与容错 ════════');
{
    const p = analyzeInput('......');
    const m = matchChannels(p);
    assert('无意义输入 → below_threshold（不强行推荐）', m.status === 'below_threshold');
}
{
    const p = analyzeInput('王者有带带我的吗');
    const m = matchChannels(p);
    assert('正常组队需求仍能推荐', m.status === 'ok' && p.intent === '组队', `推荐=${m.best ? m.best.channel.name : '无'} ${m.best ? m.best.total + '分' : ''}`);
}

console.log('');
console.log(`结果：${pass} 项通过 / ${fail} 项失败`);
if (fail > 0) process.exit(1);
