<script setup lang="ts">
import { ref, computed, nextTick, onMounted } from 'vue'
import { useEditorStore } from '../stores/editorStore'
import { sendAIRequest } from '../composables/useAI'

const store = useEditorStore()
const inputText = ref('')
const loading = ref(false)
const errorMsg = ref('')
const messages = ref<{ role: string; content: string }[]>([])
const chatRef = ref<HTMLDivElement | null>(null)

const mode = ref<'json' | 'code'>('json')

const lastMsg = computed(() => {
  const m = messages.value[messages.value.length - 1]
  if (!m) return ''
  const text = m.role === 'user' ? m.content : m.content.substring(0, 60)
  return text.length > 60 ? text + '...' : text
})

function toggleMode() {
  mode.value = mode.value === 'json' ? 'code' : 'json'
}

function buildMessage(userInput: string): string {
  if (mode.value !== 'json') return `需求: ${userInput}`

  let ctx = `修改文件 ${store.sourcePath}`
  if (store.selectedScene) ctx += `，针对场景节点 ${store.selectedScene.id}`
  ctx += `。需求: ${userInput}`
  return ctx
}

async function send() {
  const userInput = inputText.value.trim()
  if (!userInput || loading.value) return
  inputText.value = ''
  errorMsg.value = ''

  if (!store.deepseekKey) {
    errorMsg.value = '请先在设置中输入 DeepSeek API Key'
    return
  }

  const fullMessage = buildMessage(userInput)
  messages.value.push({ role: 'user', content: userInput })
  loading.value = true

  if (mode.value === 'json') {
    await store.saveVersion('AI 修改前')
  }

  const oldGameData = mode.value === 'json' ? JSON.parse(JSON.stringify(store.gameData)) : undefined

  try {
    const { result, sessionId: newSid } = await sendAIRequest(fullMessage, mode.value, store.deepseekKey, store.aiSessionId || undefined)
    if (newSid) store.setAISessionId(newSid)

    if (mode.value === 'json') {
      messages.value.push({ role: 'assistant', content: result || '已完成' })
      await store.reloadFromDisk(oldGameData)
    } else {
      messages.value.push({ role: 'assistant', content: result || '已完成' })
    }
  } catch (e: any) {
    errorMsg.value = e.message || '请求失败'
  } finally {
    loading.value = false
    await nextTick()
    chatRef.value?.scrollTo({ top: chatRef.value.scrollHeight })
  }
}

function onKeydown(e: KeyboardEvent) {
  if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send() }
}

function newSession() {
  store.clearAISession()
  messages.value = []
  errorMsg.value = ''
}

onMounted(() => {
  store.loadVersions()
})
</script>

<template>
  <div class="ai-panel" v-if="store.showAIPanel">
    <Transition name="slide-up">
      <div v-if="!store.aiCollapsed" class="ai-expanded">
        <div class="ai-exp-header">
          <span class="ai-exp-title">AI 助手</span>
          <div class="ai-exp-actions">
            <button class="ai-mode-btn" @click="toggleMode" :title="mode === 'json' ? '切换到代码模式' : '切换到 JSON 模式'">
              {{ mode === 'json' ? '📋 JSON' : '💻 代码' }}
            </button>
            <button class="ai-new-btn" @click="newSession" title="新建对话">+</button>
            <button v-if="store.aiChanges" class="ai-clear-btn" @click="store.clearAIMarkers()">清除高亮</button>
            <select v-if="store.versions.length > 0" class="ai-version-select" @change="store.restoreVersion(($event.target as HTMLSelectElement).selectedIndex)">
              <option disabled selected>版本</option>
              <option v-for="v in store.versions" :key="v.timestamp">
                {{ new Date(v.timestamp).toLocaleString('zh-CN') }} {{ v.label }}
              </option>
            </select>
            <button class="ai-collapse-btn" @click="store.aiCollapsed = true">▼ 折叠</button>
          </div>
        </div>

        <div class="ai-chat" ref="chatRef">
          <div v-if="!store.deepseekKey" class="ai-key-setup">
            <span class="key-label">DeepSeek API Key</span>
            <input
              class="key-input"
              type="password"
              placeholder="sk-..."
              :value="store.deepseekKey"
              @input="store.setDeepseekKey(($event.target as HTMLInputElement).value)"
            />
            <div class="key-hint">Key 保存在浏览器本地，不会上传到编辑器服务器</div>
          </div>
          <div v-if="messages.length === 0 && store.deepseekKey" class="ai-empty">
            输入你的需求，AI 将根据引擎规范修改配置
          </div>
          <div v-for="(m, i) in messages" :key="i" class="ai-msg" :class="m.role">
            <span class="ai-role">{{ m.role === 'user' ? '👤' : '🤖' }}</span>
            <span class="ai-content">{{ m.content }}</span>
          </div>
          <div v-if="loading" class="ai-msg assistant">
            <span class="ai-role">🤖</span>
            <span class="ai-content loading-dots">正在生成<span class="dots">...</span></span>
          </div>
          <div v-if="errorMsg" class="ai-error">{{ errorMsg }}</div>
        </div>

        <div class="ai-input-area">
          <input
            v-model="inputText"
            class="ai-input"
            placeholder="输入你的需求..."
            :disabled="loading"
            @keydown="onKeydown"
          />
          <button class="ai-send-btn" @click="send" :disabled="loading">发送</button>
        </div>
      </div>
    </Transition>

    <div v-if="store.aiCollapsed" class="ai-collapsed-bar" @click="store.aiCollapsed = false">
      <span class="ai-bar-icon">🤖</span>
      <span class="ai-bar-title">AI 助手</span>
      <span class="ai-bar-divider">·</span>
      <span class="ai-bar-msg">{{ messages.length > 0 ? lastMsg : '点击开始对话' }}</span>
      <span class="ai-bar-arrow">▲</span>
    </div>
  </div>
</template>

<style scoped>
.ai-panel {
  flex-shrink: 0;
  position: relative;
}

.ai-collapsed-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 16px;
  background: #161633;
  border-top: 1px solid rgba(100,200,255,0.1);
  cursor: pointer;
  user-select: none;
  font-size: 12px;
  color: #999;
  transition: background 0.15s;
}
.ai-collapsed-bar:hover {
  background: #1a1a3a;
  color: #bbb;
}

.ai-bar-icon { font-size: 13px; }
.ai-bar-title { font-weight: 500; color: #8cf; }
.ai-bar-divider { color: rgba(255,255,255,0.15); }
.ai-bar-msg { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #777; }
.ai-bar-arrow { color: #555; font-size: 10px; }
.ai-collapsed-bar:hover .ai-bar-arrow { color: #8cf; }

.ai-expanded {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  max-height: 40vh;
  min-height: 200px;
  display: flex;
  flex-direction: column;
  background: rgba(20, 20, 44, 0.98);
  border-top: 1px solid rgba(255,255,255,0.1);
  box-shadow: 0 -6px 24px rgba(0,0,0,0.5);
  z-index: 100;
}

.ai-exp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 16px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  flex-shrink: 0;
}

.ai-exp-title {
  font-size: 14px;
  font-weight: 500;
  color: #ddd;
}

.ai-exp-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

.ai-mode-btn {
  padding: 3px 8px;
  font-size: 11px;
  color: #8cf;
  background: rgba(100,200,255,0.08);
  border: 1px solid rgba(100,200,255,0.2);
  border-radius: 3px;
  cursor: pointer;
}
.ai-mode-btn:hover { background: rgba(100,200,255,0.15); }

.ai-new-btn {
  background: none;
  border: 1px solid rgba(255,255,255,0.1);
  color: #888;
  width: 26px;
  height: 26px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 13px;
}
.ai-new-btn:hover { color: #ddd; border-color: rgba(255,255,255,0.2); }

.ai-clear-btn {
  padding: 3px 8px;
  font-size: 11px;
  color: #ccc;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 3px;
  cursor: pointer;
  white-space: nowrap;
}
.ai-clear-btn:hover { color: #fff; border-color: rgba(255,255,255,0.2); }

.ai-version-select {
  padding: 3px 6px;
  font-size: 11px;
  max-width: 90px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 3px;
  color: #ccc;
  outline: none;
}

.ai-collapse-btn {
  padding: 3px 8px;
  font-size: 11px;
  color: #888;
  background: none;
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 3px;
  cursor: pointer;
}
.ai-collapse-btn:hover { color: #ddd; }

.ai-chat {
  flex: 1;
  overflow-y: auto;
  padding: 10px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 80px;
}

.ai-empty {
  color: #555;
  font-size: 12px;
  text-align: center;
  margin-top: 30px;
}

.ai-msg {
  display: flex;
  gap: 8px;
  font-size: 12px;
  line-height: 1.5;
}

.ai-role {
  flex-shrink: 0;
  font-size: 13px;
}

.ai-msg.user .ai-content {
  color: #8cf;
}

.ai-msg.assistant .ai-content {
  color: #ccc;
}

.loading-dots .dots {
  animation: dotPulse 1.2s infinite;
}

@keyframes dotPulse {
  0%, 20% { opacity: 0; }
  50% { opacity: 1; }
  80%, 100% { opacity: 0; }
}

.ai-error {
  font-size: 12px;
  color: #e74c3c;
  padding: 8px 12px;
  background: rgba(231,76,60,0.1);
  border-radius: 4px;
}

.ai-input-area {
  display: flex;
  gap: 6px;
  padding: 8px 14px 10px;
  border-top: 1px solid rgba(255,255,255,0.06);
  flex-shrink: 0;
}

.ai-input {
  flex: 1;
  padding: 7px 12px;
  font-size: 12px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 4px;
  color: #ddd;
  outline: none;
}
.ai-input:focus { border-color: rgba(255,255,255,0.2); }

.ai-send-btn {
  padding: 7px 14px;
  font-size: 12px;
  color: #fff;
  background: rgba(100,200,255,0.15);
  border: 1px solid rgba(100,200,255,0.25);
  border-radius: 4px;
  cursor: pointer;
}
.ai-send-btn:hover { background: rgba(100,200,255,0.25); }
.ai-send-btn:disabled { opacity: 0.4; cursor: default; }

.ai-key-setup {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 0;
}

.key-label {
  font-size: 13px;
  color: #ccc;
}

.key-input {
  padding: 6px 10px;
  font-size: 12px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 4px;
  color: #ddd;
  outline: none;
}
.key-input:focus { border-color: rgba(100,200,255,0.3); }

.key-hint {
  font-size: 11px;
  color: #666;
}

.slide-up-enter-active,
.slide-up-leave-active {
  transition: max-height 0.25s ease, opacity 0.2s ease;
}
.slide-up-enter-from,
.slide-up-leave-to {
  max-height: 0;
  opacity: 0;
}
</style>
