<template>
  <div class="chat-page">
    <!-- 消息列表 -->
    <div ref="messagesRef" class="messages">
      <div v-if="messages.length === 0" class="empty-hint">
        <el-icon :size="40" color="#c0c4cc"><ChatDotRound /></el-icon>
        <p>启动服务后开始对话</p>
      </div>
      <div v-for="msg in messages" :key="msg.id" class="bubble-wrap" :class="msg.role">
        <div class="bubble">
          <!-- 推理过程（仅助手消息显示） -->
          <div v-if="msg.parts?.reasoning?.length > 0" class="reasoning-section">
            <div class="reasoning-header" @click="msg.showReasoning = !msg.showReasoning">
              <el-icon :size="14"><ArrowRight v-if="!msg.showReasoning" /><ArrowDown v-else /></el-icon>
              <span>思考过程</span>
            </div>
            <div v-show="msg.showReasoning" class="reasoning-content">
              <div v-for="(r, idx) in msg.parts.reasoning" :key="idx" class="reasoning-item">
                {{ r.text }}
              </div>
            </div>
          </div>
          <!-- 文本内容 -->
          <pre class="bubble-text">{{ msg.text }}</pre>
        </div>
      </div>
    </div>

    <!-- 输入区 -->
    <div class="input-area">
      <el-input
        v-model="inputText"
        type="textarea"
        :autosize="{ minRows: 2, maxRows: 5 }"
        placeholder="输入消息，Ctrl+Enter 发送"
        :disabled="isSending"
        resize="none"
        @keydown.ctrl.enter.prevent="send"
      />
      <el-button type="primary" :disabled="isSending || !inputText.trim()" :loading="isSending" @click="send"> 发送 </el-button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import { ChatDotRound, ArrowRight, ArrowDown } from '@element-plus/icons-vue';
import { useAppStore } from '@/stores/app.js';
import { sseManager } from '@/http/sse.js';
import axios from 'axios';

const route = useRoute();
const router = useRouter();
const appStore = useAppStore();
const isSending = ref(false);
const inputText = ref('');
const messages = ref([]);
const messagesRef = ref(null);
const currentSessionId = ref(null);
const localAssistantMessageIds = new Set();
let unsubscribeCallbacks = [];

// 从路由参数中获取 sessionId
const routeSessionId = computed(() => route.params.id || route.query.sessionId);

// 加载历史消息
async function loadHistoryMessages(sessionId) {
  if (!sessionId) return;
  try {
    const baseUrl = window.__opencodeBaseUrl || 'http://127.0.0.1:4096';
    const requestUrl = `${baseUrl}/session/${sessionId}/message`;
    console.log('[loadHistoryMessages] ========================================');
    console.log('[loadHistoryMessages] 开始获取消息，sessionId:', sessionId);
    console.log('[loadHistoryMessages] 请求URL:', requestUrl);

    const response = await axios.get(requestUrl);
    const messagesData = response.data || [];

    console.log('[loadHistoryMessages] 获取成功！消息数量:', messagesData.length);
    console.log('[loadHistoryMessages] 原始消息数据 (JSON):', JSON.stringify(messagesData, null, 2));
    console.log('[loadHistoryMessages] ========================================');

    // 清空当前消息
    messages.value = [];
    localAssistantMessageIds.clear();
    appStore.clearAssistantMessageIds();

    // 处理历史消息
    messagesData.forEach((item) => {
      const { info, parts } = item;
      if (!info || !parts) return;

      // 按 type 分类存储 parts
      const partsByType = {
        text: [],
        reasoning: [],
        'step-start': [],
        'step-finish': [],
        // 可以在这里添加更多 type
      };

      parts.forEach((part) => {
        if (partsByType.hasOwnProperty(part.type)) {
          partsByType[part.type].push(part);
        } else {
          // 未识别的 type 统一放到 others
          if (!partsByType.others) partsByType.others = [];
          partsByType.others.push(part);
        }
      });

      console.log(`[loadHistoryMessages] 消息 ${info.id} 的 parts 分类:`, partsByType);

      // 提取文本内容（用于展示）
      const text = partsByType.text.map((part) => part.text).join('');

      if (text || info.role === 'assistant') {
        messages.value.push({
          id: info.id,
          role: info.role,
          text: text,
          parts: partsByType, // 存储分类后的 parts，方便后续按 type 渲染
          rawParts: parts, // 保留原始 parts
          showReasoning: false, // 默认折叠推理过程
        });

        // 记录 assistant 消息 ID
        if (info.role === 'assistant') {
          localAssistantMessageIds.add(info.id);
          appStore.addAssistantMessageId(info.id);
        }
      }
    });

    console.log('[loadHistoryMessages] 处理后的消息列表:', messages.value);
    scrollToBottom();
  } catch (err) {
    console.error('加载历史消息失败:', err);
    ElMessage.error(`加载历史消息失败: ${err.message}`);
  }
}

// 监听路由参数变化，加载对应会话
watch(
  routeSessionId,
  async (newSessionId) => {
    if (newSessionId) {
      currentSessionId.value = newSessionId;
      // 等待历史消息加载完毕，避免在 send 时 messages 被清空
      await loadHistoryMessages(newSessionId);

      // 处理从首页带过来的初始消息
      const text = route.query.text;
      if (text) {
        inputText.value = text;
        // 清除 query 中的 text，防止刷新页面时重复发送
        const query = { ...route.query };
        delete query.text;
        router.replace({ query });

        // 触发发送逻辑
        send();
      }

      // 确保 SSE 连接已建立
      if (!appStore.sseConnected) {
        appStore.initSSE();
      }
    }
  },
  { immediate: true }
);

function scrollToBottom() {
  nextTick(() => {
    if (messagesRef.value) {
      messagesRef.value.scrollTop = messagesRef.value.scrollHeight;
    }
  });
}

function upsertAssistantBubble(msgId, text) {
  const existing = messages.value.find((m) => m.id === msgId);
  if (existing) {
    existing.text = text;
  } else {
    messages.value.push({ id: msgId, role: 'assistant', text });
  }
  scrollToBottom();
}

/**
 * 注册 SSE 事件监听器
 */
function registerSSEListeners() {
  // 监听消息部分更新事件
  const unsubscribePartUpdated = sseManager.on('message.part.updated', (data) => {
    const props = data.properties || {};
    const part = props.part;
    if (!part || part.type !== 'text') return;
    if (part.sessionID !== currentSessionId.value) return;
    // 通过 messageID 前缀区分用户/助手消息：只渲染 assistant 消息的 part
    // assistant 消息的 messageID 会在 message.updated 事件中记录，用 localAssistantMessageIds 集合过滤
    if (!localAssistantMessageIds.has(part.messageID) && !appStore.isAssistantMessage(part.messageID)) return;
    upsertAssistantBubble(part.messageID, part.text || '');
  });

  // 监听消息更新事件
  const unsubscribeMessageUpdated = sseManager.on('message.updated', (data) => {
    const props = data.properties || {};
    const info = props.info;
    // 记录 assistant 消息的 ID，供 message.part.updated 过滤使用
    if (info && info.role === 'assistant' && info.sessionID === currentSessionId.value) {
      localAssistantMessageIds.add(info.id);
      appStore.addAssistantMessageId(info.id);
    }
  });

  // 监听会话空闲事件
  const unsubscribeSessionIdle = sseManager.on('session.idle', (data) => {
    const props = data.properties || {};
    // session.idle 表示 AI 响应已全部完成，重置发送状态
    if (props.sessionID === currentSessionId.value) {
      isSending.value = false;
    }
  });

  // 保存取消订阅函数
  unsubscribeCallbacks.push(unsubscribePartUpdated, unsubscribeMessageUpdated, unsubscribeSessionIdle);
}

/**
 * 注销 SSE 事件监听器
 */
function unregisterSSEListeners() {
  unsubscribeCallbacks.forEach((unsubscribe) => {
    if (typeof unsubscribe === 'function') {
      unsubscribe();
    }
  });
  unsubscribeCallbacks = [];
}

async function send() {
  const text = inputText.value.trim();
  if (!text || isSending.value) return;

  // 首次发送时创建会话，使用用户输入的第一条消息作为 title
  if (!currentSessionId.value) {
    try {
      const session = await window.opencode.createSession({ title: text });
      currentSessionId.value = session.id;
    } catch (err) {
      ElMessage.error(`创建会话失败: ${err.message}`);
      return;
    }
  }

  messages.value.push({ id: Date.now(), role: 'user', text });
  inputText.value = '';
  isSending.value = true;
  scrollToBottom();

  try {
    await window.opencode.promptAsync(currentSessionId.value, text);
    // 发送成功后等待 SSE 事件流推送 AI 响应，isSending 由 session.idle 事件重置
  } catch (err) {
    console.error('发送指令失败:', err);
    // 如果是服务未运行，尝试启动服务
    if (appStore.serviceStatus !== appStore.SERVICE_STATUS.RUNNING) {
      ElMessage.info('服务未运行，正在尝试启动...');
      appStore.triggerStartService();
    }
    ElMessage.error(`发送失败: ${err.message}`);
    isSending.value = false;
  }
}

onMounted(() => {
  // 组件挂载时注册 SSE 监听器
  registerSSEListeners();
  // 确保全局 SSE 连接已建立
  if (!appStore.sseConnected) {
    appStore.initSSE();
  }
});

onUnmounted(() => {
  // 组件卸载时注销 SSE 监听器
  unregisterSSEListeners();
});
</script>

<style scoped>
.chat-page {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  gap: 12px;
}

.messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 8px 4px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.empty-hint {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  color: #c0c4cc;
  font-size: 14px;
  margin: auto;
}

.bubble-wrap {
  display: flex;
}

.bubble-wrap.user {
  justify-content: flex-end;
}
.bubble-wrap.assistant {
  justify-content: flex-start;
}

.bubble {
  max-width: 75%;
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 14px;
  line-height: 1.6;
}

.bubble-wrap.user .bubble {
  background: #409eff;
  color: #fff;
  border-bottom-right-radius: 4px;
}

.bubble-wrap.assistant .bubble {
  background: #f0f2f5;
  color: #303133;
  border-bottom-left-radius: 4px;
}

.bubble-text {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
}

.reasoning-section {
  margin-bottom: 8px;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.03);
  overflow: hidden;
}

.reasoning-header {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 10px;
  font-size: 12px;
  color: #666;
  cursor: pointer;
  user-select: none;
  transition: background 0.2s;
}

.reasoning-header:hover {
  background: rgba(0, 0, 0, 0.05);
}

.reasoning-content {
  padding: 0 10px 8px;
}

.reasoning-item {
  font-size: 12px;
  color: #888;
  line-height: 1.5;
  padding: 4px 0;
  border-left: 2px solid #ddd;
  padding-left: 8px;
  margin: 4px 0;
}

.input-area {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  padding: 12px 16px;
  background: #fff;
  border-radius: 10px;
  border: 1px solid #e4e7ed;
}

.input-area .el-textarea {
  flex: 1;
}

.input-area .el-button {
  height: 60px;
  padding: 0 20px;
}
</style>
