import { WritableStreamBuffer } from 'stream-buffers'
import { createLLM } from './llm'
import { createFlow } from './flow'
import { createER } from './er'
import { createTable } from './table'
import { uploadDoc } from './upload'
import { createArch } from './arch'
import { createAbstract } from './abstract'
import { createUseCase } from './useCase'

export async function genPaper(title: string, desc: string) {
    const tools = createLLM()
    const { llm, usage, conversation } = tools
    const pRetry = (await eval("import('p-retry')")).default

    const chapters = [
        {
            title: '第一章概述'
        },
        {
            title: '第二章关键技术介绍'
        },
        {
            title: '第三章系统分析',
            sections: [
                {
                    title: '3.1 系统概述'
                },
                {
                    title: '3.2 需求分析'
                },
                {
                    title: '3.3 可行性分析'
                },
                {
                    title: '3.4 系统流程分析'
                },
                {
                    title: '3.5 本章小节'
                }
            ]
        },
        {
            title: '第四章系统设计',
            sections: [
                { title: '4.1 系统基本结构设计' },
                {
                    title: '4.2 数据库设计',
                    sections: [{ title: '4.2.1 数据库ER图设计' }, { title: '4.2.2 数据库表设计' }]
                },
                { title: '4.3 本章小节' }
            ]
        },
        {
            title: '第五章系统实现'
        },
        {
            title: '第六章系统测试'
        },
        {
            title: '结论'
        },
        {
            title: '参考文献'
        },
        {
            title: '致谢'
        }
    ]
    let paper = new WritableStreamBuffer()
    const startTime = Date.now()

    paper.write(`${await createAbstract(tools, title, desc)}\n\n`)

    const { chain, memory } = conversation(`你是一个计算机专业擅长写毕业论文的专家，你的任务是帮我的毕业设计撰写一篇论文
我的毕业设计项目是${title}
这个项目包含以下功能：${desc}
现在我们已经为论文拟好了一个大纲：
${chapters.map((i) => `- ${i.title}`).join('\n')}

现在我们来一步一步的编写这篇论文
请严格按照markdown格式返回内容。
请注意，你只需要输出能够直接出现在论文中的内容，不需要输出你对该内容的总结或者介绍等其他文字`)

    for (let i = 0; i < chapters.length; i++) {
        if (i === 2) {
            for (let j = 0; j < chapters[i].sections.length; j++) {
                let input = ''
                if (j === 0) {
                    input += `现在我们来编写第三章系统分析，这一章节内容较多，我们可以分成几个小节来写:
${chapters[i].sections.map((i) => i.title).join('\n')}\n`
                }
                input += `现在我们来编写${chapters[i].title}的第${j + 1}小节: ${chapters[i].sections[j].title}`
                if (j === 0) {
                    const arch = await createArch(tools, title, desc)
                    const useCases = await createUseCase(tools, title, desc)
                    input += `\n我已为你绘制好了以下总体结构图:
![总体结构图](${arch.url})

以及以下用例图:
${useCases.map((i) => {
    return `- ![${i.name}用例图](${i.url})`
})}

请你帮我完成第${j + 1}小节: ${chapters[i].sections[j].title}的内容，请确保附上我提供的总体结构图和用例图`
                }
                if (j === 3) {
                    const flows = await createFlow(tools, title, desc)
                    input += `\n我已为你绘制好了以下几个流程图       
${flows
    .map((i) => {
        return `- ![${i.name}](${i.url})
${i.desc}`
    })
    .join('\n\n')}

请你帮我完成第${j + 1}小节: ${chapters[i].sections[j].title}的内容，请确保附上我提供的图片`
                }
                let { response } = await chain.call({
                    input: input
                })
                if (j !== 0) {
                    response = response.replace(/# ?第三章 ?系统分析\n/, '')
                }
                paper.write('\n\n' + response)
            }
        } else if (i === 3) {
            for (let j = 0; j < chapters[i].sections.length; j++) {
                let input = ''
                if (j === 0) {
                    input += `现在我们来编写第四章系统设计，这一章节内容较多，我们可以分成几个小节来写:
${chapters[i].sections.map((i) => i.title).join('\n')}\n`
                }
                input += `\n现在我们来编写${chapters[i].title}的第${j + 1}小节: ${chapters[i].sections[j].title}`

                if (j === 1) {
                    const er = await createER(tools, title, desc)
                    const table = await createTable(tools, title, desc)
                    input += `\n本小节分为以下几个部分：
${chapters[i].sections[j].sections.map((i) => `- ${i.title}`).join('\n')}

我已为你绘制好了以下几个ER图:

${er
    .map((i) => {
        return `- ![${i.name}ER图](${i.url})
${i.desc}`
    })
    .join('\n')}

以下是数据库表的设计：

${table
    .map((i) => {
        return `- ${i.name}表：
${i.desc}
`
    })
    .join('\n\n')}

请你帮我编写第${j + 1}小节: ${
                        chapters[i].sections[j].title
                    }的内容, 请确保附上我提供的ER图以及设计好的数据库表。(请注意，我希望你保持数据库表格的原始格式，不需要转换为SQL语句)`
                }
                let { response } = await chain.call({
                    input: input
                })
                if (j !== 0) {
                    response = response.replace(/# ?第四章 ?系统设计\n/, '')
                }
                paper.write('\n\n' + response)
            }
        } else {
            const { response } = await chain.call({
                input: `现在我们来编写${chapters[i].title}`
            })
            paper.write('\n\n' + response)
        }
    }

    const content = paper.getContentsAsString('utf8')
    const duration = (Date.now() - startTime) / 1000
    const fileUrl = await uploadDoc(title, content)
    return {
        content,
        duration,
        tokenUsage: usage,
        fileUrl
    }
}
