/**
 * 质量校验节点（qualityCheckNode）
 *
 * 在正文内容并行生成完成后，对所有章节做四维质量评估：
 * - 通顺性（fluency）
 * - 逻辑性（logic）
 * - 是否跑题（relevance）
 * - 是否达标（completeness）
 *
 * 输出每个章节的评分和问题列表，决定是否进入重写环节。
 * 与 rewrite.node.ts 组成质量闭环：校验→不通过→重写→再校验
 */

import { GraphState } from '../graph';
import { bookStore } from '../book-generator.store';
import { callLLMWithMessages, ChatMessage } from '../../../services/llm';
import { callLLMWithRetry, executeNodeWithTimeout, FAULT_TOLERANCE_CONFIG } from '../fault-tolerance';
import { QUALITY_CHECK_SYSTEM_PROMPT } from '../prompts/templates';
import { PROGRESS, countWords } from '../utils';
import { prisma } from '../../../models';

// ============ 类型定义 ============

export interface QualityScore {
  fluency: number;      // 通顺 0-25
  logic: number;        // 逻辑 0-25
  relevance: number;    // 跑题 0-25
  completeness: number; // 达标 0-25
}

export interface QualityIssue {
  dimension: 'fluency' | 'logic' | 'relevance' | 'completeness';
  severity: 'high' | 'medium' | 'low';
  description: string;
  location: string;
  suggestion: string;
}

export interface FailedChapter {
  chapterNumber: number;
  chapterTitle: string;
  scores: QualityScore;
  totalScore: number;
  issues: QualityIssue[];
  rewriteInstructions: string;
}

export interface QualityCheckResult {
  overallScore: number;
  overallAssessment: string;
  passedChapters: number[];
  failedChapters: FailedChapter[];
}

// ============ 常量 ============

/** 合格分数线 */
const PASS_THRESHOLD = 80;

/** 每批最大发送字符数（避免 token 超限）*/
const MAX_BATCH_CHARS = 60000;

// ============ 核心逻辑 ============

/**
 * 构建单批质量校验消息
 */
function buildBatchQualityCheckMessages(
  bookTitle: string,
  bookTopic: string,
  batchChapters: Array<{ number: number; title: string; content: string; summary?: string; estimatedWords?: number }>
): ChatMessage[] {
  let chaptersText = '';
  for (const ch of batchChapters) {
    const header = `\n## 第${ch.number}章：${ch.title}\n> 概述：${ch.summary || '无'}\n> 预估字数：${ch.estimatedWords || 0} | 实际字数：${countWords(ch.content)}\n\n`;
    const content = ch.content || '（空）';
    chaptersText += header + content;
  }

  return [
    { role: 'system', content: QUALITY_CHECK_SYSTEM_PROMPT },
    {
      role: 'user',
      content: `书名：《${bookTitle}》
主题：${bookTopic}

以下是 ${batchChapters.length} 个章节的完整内容，请逐一评估质量：

${chaptersText}

请输出 JSON 格式的质量评估报告。`,
    },
  ];
}

/**
 * 分批处理章节，确保每批不超过 MAX_BATCH_CHARS
 */
function splitChaptersIntoBatches(
  chapters: Array<{ number: number; title: string; content: string; summary?: string; estimatedWords?: number }>
): Array<Array<{ number: number; title: string; content: string; summary?: string; estimatedWords?: number }>> {
  const batches: Array<Array<{ number: number; title: string; content: string; summary?: string; estimatedWords?: number }>> = [];
  let currentBatch: Array<{ number: number; title: string; content: string; summary?: string; estimatedWords?: number }> = [];
  let currentChars = 0;

  for (const ch of chapters) {
    const headerLen = `\n## 第${ch.number}章：${ch.title}\n> 概述：${ch.summary || '无'}\n> 预估字数：${ch.estimatedWords || 0} | 实际字数：${countWords(ch.content)}\n\n`.length;
    const contentLen = (ch.content || '').length;
    const chapterChars = headerLen + contentLen;

    // 如果加上当前章节会超限，且当前批次不为空，则先保存当前批次
    if (currentChars + chapterChars > MAX_BATCH_CHARS && currentBatch.length > 0) {
      batches.push(currentBatch);
      currentBatch = [];
      currentChars = 0;
    }

    currentBatch.push(ch);
    currentChars += chapterChars;
  }

  if (currentBatch.length > 0) {
    batches.push(currentBatch);
  }

  return batches;
}

/**
 * 解析质量校验 JSON 响应
 * 使用多策略解析确保鲁棒性
 */
function parseQualityCheckResponse(response: string): QualityCheckResult | null {
  try {
    let cleaned = response.trim();

    // 移除 think 标签
    const thinkEnd = cleaned.indexOf('</think>');
    if (thinkEnd !== -1) {
      cleaned = cleaned.substring(thinkEnd + 8).trim();
    }

    // 策略1：直接解析
    try {
      const data = JSON.parse(cleaned);
      if (data.failedChapters !== undefined || data.passedChapters !== undefined) {
        return normalizeResult(data);
      }
    } catch { /* continue */ }

    // 策略2：正则提取 JSON
    const match = cleaned.match(/\{[\s\S]*\}/);
    if (match) {
      const data = JSON.parse(match[0]);
      if (data.failedChapters !== undefined || data.passedChapters !== undefined) {
        return normalizeResult(data);
      }
    }

    console.error('[QualityCheck] 所有解析策略失败');
    return null;
  } catch (err) {
    console.error('[QualityCheck] 解析异常:', err);
    return null;
  }
}

/**
 * 规范化校验结果，补全默认值
 */
function normalizeResult(data: any): QualityCheckResult {
  return {
    overallScore: typeof data.overallScore === 'number' ? data.overallScore : 0,
    overallAssessment: data.overallAssessment || '',
    passedChapters: Array.isArray(data.passedChapters)
      ? data.passedChapters.map(Number)
      : [],
    failedChapters: Array.isArray(data.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: Array.isArray(fc.issues) ? fc.issues : [],
          rewriteInstructions: fc.rewriteInstructions || '请重新撰写本章',
        }))
      : [],
  };
}

/**
 * 质量校验节点
 *
 * 评估所有已完成内容的章节，判定是否通过质量检查。
 * - 通过 → qualityPassed = true → 进入 continuity_edit
 * - 不通过 → qualityPassed = false → 进入 rewrite
 */
export async function qualityCheckNode(state: typeof GraphState.State): Promise<Partial<typeof GraphState.State>> {
  console.log('[QualityCheck] 开始质量校验, bookId:', state.bookId);

  try {
    const book = await bookStore.getById(state.bookId);
    if (!book) {
      console.log('[QualityCheck] 书籍不存在，跳过');
      return { qualityPassed: true, progress: state.progress };
    }

    const bookIdNum = parseInt(state.bookId);

    // 获取所有已完成内容的叶节点
    const completedChapters = await prisma.bookChapter.findMany({
      where: {
        bookId: bookIdNum,
        genStage: 'content_completed',
        content: { not: '' },
      },
      orderBy: { number: 'asc' },
    });

    if (completedChapters.length === 0) {
      console.log('[QualityCheck] 无已完成内容，跳过');
      return { qualityPassed: true, progress: state.progress };
    }

    console.log(`[QualityCheck] 评估 ${completedChapters.length} 个已完成章节`);

    // 构建章节信息
    const chapterInfos = completedChapters.map(ch => ({
      number: ch.number,
      title: ch.title,
      content: ch.content,
      summary: ch.summary || undefined,
      estimatedWords: (ch as any).estimatedWords || 0,
    }));

    // 分批处理，避免上下文窗口超限
    const batches = splitChaptersIntoBatches(chapterInfos);
    console.log(`[QualityCheck] 分 ${batches.length} 批评估`);

    // 合并多批结果
    const allPassedChapters: number[] = [];
    const allFailedChapters: FailedChapter[] = [];
    let totalScore = 0;
    let assessedCount = 0;

    for (let i = 0; i < batches.length; i++) {
      const batch = batches[i];
      console.log(`[QualityCheck] 处理第${i + 1}批（${batch.length}章节）`);

      const messages = buildBatchQualityCheckMessages(
        book.title,
        state.topic,
        batch
      );

      const response = await executeNodeWithTimeout(
        state.bookId,
        'quality_check',
        async () => callLLMWithRetry(
          messages,
          undefined,
          { bookId: state.bookId, nodeId: 'quality_check', attempt: 0, maxAttempts: FAULT_TOLERANCE_CONFIG.aiRetry.maxRetries }
        ),
        FAULT_TOLERANCE_CONFIG.nodeTimeout.continuity_edit
      );

      const batchResult = parseQualityCheckResponse(response);
      if (!batchResult) {
        console.warn(`[QualityCheck] 第${i + 1}批解析失败，跳过`);
        continue;
      }

      allPassedChapters.push(...batchResult.passedChapters);
      allFailedChapters.push(...batchResult.failedChapters);
      totalScore += batchResult.overallScore * batch.length; // 加权累计
      assessedCount += batch.length;
    }

    // 合并最终结果
    const overallScore = assessedCount > 0 ? Math.round(totalScore / assessedCount) : 0;
    const finalResult: QualityCheckResult = {
      overallScore,
      overallAssessment: `分${batches.length}批评估，共${assessedCount}章，合格${allPassedChapters.length}章，不合格${allFailedChapters.length}章`,
      passedChapters: allPassedChapters,
      failedChapters: allFailedChapters,
    };

    const result = finalResult;

    if (!result) {
      console.warn('[QualityCheck] 解析失败，默认通过');
      return { qualityPassed: true, progress: state.progress };
    }

    // 计算整体通过状态
    const hasFailedChapters = result.failedChapters.length > 0;
    const qualityPassed = !hasFailedChapters;

    console.log(`[QualityCheck] 总分: ${result.overallScore}, 不合格章节: ${result.failedChapters.length}`);
    if (hasFailedChapters) {
      for (const fc of result.failedChapters) {
        console.log(`  - 第${fc.chapterNumber}章「${fc.chapterTitle}」得分: ${fc.totalScore} → ${fc.rewriteInstructions}`);
      }
    }

    // 持久化质量报告到数据库
    await bookStore.update(state.bookId, {
      errorMsg: `[质量校验] ${result.overallAssessment}`,
    } as any);

    const qualityResultJson = JSON.stringify(result);

    return {
      qualityPassed,
      qualityResult: qualityResultJson,
      progress: qualityPassed ? PROGRESS.CONTENT_END : Math.min(state.progress + 2, PROGRESS.CONTENT_END - 5),
    };
  } catch (error) {
    console.error('[QualityCheck] 校验失败:', error);
    // 容错：失败时不阻塞流水线
    return { qualityPassed: true, progress: state.progress };
  }
}
