import { HumanMessage } from 'langchain/schema'
import { StructuredOutputParser } from 'langchain/output_parsers'
import { z } from 'zod'
import { uploadUml } from './upload'
import { LLMTools } from './types'

async function genFlowNames(tools: LLMTools, title, desc) {
    const { llm, usage, conversation } = tools
    const scheme = StructuredOutputParser.fromZodSchema(
        z.array(
            z.object({
                title: z.string().describe('流程图名称')
            })
        )
    )
    const { content } = await llm.call([
        new HumanMessage(`${scheme.getFormatInstructions()}
------
你是一个计算机专业擅长写毕业论文的专家，你的任务是帮我的毕业设计撰写一篇论文
我的毕业设计项目是${title}
这个项目包含以下功能：
${desc}
现在我们分析一下论文中需要用到的流程图，我们需要绘制以下五个主要流程图：`)
    ])
    return await scheme.parse(content)
}

async function plotFlow(tools, title, desc, name) {
    const { llm, usage, conversation } = tools
    const { chain } = conversation(`你是一个计算机专业擅长写毕业论文的专家，你的任务是帮我的毕业设计撰写一篇论文
我的毕业设计项目是${title}
这个项目包含以下功能：
${desc}`)
    const { response: descr } = await chain.call({
        input: `现在我们需要在论文中附上${name}，请你先用文字描述一下这个流程`
    })
    let { response: code } = await chain.call({
        input: `现在根据文字描述将它转换为plantuml语言
这是一个plantuml流程图的示例：
\`\`\`
@startuml 名称

start

if (Graphviz installed?) then (yes)
:process all\ndiagrams;
else (no)
:process only
__sequence__ and __activity__ diagrams;
endif

stop

@enduml

\`\`\``
    })
    code = /\`\`\`(?:plantuml)?([\s\S]+)\`\`\`/.exec(code)[1]
    const url = await uploadUml(code)
    return {
        name,
        desc: descr,
        url
    }
}

export async function createFlow(tools: LLMTools, title, desc) {
    const pRetry = (await eval("import('p-retry')")).default
    const list = await pRetry(() => genFlowNames(tools, title, desc), { retries: 5 })
    return await Promise.all(list.map((item) => pRetry(() => plotFlow(tools, title, desc, item.title), { retries: 5 })))
}
