/**
 * 大纲生成节点（集成容错机制）
 */

import { GraphState } from '../graph';
import { bookStore } from '../book-generator.store';
import { callLLMWithMessages } from '../../../services/llm';
import { parseOutline } from '../parsers/outline.parser';
import { buildOutlineMessages, SCALE_CHAPTER_RANGE } from '../prompts/builder';
import { PROGRESS } from '../utils';
import { callLLMWithRetry, executeNodeWithTimeout, FAULT_TOLERANCE_CONFIG } from '../fault-tolerance';
import { getChapterRange } from '../book-type-config';

export async function generateOutlineNode(state: typeof GraphState.State): Promise<Partial<typeof GraphState.State>> {
  console.log('[LangGraph] 生成大纲, bookId:', state.bookId, 'scale:', state.bookScale);

  // 读取前序规划节点的分析结果，用于指导大纲生成
  let bookPlan: any = null;
  if (state.bookPlan) {
    try {
      bookPlan = JSON.parse(state.bookPlan);
      console.log('[LangGraph] 使用规划结果指导大纲:', bookPlan.structureLogic, bookPlan.writingStyle);
    } catch {
      console.warn('[LangGraph] bookPlan 解析失败，忽略');
    }
  }

  try {
    // 使用容错包装器执行AI调用
    const response = await executeNodeWithTimeout(
      state.bookId,
      'generate_outline',
      async () => {
        return callLLMWithRetry(
          buildOutlineMessages(state.topic, state.bookScale, state.description, bookPlan),
          undefined,
          {
            bookId: state.bookId,
            nodeId: 'generate_outline',
            attempt: 0,
            maxAttempts: FAULT_TOLERANCE_CONFIG.aiRetry.maxRetries,
          }
        );
      },
      FAULT_TOLERANCE_CONFIG.nodeTimeout.generate_outline
    );

    const outline = parseOutline(response);
    if (!outline) throw new Error('大纲解析失败');

    // 校验章节数：允许 ±20% 浮动，超出才截断/补充
    const targetChapters = SCALE_CHAPTER_RANGE[state.bookScale as keyof typeof SCALE_CHAPTER_RANGE];
    if (targetChapters) {
      const { min: minAllowed, max: maxAllowed } = getChapterRange(targetChapters);
      const actual = outline.chapters.length;

      if (actual > maxAllowed) {
        console.warn(`[LangGraph] AI 返回章节数 ${actual} 超出上限 ${maxAllowed}，截断`);
        outline.chapters = outline.chapters.slice(0, maxAllowed);
      } else if (actual < minAllowed) {
        console.warn(`[LangGraph] AI 返回章节数 ${actual} 少于下限 ${minAllowed}，使用话题相关的默认章节补充`);
        const topicHint = state.topic?.substring(0, 30) || '';
        const perChapterWords = Math.round(parseInt(state.bookScale) / minAllowed);
        const gapTopics = [
          `概述与背景`,
          `核心概念`,
          `深入探究`,
          `应用与实践`,
          `总结与展望`,
        ];
        while (outline.chapters.length < minAllowed) {
          const idx = outline.chapters.length;
          const gapTitle = gapTopics[idx % gapTopics.length];
          outline.chapters.push({
            number: idx + 1,
            title: topicHint ? `第${idx + 1}章 ${topicHint} - ${gapTitle}` : `第${idx + 1}章 ${gapTitle}`,
            summary: `本章围绕"${topicHint || gapTitle}"展开，介绍${gapTitle}相关内容。`,
            keyPoints: [gapTitle, '关键知识点', '实践要点'],
            estimatedWords: perChapterWords,
          });
        }
      }
      // 在范围内（±20%）不做任何处理，让 AI 自己决定
    }

    // 短文类至少1个章节
    if (outline.chapters.length === 0) {
      console.warn('[LangGraph] AI 返回章节数为0，使用话题创建默认章节');
      const fallbackTitle = state.topic?.substring(0, 50) || '正文';
      outline.chapters = [{
        number: 1,
        title: fallbackTitle,
        summary: `关于"${fallbackTitle}"的全面介绍，涵盖核心概念、关键知识和实践要点。`,
        keyPoints: ['核心概念', '关键知识', '实践要点'],
        estimatedWords: parseInt(state.bookScale) || 800,
      }];
    }

    const totalChapters = outline.chapters.length;
    await bookStore.update(state.bookId, {
      totalChapters,
      outlineJson: JSON.stringify(outline),
      progress: PROGRESS.OUTLINE_DONE
    });
    await bookStore.createChapters(state.bookId, outline.chapters.map(c => ({
      number: c.number,
      title: c.title,
      summary: c.summary,
      keyPoints: c.keyPoints,
      estimatedWords: c.estimatedWords,
    })));

    console.log('[LangGraph] 大纲生成完成，章节数:', outline.chapters.length);
    return { progress: PROGRESS.OUTLINE_DONE };
  } catch (error) {
    console.error('[LangGraph] 大纲生成失败:', error);
    // 更新书籍状态为失败
    await bookStore.update(state.bookId, {
      genStage: 'failed',
      failedStage: 'outlining',
      errorMsg: error instanceof Error ? error.message : '大纲生成失败',
    });
    return {
      error: error instanceof Error ? error.message : '大纲生成失败',
      finished: true
    };
  }
}
