"use strict";
/**
 * LangGraph 书籍生成器
 * 使用 @langchain/langgraph v1.2.8 API
 * 状态通过数据库传递，LangGraph 只负责流程控制
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.langGraphGenerator = exports.LangGraphBookGenerator = void 0;
const axios_1 = __importDefault(require("axios"));
const config_1 = require("../../../config");
const book_generator_store_1 = require("../book-generator.store");
const langgraph_1 = require("@langchain/langgraph");
// ============ 定义 State ============
const GraphState = langgraph_1.Annotation.Root({
    bookId: (langgraph_1.Annotation),
    topic: (langgraph_1.Annotation),
    bookScale: (langgraph_1.Annotation), // 纯数字字符串，如 '1000', '130000', '340000'
    currentChapter: (langgraph_1.Annotation),
    finished: (langgraph_1.Annotation),
    error: (langgraph_1.Annotation),
    progress: (langgraph_1.Annotation),
});
// ============ LLM 配置 ============
const TEMPERATURE = 0.7;
const MAX_RETRIES = 2;
async function callLLM(prompt, currentModel) {
    const modelId = currentModel || config_1.config.models.textGeneration.defaultModel;
    const modelConfig = config_1.config.models.getModel(modelId);
    const apiKey = modelConfig?.apiKey;
    const baseUrl = modelConfig?.baseUrl;
    if (!apiKey || !baseUrl)
        throw new Error(`模型 ${modelId} 缺少 API 配置`);
    try {
        const response = await axios_1.default.post(`${baseUrl}/chat/completions`, { model: modelId, messages: [{ role: 'user', content: prompt }] }, { headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, timeout: 180000 });
        const result = response.data?.choices?.[0]?.message?.content || '';
        if (!result)
            throw new Error('API 返回内容为空');
        return result;
    }
    catch (error) {
        const errorMessage = error.response?.data?.message || error.message || 'API 调用失败';
        console.log(`[LLM] 模型 ${modelId} 调用失败: ${errorMessage}`);
        // 检查是否需要切换模型
        if (config_1.config.models.shouldSwitchModel(errorMessage)) {
            const nextModel = config_1.config.models.getNextModel(modelId, 'text');
            if (nextModel) {
                console.log(`[LLM] 自动切换到模型: ${nextModel}`);
                return callLLM(prompt, nextModel);
            }
        }
        throw new Error(errorMessage);
    }
}
function countWords(text) {
    return (text.match(/[\u4e00-\u9fa5]/g) || []).length;
}
function parseOutline(jsonStr) {
    try {
        const match = jsonStr.match(/\{[\s\S]*\}/);
        if (match) {
            const data = JSON.parse(match[0]);
            return {
                mainTheme: data.mainTheme || '主题待定',
                structureLogic: data.structureLogic || '由浅入深',
                chapters: (data.chapters || []).map((c, i) => ({
                    number: c.number || i + 1,
                    title: c.title || `第${i + 1}章`,
                    summary: c.summary || '',
                    keyPoints: c.keyPoints || [],
                    estimatedWords: c.estimatedWords || 1000,
                })),
            };
        }
    }
    catch {
        console.error('解析大纲失败');
    }
    return null;
}
// ============ LangGraph 节点（从数据库读取状态）============
// 规模对应的章节范围
const SCALE_CHAPTER_RANGE = {
    '800': { min: 1, max: 1, wordsPerChapter: 800 },
    '2000': { min: 1, max: 1, wordsPerChapter: 2000 },
    '5000': { min: 1, max: 1, wordsPerChapter: 5000 },
    '2000': { min: 2, max: 8, wordsPerChapter: 3000 },
    '130000': { min: 5, max: 15, wordsPerChapter: 2500 },
    '340000': { min: 10, max: 20, wordsPerChapter: 2500 },
};
async function generateOutlineNode(state) {
    console.log('[LangGraph] 生成大纲, bookId:', state.bookId, 'scale:', state.bookScale);
    // 规模说明
    const scaleDesc = {
        '800': '短文，约800字',
        '2000': '短文，约2000字',
        '5000': '短文，约5000字',
    };
    const scaleLabel = scaleDesc[state.bookScale] || `书籍，约${state.bookScale}字`;
    const prompt = `请为书籍《${state.topic}》设计大纲。

书籍规模：${scaleDesc[state.bookScale] || '中篇'}

请分析这个主题的复杂程度，决定合适的章节数量（${SCALE_CHAPTER_RANGE[state.bookScale]?.min || 5}-${SCALE_CHAPTER_RANGE[state.bookScale]?.max || 10}章之间），并生成完整大纲。

返回JSON格式：
{
  "mainTheme": "主题一句话描述",
  "structureLogic": "结构逻辑说明",
  "chapters": [
    {
      "number": 1,
      "title": "章节标题",
      "summary": "章节摘要，50字左右",
      "keyPoints": ["要点1", "要点2", "要点3"],
      "estimatedWords": 预估字数
    }
  ]
}

请确保：
1. 章节数根据主题实际复杂度决定，不要固定用中间值
2. 章节之间有清晰的逻辑递进关系
3. 每章的预估字数要符合规模要求`;
    try {
        const response = await callLLM(prompt);
        const outline = parseOutline(response);
        if (!outline)
            throw new Error('大纲解析失败');
        // 更新书籍的总章节数
        const totalChapters = outline.chapters.length;
        // 保存大纲和创建章节到数据库
        await book_generator_store_1.bookStore.update(state.bookId, {
            totalChapters,
            outlineJson: JSON.stringify(outline),
            status: 'planning',
            progress: 5,
        });
        // 创建章节记录
        await book_generator_store_1.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: 5 };
    }
    catch (error) {
        console.error('[LangGraph] 大纲生成失败:', error);
        return { error: error instanceof Error ? error.message : '失败', finished: true };
    }
}
async function writeChaptersNode(state) {
    console.log('[LangGraph] 生成章节, bookId:', state.bookId);
    // 从数据库读取书籍和章节
    const book = await book_generator_store_1.bookStore.getById(state.bookId);
    if (!book || !book.outline) {
        console.log('[LangGraph] 无大纲或书籍，跳过章节生成');
        return { finished: true, progress: 90 };
    }
    const chapters = [];
    const failedChapters = [];
    for (const chapterOutline of book.outline.chapters) {
        console.log(`[LangGraph] 生成第${chapterOutline.number}章: ${chapterOutline.title}`);
        const prompt = `撰写《${state.topic}》第${chapterOutline.number}章。章节：${chapterOutline.title}，概述：${chapterOutline.summary}，知识点：${chapterOutline.keyPoints.join(', ')}，长度${chapterOutline.estimatedWords}字左右。直接输出正文：`;
        try {
            const content = await callLLM(prompt);
            const wordCount = countWords(content);
            await book_generator_store_1.bookStore.updateChapter(state.bookId, chapterOutline.number, {
                content,
                wordCount,
                status: 'completed',
            });
            chapters.push({
                number: chapterOutline.number,
                title: chapterOutline.title,
                content,
                wordCount,
                status: 'completed',
            });
            const progress = Math.round((chapters.length / book.outline.chapters.length) * 80) + 10;
            await book_generator_store_1.bookStore.update(state.bookId, { progress, status: 'generating' });
            console.log(`[LangGraph] 第${chapterOutline.number}章完成，进度${progress}%`);
        }
        catch (error) {
            const errorMsg = error instanceof Error ? error.message : '失败';
            await book_generator_store_1.bookStore.updateChapter(state.bookId, chapterOutline.number, { status: 'failed', errorMsg });
            failedChapters.push(chapterOutline.number);
            console.error(`[LangGraph] 第${chapterOutline.number}章失败:`, errorMsg);
        }
    }
    return {
        currentChapter: book.outline.chapters.length,
        progress: 90,
        error: failedChapters.length > 0 ? `章节${failedChapters.join(',')}失败` : undefined,
    };
}
async function writeForewordNode(state) {
    console.log('[LangGraph] 生成前言, bookId:', state.bookId);
    const prompt = `为《${state.topic}》写前言。主题：${state.topic}，300-500字。直接输出：`;
    try {
        const foreword = await callLLM(prompt);
        await book_generator_store_1.bookStore.update(state.bookId, { foreword, progress: 95 });
        return { progress: 95 };
    }
    catch (error) {
        console.error('[LangGraph] 前言生成失败:', error);
        return { progress: 95 };
    }
}
async function writeAfterwordNode(state) {
    console.log('[LangGraph] 生成后记, bookId:', state.bookId);
    const prompt = `为《${state.topic}》写后记。主题：${state.topic}，300-500字。直接输出：`;
    try {
        const afterword = await callLLM(prompt);
        await book_generator_store_1.bookStore.update(state.bookId, { afterword });
        return { finished: true, progress: 100 };
    }
    catch (error) {
        console.error('[LangGraph] 后记生成失败:', error);
        return { finished: true, progress: 100 };
    }
}
// ============ 创建工作流 ============
function createGraph() {
    const workflow = new langgraph_1.StateGraph(GraphState)
        .addNode('generate_outline', generateOutlineNode)
        .addNode('write_chapters', writeChaptersNode)
        .addNode('write_foreword', writeForewordNode)
        .addNode('write_afterword', writeAfterwordNode)
        .setEntryPoint('generate_outline')
        // 顺序流程
        .addEdge('generate_outline', 'write_chapters')
        .addEdge('write_chapters', 'write_foreword')
        .addEdge('write_foreword', 'write_afterword')
        .addEdge('write_afterword', langgraph_1.END);
    return workflow.compile();
}
// ============ 主类 ============
class LangGraphBookGenerator {
    graph = createGraph();
    async generate(bookId, topic, bookScale = '130000') {
        const initialState = {
            bookId,
            topic,
            bookScale,
            currentChapter: 0,
            finished: false,
            error: undefined,
            progress: 0,
        };
        await book_generator_store_1.bookStore.update(bookId, { status: 'generating', progress: 0 });
        try {
            const stream = await this.graph.stream(initialState);
            for await (const step of stream) {
                console.log('[LangGraph] Step:', Object.keys(step));
            }
            await book_generator_store_1.bookStore.update(bookId, { status: 'completed', progress: 100 });
            await book_generator_store_1.bookStore.publishAlbum(bookId); // 发布专辑
            console.log('[LangGraph] 书籍生成完成');
        }
        catch (error) {
            console.error('[LangGraph] 生成失败:', error);
            await book_generator_store_1.bookStore.update(bookId, { status: 'failed', errorMsg: error instanceof Error ? error.message : '生成失败' });
        }
    }
}
exports.LangGraphBookGenerator = LangGraphBookGenerator;
exports.langGraphGenerator = new LangGraphBookGenerator();
