<script setup lang="ts">
import { ref, onMounted, nextTick } from 'vue'
import OpenAI from 'openai'

// Props：从 App 传入的实时电路状态（完整、可序列化）
// 允许任何结构，但推荐使用你在 App.vue 的 SaveFile 形状
const props = defineProps<{
    state: any
}>()

// 向父组件发出事件：可选，用于保存/载入 AI 偏好设置
const emit = defineEmits<{
    (e: 'error', err: string): void
    (e: 'close'): void
}>()

let client: OpenAI = new OpenAI({
    apiKey: "sk-9aXW6M6V8ddd3d02A3d4T3BLBkFJ8D22a56Efcb14d43b559",
    baseURL: "https://c-z0-api-01.hash070.com/v1",
    dangerouslyAllowBrowser: true
})


// 对话历史（UI 可见）。hasState 用于标记该条消息请求时附带了电路状态
type ChatRole = 'user' | 'assistant' | 'system'
type ChatMessage = { role: ChatRole; content: string; hasState?: boolean }

// 为降低 token 压力，历史消息在发送给模型时会做截断，但 UI 全量保留
const messages = ref<ChatMessage[]>([
    {
        role: 'system',
        content:
            '你是电路虚拟实验室的智能助手。你能阅读用户的电路JSON状态，帮助分析连线是否闭合、元件参数是否合理，解释电压/电流结果，并给出下一步建议。回答保持简洁、条理清晰。'
    }
])
const input = ref('')
const sending = ref(false)

// 把电路状态格式化成简洁摘要（避免无上限增长）
function summarizeState(s: any): string {
    try {
        if (!s) return '无状态'
        const full = JSON.stringify(s)
        // 将完整电路状态作为隐藏的 system 上下文传递
        return `电路状态: ${full}`
    } catch (e) {
        return '状态序列化失败'
    }
}

// 发送问题
async function ask() {
    const question = input.value.trim()
    if (!question) return
    if (!client) {
        emit('error', '请先提供 OpenAI API Key')
        return
    }
    // UI 只展示问题本身，不展示电路 JSON；用 hasState 指示
    const uiMsg: ChatMessage = { role: 'user', content: question, hasState: true }
    messages.value.push(uiMsg)
    input.value = ''
    await nextTick(); scrollToBottom()

    sending.value = true
    try {
        // 构造发送给模型的消息：人格 + 本次完整电路状态 + 近期对话
        const persona = messages.value[0]
        const stateMsg = { role: 'system' as const, content: summarizeState(props.state) }
        const history = messages.value.slice(1).map(m => ({ role: m.role, content: m.content }))
        const recent = history.slice(-10)

        // 流式输出
        const stream = await client.chat.completions.create({
            model: 'gpt-5',
            temperature: 1,
            reasoning_effort: 'minimal',
            stream: true,
            messages: [persona, stateMsg, ...recent]
        })

        const assistantMsg: ChatMessage = { role: 'assistant', content: '' }
        messages.value.push(assistantMsg)
        for await (const part of stream as any) {
            const delta: string = part?.choices?.[0]?.delta?.content ?? ''
            if (delta) assistantMsg.content += delta
            await nextTick(); scrollToBottom()
        }
    } catch (err: any) {
        const msg = err?.message || String(err)
        emit('error', msg)
        messages.value.push({ role: 'assistant', content: `出错：${msg}` })
    } finally {
        sending.value = false
    }
}

// UI：滚动到底
const listRef = ref<HTMLDivElement | null>(null)
function scrollToBottom() {
    const el = listRef.value
    if (!el) return
    el.scrollTop = el.scrollHeight
}

onMounted(() => nextTick(scrollToBottom))
</script>

<template>
    <div class="ai-panel">
        <header class="ai-header">
            <div class="title">AI 助手</div>
            <button class="close-btn" title="关闭" @click="emit('close')">×</button>
        </header>

        <div class="chat-list" ref="listRef">
            <div v-for="(m, i) in messages" :key="i" class="msg" :class="m.role">
                <div class="bubble" v-text="m.content" />
                <div v-if="m.hasState" class="attachments">
                    <span class="chip" title="请求中已附带完整电路状态（不会在聊天中显示）">circuit.json</span>
                </div>
            </div>
        </div>

        <footer class="ai-input">
            <textarea v-model="input" class="q-input" rows="2" :placeholder="sending ? '发送中…' : '询问电路分析、错误排查、参数建议…'"
                :disabled="sending" @keydown.enter.exact.prevent="ask" />
            <button class="send-btn" :disabled="sending" @click="ask">发送</button>
        </footer>
    </div>
</template>

<style scoped>
.ai-panel {
    display: grid;
    grid-template-rows: auto 1fr auto;
    height: 100%;
    border-left: 1px solid #e5e7eb;
    background: #ffffff;
}

.ai-header {
    display: flex;
    gap: 10px;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid #e5e7eb;
    background: #fafafa;
}

.title {
    font-weight: 600;
    color: #111827;
}

.close-btn {
    padding: 4px 8px;
    border: 1px solid #d1d5db;
    border-radius: 6px;
    background: #fff;
    color: #111827;
    cursor: pointer;
    font-weight: 700;
    line-height: 1;
}
.close-btn:hover { background: #f3f4f6; }

.key-box {
    flex: 1;
    display: flex;
    justify-content: flex-end;
}

.key-input {
    min-width: 260px;
    padding: 6px 10px;
    border: 1px solid #d1d5db;
    border-radius: 6px;
    font-size: 12px;
}

.chat-list {
    overflow: auto;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.msg {
    display: flex;
    flex-direction: column;
    max-width: 80%;
    width: fit-content;
}

.msg.system {
    justify-content: center;
    align-self: flex-start;
}

.msg.user {
    justify-content: flex-end;
    align-self: flex-end;
    align-items: flex-end;
}

.msg.assistant {
    justify-content: flex-start;
}

.bubble {
    white-space: pre-wrap;
    padding: 8px 10px;
    border-radius: 10px;
    font-size: 13px;
    line-height: 1.5;
}

.msg.system .bubble {
    background: #eef2ff;
    color: #3730a3;
}

.msg.user .bubble {
    background: #dbeafe;
    color: #1e3a8a;
}

.msg.assistant .bubble {
    background: #f3f4f6;
    color: #111827;
}

.ai-input {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 10px 12px;
    border-top: 1px solid #e5e7eb;
}

.q-input {
    width: 100%;
    resize: vertical;
    min-height: 44px;
    padding: 8px 10px;
    border: 1px solid #d1d5db;
    border-radius: 8px;
    font-size: 13px;
}

.send-btn {
    padding: 8px 12px;
    border: 1px solid #d1d5db;
    border-radius: 8px;
    background: #111827;
    color: #fff;
    font-weight: 600;
    cursor: pointer;
}

.send-btn:disabled {
    opacity: .6;
    cursor: not-allowed;
}

.attachments {
    margin-top: 4px;
}

.chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    font-size: 12px;
    line-height: 1.2;
    border-radius: 999px;
    background: #eef2ff;
    color: #3730a3;
    border: 1px solid #d1d5db;
}
</style>
