/**
 * 质量校验 & 改写优化节点 - 单元测试
 * 测试消息构建、响应解析等纯函数逻辑
 */
import { strict as assert } from 'assert';

// ====== 模拟数据 ======

// 模拟 quality-check 响应
const mockQualityPassResponse = JSON.stringify({
  overallScore: 92,
  overallAssessment: "全书内容质量优秀，章节逻辑清晰，通顺性好",
  passedChapters: [1, 2, 3, 4, 5],
  failedChapters: []
});

const mockQualityFailResponse = JSON.stringify({
  overallScore: 68,
  overallAssessment: "部分章节存在逻辑和跑题问题，需要改写",
  passedChapters: [1, 4],
  failedChapters: [
    {
      chapterNumber: 2,
      chapterTitle: "变量与数据类型",
      scores: { fluency: 20, logic: 12, relevance: 15, completeness: 18 },
      totalScore: 65,
      issues: [
        {
          dimension: "logic",
          severity: "high",
          description: "变量作用域的解释与前面声明周期的概念矛盾",
          location: "第3段",
          suggestion: "统一变量作用域的定义，参考MDN标准术语"
        }
      ],
      rewriteInstructions: "修复逻辑矛盾，统一变量作用域概念"
    },
    {
      chapterNumber: 3,
      chapterTitle: "控制流",
      scores: { fluency: 15, logic: 14, relevance: 10, completeness: 14 },
      totalScore: 53,
      issues: [
        {
          dimension: "relevance",
          severity: "high",
          description: "大段内容在讲数据结构而非控制流，严重跑题",
          location: "第2段开始",
          suggestion: "裁减数据结构内容，聚焦if/switch/loop等控制流语句"
        },
        {
          dimension: "fluency",
          severity: "medium",
          description: "多处句子过长，可读性差",
          location: "全文多处",
          suggestion: "拆分长句，每句不超过30字"
        }
      ],
      rewriteInstructions: "去除跑题内容，拆分长句，精简文笔"
    }
  ]
});

// 模拟质量校验带 think 标签的响应
const mockQualityWithThink = `<think>这个内容需要仔细评估...</think>
${JSON.stringify({
  overallScore: 75,
  overallAssessment: "中等水平，第3章有轻微问题",
  passedChapters: [1, 2, 4, 5],
  failedChapters: [
    {
      chapterNumber: 3,
      chapterTitle: "数组与集合",
      scores: { fluency: 18, logic: 16, relevance: 15, completeness: 17 },
      totalScore: 66,
      issues: [],
      rewriteInstructions: "需要增加代码示例"
    }
  ]
})}`;

// 模拟 rewrite 响应
const mockRewriteResponse = JSON.stringify({
  chapters: [
    {
      number: 2,
      title: "变量与数据类型",
      rewrittenContent: "# 第2章 变量与数据类型\n\n修正后的内容...",
      changesSummary: "修复了变量作用域的矛盾表述"
    }
  ]
});

// ====== 解析函数（从源文件摘取核心逻辑用于测试）======

function parseJSONResponse(raw: string) {
  let cleaned = raw.trim();
  const thinkEnd = cleaned.indexOf('</think>');
  if (thinkEnd !== -1) cleaned = cleaned.substring(thinkEnd + 8).trim();
  const match = cleaned.match(/\{[\s\S]*\}/);
  return match ? JSON.parse(match[0]) : null;
}

function parseQualityCheckResponse(response: string) {
  try {
    const data = parseJSONResponse(response);
    if (!data) return null;
    return {
      overallScore: data.overallScore || 0,
      overallAssessment: data.overallAssessment || '',
      passedChapters: data.passedChapters || [],
      failedChapters: (data.failedChapters || []).map((fc: any) => ({
        chapterNumber: fc.chapterNumber || 0,
        chapterTitle: fc.chapterTitle || '',
        scores: {
          fluency: fc.scores?.fluency ?? 0,
          logic: fc.scores?.logic ?? 0,
          relevance: fc.scores?.relevance ?? 0,
          completeness: fc.scores?.completeness ?? 0,
        },
        totalScore: fc.totalScore ?? 0,
        issues: fc.issues || [],
        rewriteInstructions: fc.rewriteInstructions || '请重新撰写本章',
      })),
    };
  } catch { return null; }
}

function parseRewriteResponse(response: string) {
  try {
    const data = parseJSONResponse(response);
    if (!data) return null;
    const chapters = data.chapters || data;
    if (Array.isArray(chapters) && chapters.length > 0) {
      return {
        title: chapters[0].title || '',
        rewrittenContent: chapters[0].rewrittenContent || chapters[0].content || '',
        changesSummary: chapters[0].changesSummary || '',
      };
    }
    return null;
  } catch { return null; }
}

// ====== 测试用例 ======

let passed = 0, failed = 0;

function test(name: string, fn: () => void) {
  try {
    fn();
    console.log(`  ✅ ${name}`);
    passed++;
  } catch (e: any) {
    console.log(`  ❌ ${name}: ${e.message}`);
    failed++;
  }
}

console.log('\n📋 质量校验 & 改写优化节点 - 单元测试\n');

// ---- 质量校验响应解析 ----
console.log('📝 质量校验响应解析:'); 

test('解析全部通过的响应', () => {
  const result = parseQualityCheckResponse(mockQualityPassResponse);
  assert.ok(result, '解析结果不能为空');
  assert.strictEqual(result.overallScore, 92);
  assert.strictEqual(result.passedChapters.length, 5);
  assert.strictEqual(result.failedChapters.length, 0);
  assert.strictEqual(result.overallAssessment.includes('优秀'), true);
});

test('解析有不合格章节的响应', () => {
  const result = parseQualityCheckResponse(mockQualityFailResponse);
  assert.ok(result, '解析结果不能为空');
  assert.strictEqual(result.overallScore, 68);
  assert.strictEqual(result.failedChapters.length, 2);
  assert.strictEqual(result.failedChapters[0].chapterNumber, 2);
  assert.strictEqual(result.failedChapters[0].scores.logic, 12);
  assert.strictEqual(result.failedChapters[0].issues[0].severity, 'high');
  assert.strictEqual(result.failedChapters[1].issues.length, 2);
});

test('解析带 think 标签的响应', () => {
  const result = parseQualityCheckResponse(mockQualityWithThink);
  assert.ok(result, 'think标签不应影响解析');
  assert.strictEqual(result.overallScore, 75);
  assert.strictEqual(result.failedChapters.length, 1);
});

test('解析空字符串', () => {
  const result = parseQualityCheckResponse('');
  assert.strictEqual(result, null, '空字符串应返回null');
});

test('解析非法JSON', () => {
  const result = parseQualityCheckResponse('这不是JSON');
  assert.strictEqual(result, null, '非法JSON应返回null');
});

// ---- 改写响应解析 ----
console.log('\n📝 改写响应解析:');

test('解析正常改写响应', () => {
  const result = parseRewriteResponse(mockRewriteResponse);
  assert.ok(result, '解析结果不能为空');
  assert.strictEqual(result.title, '变量与数据类型');
  assert.ok(result.rewrittenContent.includes('修正后'), '应包含改写内容');
  assert.ok(result.changesSummary.length > 0, '应有改动摘要');
});

test('解析空响应', () => {
  const result = parseRewriteResponse('');
  assert.strictEqual(result, null, '空响应应返回null');
});

// ---- 质量评分阈值 ----
console.log('\n📝 评分阈值逻辑:');

test('总分≥80为通过', () => {
  const passResult = parseQualityCheckResponse(mockQualityPassResponse)!;
  const allPassed = passResult.overallScore >= 80 && passResult.failedChapters.length === 0;
  assert.strictEqual(allPassed, true);
});

test('总分<80且存在不合格章节为不通过', () => {
  const failResult = parseQualityCheckResponse(mockQualityFailResponse)!;
  const needsRewrite = failResult.overallScore < 80 || failResult.failedChapters.length > 0;
  assert.strictEqual(needsRewrite, true);
});

// ---- 改写指令完整性 ----
console.log('\n📝 改写指令完整性:');

test('不合格章节必须有改写指令', () => {
  const result = parseQualityCheckResponse(mockQualityFailResponse)!;
  for (const fc of result.failedChapters) {
    assert.ok(fc.rewriteInstructions.length > 0, 
      `第${fc.chapterNumber}章缺少改写指令`);
  }
});

test('每条问题必须有四个维度之一', () => {
  const validDimensions = ['fluency', 'logic', 'relevance', 'completeness'];
  const result = parseQualityCheckResponse(mockQualityFailResponse)!;
  for (const fc of result.failedChapters) {
    for (const issue of fc.issues) {
      assert.ok(validDimensions.includes(issue.dimension),
        `无效维度: ${issue.dimension}`);
    }
  }
});

// ====== 结果汇总 ======
console.log(`\n${'='.repeat(40)}`);
console.log(`测试结果: ${passed} 通过, ${failed} 失败, ${passed + failed} 总计`);
console.log(`${'='.repeat(40)}\n`);

process.exit(failed > 0 ? 1 : 0);
