<script setup lang="ts">
import Msg from "./_/Msg.vue";
import PromptText from "./prompt.txt?raw";

const chatboxContainerEl = useTemplateRef<HTMLDivElement>("chatboxContainer");
const chatboxContentEl = useTemplateRef<HTMLDivElement>("chatboxContent");
const { scrollToBottom } = useScroll({
    containerEl: chatboxContainerEl,
    contentEl: chatboxContentEl,
    firstToBottom: true,
});

// import sseDataModule from "./_/sseData.ts";
interface IMsg <T = "user">{
    role: "user" | "assistant" | "system",
    content: T extends "user" ? any : string,
    reasoning_content?: string,
    isHidden?: boolean
}
const msgList = ref<IMsg[]>([
    {
        role: "system",
        content: PromptText
    }
]);
const inputMsg = ref("");

enum STATUS {
    WAITING = "WAITING",
    SENDING = "SENDING",
}
const status = ref(STATUS.WAITING);

const { sendStream, getConfig, updateConfig } = useChat(Chat.ModelProvider.OpenAI, {
    // DeepSeek
    // model: "deepseek-chat",
    // apiKey: process.env.AI_APIKEY,
    // baseUrl: "https://api.deepseek.com",
    // temperature: 0.8,

    // siliconflow
    model: "Qwen/Qwen3-8B", // 免费文本模型，可tools
    // model: "deepseek-ai/deepseek-vl2",
    apiKey: process.env.AI_APIKEY,
    baseUrl: "https://api.siliconflow.cn/v1",
    temperature: 0.8,
});

const openaiConfig = reactive({
    model: getConfig().model,
    apiKey: getConfig().apiKey,
    baseUrl: getConfig().baseUrl,
    temperature: getConfig().temperature,
});
watch(openaiConfig, () => {
    updateConfig(toRaw(openaiConfig) as OpenAIModelConfig);
    console.log(getConfig());
}, { deep: true })

const inputEl = useTemplateRef("inputEl")
async function sendMsg(msg: any, isHidden?: boolean) {
    const newMsg = `检查回答是否符合要求！！！
    ---
    ${msg}`
    msgList.value.push({
        role: "user",
        content: newMsg,
        isHidden: isHidden,
    });
    status.value = STATUS.SENDING;
    let contents = JSON.parse(JSON.stringify(unref(msgList))).map((v: any) => {
        return {
            role: v.role,
            content: v.content,
        }
    })
    msgList.value.push({
        role: "assistant",
        content: "",
        reasoning_content: "",
    });
    try {
        await sendStream(contents as any, (msg: any) => {
            msgList.value[msgList.value.length - 1].reasoning_content = msg.reasoning_content;
            msgList.value[msgList.value.length - 1].content = msg.content;
            if (msg.isComplete) {
                status.value = STATUS.WAITING;
            }
        });
    } catch (error: any) {
        try {
            const text = await error.response.text()
            msgList.value[msgList.value.length - 1].content = text;
        } catch (err) {
            msgList.value[msgList.value.length - 1].content = error.message;
        }
        status.value = STATUS.WAITING;
    }
}
onMounted(() => {
    sendMsg("列举你能的事情,标记顺序，简洁回答。", true)
    inputEl.value?.focus()
})
function handleSubmit() {
    if (status.value === STATUS.SENDING) return
    sendMsg(inputMsg.value)
    inputMsg.value = "";
    nextTick(() => {
        scrollToBottom();
    });
}

function handleDelete(item: { role: string, content: string, reasoning_content?: string }, index: number) {
    if (item.role === 'system') {
        msgList.value[0].content = "";
    } else {
        msgList.value.splice(index, 1);
    }
}

//https://www.codecopy.cn/post/t3clc5
// https://zhuanlan.zhihu.com/p/1948421667379483653#:~:text=Cursor%20%E6%9C%89%E5%BE%88%E5%A4%9A%E5%A5%97%E6%8F%90%E7%A4%BA%E8%AF%8D%EF%BC%8C%E6%AF%8F%E5%A5%97%E6%8F%90%E7%A4%BA%E8%AF%8D%E9%80%82%E7%94%A8%E4%BA%8E%E4%B8%8D%E5%90%8C%E7%9A%84%E5%9C%BA%E6%99%AF%E3%80%82%20%E6%AF%94%E5%A6%82%EF%BC%9A%20Agent%20%E6%A8%A1%E5%BC%8F%E6%8F%90%E7%A4%BA%E8%AF%8D%EF%BC%9A%E8%AE%A9%20AI%20%E8%83%BD%E5%A4%9F%E8%87%AA%E4%B8%BB%E5%9C%B0%E5%88%86%E6%9E%90%E3%80%81%E8%A7%84%E5%88%92%E5%B9%B6%E6%89%A7%E8%A1%8C%E7%BC%96%E7%A0%81%E4%BB%BB%E5%8A%A1%EF%BC%8C%E7%9B%B4%E5%88%B0%E9%97%AE%E9%A2%98%E8%A2%AB%E5%BD%BB%E5%BA%95%E8%A7%A3%E5%86%B3%E3%80%82,Chat%20%E5%AF%B9%E8%AF%9D%E6%8F%90%E7%A4%BA%E8%AF%8D%EF%BC%9A%E9%80%82%E7%94%A8%E4%BA%8E%E4%BB%A5%E5%AF%B9%E8%AF%9D%E9%97%AE%E7%AD%94%E4%B8%BA%E4%B8%BB%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%8C%E8%83%BD%E5%BF%AB%E9%80%9F%E5%93%8D%E5%BA%94%E7%94%A8%E6%88%B7%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%20Memory%20%E5%AF%B9%E8%AF%9D%E8%AE%B0%E5%BF%86%E6%8F%90%E7%A4%BA%E8%AF%8D%EF%BC%9A%E8%AF%84%E4%BC%B0%20AI%20%E7%9A%84%E9%95%BF%E6%9C%9F%E8%AE%B0%E5%BF%86%EF%BC%8C%E4%BF%9D%E8%AF%81%20AI%20%E8%83%BD%E5%A4%9F%E4%BB%8E%E5%8E%86%E5%8F%B2%E4%BA%A4%E4%BA%92%E4%B8%AD%E5%AD%A6%E4%B9%A0%E5%B9%B6%E6%B2%89%E6%B7%80%E9%AB%98%E8%B4%A8%E9%87%8F%E7%9A%84%E9%80%9A%E7%94%A8%E5%81%8F%E5%A5%BD%E8%AE%B0%E5%BF%86%E3%80%82
// https://mcpcn.com/docs/tutorials/building-a-client-node/#%e4%ba%a4%e4%ba%92%e5%bc%8f%e8%81%8a%e5%a4%a9%e7%95%8c%e9%9d%a2
</script>

<template>
    <div class="chat-wrapper">
        <div style="display: flex;gap: 20px;">
            <input type="text" v-model="openaiConfig.model" placeholder="模型">
            <input type="text" v-model="openaiConfig.apiKey" placeholder="apiKey">
            <input type="text" v-model="openaiConfig.baseUrl" placeholder="baseUrl">
            <input type="text" v-model="openaiConfig.temperature" placeholder="temperature">
        </div>
        <div class="chatbox-container" ref="chatboxContainer">
            <div class="chatbox-content" ref="chatboxContent">
                <template v-for="(data, index) in msgList" :key="index">
                    <div class="system-msg" v-if="data.role === 'system' && !data.isHidden">
                        <textarea rows="10" cols="50" v-model="data.content"></textarea>
                    </div>
                    <div v-else-if="!data.isHidden" class="chat-item"
                        :class="{ left: data.role === 'assistant', right: data.role === 'user' }">
                        <div v-if="data.role === 'assistant'" style="display: flex; flex-direction: column; gap: 2px;">
                            <div style="display: flex; gap: 10px;">
                                <div style="width: 50px; height: 50px;flex-shrink: 0;">
                                    <img style="width: 100%; height: 100%;" src="/deepseek.svg" alt="avatar"></img>
                                </div>
                                <div style="padding-top: 5px;">
                                    <div v-if="data.reasoning_content"
                                        style="color: var(--color-fg-muted);padding: 20px;">
                                        <h2 style="font-size: 20px;margin-bottom: 10px;">推理中</h2>
                                        <Msg :msg="data.reasoning_content"></Msg>
                                    </div>
                                    <div>
                                        <Msg :msg="data.content"></Msg>
                                    </div>
                                </div>
                            </div>
                            <div style="display: flex; gap: 10px;margin-left: 60px;">
                                <div @click="handleDelete(data, index)">删除</div>
                            </div>
                        </div>
                        <div v-else style="display: flex; flex-direction: column; gap: 2px;">
                            <div style="display: flex; gap: 10px;flex-direction: row-reverse;">
                                <div style="width: 50px; height: 50px;flex-shrink: 0;">
                                    <img style="width: 100%; height: 100%;" src="/vite.svg" alt="avatar"></img>
                                </div>
                                <div style="padding-top: 5px;">
                                    {{ data.content }}
                                </div>
                            </div>
                            <div style="display: flex; gap: 10px;justify-content: flex-end;margin-right: 60px;">
                                <div @click="handleDelete(data, index)">删除</div>
                            </div>
                        </div>
                    </div>
                </template>
            </div>
        </div>
        <form class="chat-input" @submit.native.prevent="handleSubmit">
            <input ref="inputEl" type="text" v-model="inputMsg" placeholder="请输入内容" class="chat-input-input">
        </form>
    </div>
</template>

<style lang="scss" scoped>
.chat-wrapper {
    padding: 20px;
    box-sizing: border-box;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 10px;
    overflow: hidden;
}

.chat-input {
    .chat-input-input {
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        border: none;
        background: css-var("color-canvas-subtle");
        color: css-var("color-fg-default");
        line-height: 1.5;
        word-break: break-all;
        border-radius: 10px;
        padding: 10px;
        box-sizing: border-box;
        outline: none;
    }
}

.chatbox-container {
    background: css-var("color-canvas-default");
    color: css-var("color-fg-default");
    height: 0;
    flex: 1;
    overflow: auto;
    padding: 10px;
    box-sizing: border-box;
    border-radius: 10px;
    background: css-var("color-canvas-subtle");
    color: css-var("color-fg-default");
    line-height: 1.2;

    .chatbox-content {
        display: flex;
        flex-direction: column;
        gap: 10px;
    }

    .system-msg {
        align-self: center;
        font-size: 12px;
        color: css-var("color-fg-muted");
        line-height: 1.5;
        word-break: break-all;
        padding: 10px;
        width: 50%;
        box-sizing: border-box;
        border-radius: 10px;
        background: css-var("color-canvas-subtle");
        color: css-var("color-fg-default");
        word-break: break-all;
        text-align: center;
    }

    .chat-item {
        max-width: 100%;
        padding: 10px;
        box-sizing: border-box;
        border-radius: 10px;
        background: css-var("color-canvas-subtle");
        color: css-var("color-fg-default");
        line-height: 1.5;
        word-break: break-all;
        position: relative;

        &.left {
            align-self: flex-start;
        }

        &.right {
            // border: css-var("color-border-default") 1px solid;
            align-self: flex-end;
            margin-left: 10%;
        }

        .close-btn {
            position: absolute;
            right: 0;
            top: 0;
            cursor: pointer;
            font-size: 12px;
            color: css-var("color-fg-muted");
            line-height: 1.5;
            padding: 5px;
            box-sizing: border-box;
            border-radius: 5px;
            background: css-var("color-canvas-subtle");
            color: css-var("color-fg-default");
            line-height: 1.5;
            word-break: break-all;
            border: css-var("color-border-default") 1px solid;
            align-self: flex-end;
            margin-left: 10%;
        }
    }
}
</style>
