<template>
  <div class="ai-container">
    <div class="chat-header">
      <div class="header-content">
        <div class="logo-area">
          <svg class="logo-icon" viewBox="0 0 32 32" fill="none">
            <path d="M16 2L4 9v14l12 7 12-7V9L16 2z" stroke="#6c5ce7" stroke-width="1.5" fill="none"/>
            <path d="M16 2v30M4 9l12 7 12-7" stroke="#6c5ce7" stroke-width="1.5" fill="none"/>
          </svg>
          <span class="logo-text">银盾AI</span>
        </div>
        <div class="header-actions">
          <button class="action-btn" @click="clearChat" title="清空对话">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
            </svg>
          </button>
        </div>
      </div>
    </div>

    <div class="chat-messages" ref="messagesContainer" @click="handleProductClick">
      <div v-for="(msg, idx) in messages" :key="idx" :class="['message', msg.role]">
        <div class="message-avatar">
          <div v-if="msg.role === 'user'" class="user-avatar">U</div>
          <div v-else class="ai-avatar">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
              <path d="M12 2a10 10 0 1 0 10 10 10 10 0 0 0-10-10z"/>
              <path d="M12 6v4M12 16h.01"/>
            </svg>
          </div>
        </div>
        <!-- 产品列表消息直接渲染HTML，其他消息使用markdown -->
        <div class="message-content" v-if="msg.isProductList" v-html="msg.content"></div>
        <div class="message-content" v-else v-html="formatMessage(msg.content)"></div>
      </div>
      <div v-if="isLoading" class="message assistant">
        <div class="message-avatar">
          <div class="ai-avatar typing">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
              <path d="M12 2a10 10 0 1 0 10 10 10 10 0 0 0-10-10z"/>
              <path d="M12 6v4M12 16h.01"/>
            </svg>
          </div>
        </div>
        <div class="message-content">
          <div class="typing-indicator">
            <span></span><span></span><span></span>
          </div>
        </div>
      </div>
      <div ref="messagesEnd"></div>
    </div>

    <div class="chat-input-area">
      <div class="suggestions-area" v-if="suggestions.length || suggestionsLoading">
        <div class="suggestions-header">
          <span class="suggestions-title">💡 你可能想问：</span>
          <button class="refresh-suggestions" @click="refreshSuggestions" :disabled="suggestionsLoading">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M20 2v6h-6M4 12a8 8 0 0 1 16 0 8 8 0 0 1-8 8 8 8 0 0 1-8-8z"/>
              <path d="M12 8v4l3 3"/>
            </svg>
            换一批
          </button>
        </div>
        <div class="suggestions-list">
          <div v-if="suggestionsLoading" class="suggestions-loading">
            <span class="loading-dot"></span><span class="loading-dot"></span><span class="loading-dot"></span>
          </div>
          <template v-else>
            <button
                v-for="(item, idx) in suggestions"
                :key="idx"
                class="suggestion-chip"
                @click="handleSuggestionClick(item.content)"
                :disabled="isLoading"
            >
              {{ item.content }}
            </button>
            <div v-if="!suggestions.length && !suggestionsLoading" class="suggestions-empty">
              暂无推荐，点击换一批
            </div>
          </template>
        </div>
      </div>

      <div class="input-wrapper">
        <textarea
            v-model="question"
            :disabled="isLoading"
            placeholder="请输入问题..."
            @keydown.enter.exact.prevent="sendMessage"
            @keydown.enter.shift.exact="question += '\n'"
            rows="1"
            ref="inputTextarea"
        ></textarea>
        <button class="send-btn" @click="sendMessage" :disabled="isLoading || !question.trim()">
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="22" y1="2" x2="11" y2="13"/>
            <polygon points="22 2 15 22 11 13 2 9 22 2"/>
          </svg>
        </button>
      </div>
      <div class="input-hint">Shift + Enter 换行</div>
    </div>
  </div>
</template>

<script>
import { randList, getFullAnswer, getServiceCardList, startStream, pollContent } from '@/api/ai/ai';
import { marked } from 'marked'
import hljs from 'highlight.js'
import 'highlight.js/styles/github-dark.css'

// ==================== 强化预处理函数：确保表格正确渲染 + 段落分明 ====================
function preprocessMarkdown(text) {
  if (!text) return text;

  const lines = text.split('\n');
  const result = [];
  let inTable = false;
  let tableRows = [];

  const isTableRow = (line) => {
    const trimmed = line.trim();
    // 以 | 开头或结尾，且包含至少一个 |，认为是表格行
    return (trimmed.startsWith('|') || trimmed.endsWith('|')) && trimmed.includes('|');
  };

  const fixTableRow = (row) => {
    // 确保行以 | 开头，以 | 结尾
    let fixed = row.trim();
    if (!fixed.startsWith('|')) fixed = '| ' + fixed;
    if (!fixed.endsWith('|')) fixed = fixed + ' |';
    // 标准化分隔行中的横线
    if (fixed.includes('---') || fixed.includes(':---')) {
      fixed = fixed.replace(/:\-{3,}/g, ':---').replace(/\-{3,}:?/g, '---:').replace(/\-{3,}/g, '---');
      fixed = fixed.replace(/\|/g, ' | ').replace(/\s+/g, ' ').replace(/\|\s*\|\s*/g, '|');
    }
    return fixed;
  };

  const flushTable = () => {
    if (tableRows.length === 0) return;
    // 修复每一行
    const fixedRows = tableRows.map(row => fixTableRow(row));
    // 确保表格前后有空行
    if (result.length > 0 && result[result.length - 1].trim() !== '') {
      result.push('');
    }
    result.push(...fixedRows);
    result.push(''); // 表格后空行
    tableRows = [];
  };

  for (let line of lines) {
    const isRow = isTableRow(line);
    if (isRow) {
      if (!inTable) {
        // 进入表格区域
        inTable = true;
      }
      tableRows.push(line);
    } else {
      if (inTable) {
        flushTable();
        inTable = false;
      }
      result.push(line);
    }
  }
  if (inTable) {
    flushTable();
  }

  let processed = result.join('\n');

  // 将单个换行转换为双换行（段落分隔），但保留表格区域的多行结构（表格行之间是单个\n，marked要求如此）
  // 我们已在表格前后添加了空行，这里只需处理非表格区域
  const nonTablePartRegex = /(?:^|\n\n)(?!\|)(?:.|\n(?!\n|$))+/g;
  processed = processed.replace(nonTablePartRegex, (part) => {
    return part.replace(/([^\n])\n([^\n])/g, '$1\n\n$2');
  });

  return processed;
}

// 配置 marked：关闭 breaks，因为我们已经手动处理了段落（用双换行生成 <p>）
marked.setOptions({
  highlight: function(code, lang) {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(code, { language: lang }).value
    }
    return hljs.highlightAuto(code).value
  },
  breaks: false,    // 不自动转换单个换行，由我们的预处理负责
  gfm: true,
  tables: true,
  mangle: false,
  headerIds: false,
})

export default {
  name: 'Ai',
  data() {
    return {
      question: '',
      messages: [],
      isLoading: false,
      suggestions: [],
      suggestionsLoading: false,
    }
  },
  mounted() {
    this.messages.push({
      role: 'assistant',
      content: '你好！我是 银盾AI助手，有什么可以帮你的吗？'
    })
    this.loadSuggestions()
  },
  methods: {
    scrollToBottom() {
      this.$nextTick(() => {
        const container = this.$refs.messagesContainer
        if (container) {
          container.scrollTop = container.scrollHeight
        }
      })
    },

    async loadSuggestions(randNum = 4) {
      this.suggestionsLoading = true
      try {
        const response = await randList({ randNum })
        if (response.code === 200 && Array.isArray(response.data)) {
          this.suggestions = response.data.map(item => ({
            content: item.content,
            id: item.id,
          }))
        } else {
          console.warn('词条接口返回异常:', response)
          this.suggestions = []
        }
      } catch (error) {
        console.error('加载词条失败:', error)
        this.suggestions = []
      } finally {
        this.suggestionsLoading = false
      }
    },

    refreshSuggestions() {
      if (!this.suggestionsLoading) {
        this.loadSuggestions(4)
      }
    },

    handleSuggestionClick(content) {
      if (this.isLoading) return
      if (content && content.trim()) {
        this.question = content.trim()
        this.sendMessage()
      }
    },

    // 核心渲染：预处理 + marked 解析
    // 在 formatMessage 方法中增加对表格的显式保护
    formatMessage(content) {
      if (!content) return '';
      try {
        // 1. 修复被压缩成一行的表格：在管道符之间合理插入换行
        let fixedContent = content;

        // 检测是否包含表格特征（连续管道符），且缺少换行
        if (fixedContent.includes('|') && !fixedContent.includes('\n|')) {
          // 将 "||" 视为两个单元格之间的分隔，但实际上是两行表格之间的分隔符缺失
          // 更稳妥的方法：根据表头数量推断列数，然后按列数拆分后续数据行
          const lines = fixedContent.split('\n');
          const newLines = [];

          for (let line of lines) {
            // 如果这一行包含表格标记但没有任何换行（即整段表格被压缩在一行）
            if (line.includes('|') && !line.includes('\n')) {
              // 尝试识别表格头部分隔行（例如包含 :--- 或 ---）
              const separatorMatch = line.match(/(?:\|[\s:]*[-:]+[\s:]*)+(?=\|)/);
              if (separatorMatch) {
                const separatorIndex = line.indexOf(separatorMatch[0]);
                // 表头部分（分隔行之前的内容）
                const headerPart = line.substring(0, separatorIndex).trim();
                // 分隔行
                const sepLine = separatorMatch[0];
                // 数据部分（分隔行之后）
                const dataPart = line.substring(separatorIndex + sepLine.length).trim();

                // 将表头按 || 分割成单独的行（注意：|| 表示两行表格之间的连接）
                // 但更常见的是 "||" 出现在数据行之间
                // 重构表格：先将表头行和分隔行加入
                if (headerPart) {
                  newLines.push(headerPart);
                }
                newLines.push(sepLine);

                // 处理数据部分：按 "||" 分割成多行
                const dataRows = dataPart.split('||').filter(row => row.trim() !== '');
                for (let row of dataRows) {
                  newLines.push(row.trim());
                }
              } else {
                // 没有分隔行，无法修复，原样保留
                newLines.push(line);
              }
            } else {
              newLines.push(line);
            }
          }
          fixedContent = newLines.join('\n');
        }

        // 2. 调用原有的预处理函数
        const preprocessed = preprocessMarkdown(fixedContent);
        return marked.parse(preprocessed);
      } catch (e) {
        console.error('Markdown 渲染失败:', e);
        return escapeHtml(content);
      }
    },

    // 生成产品列表 HTML
    buildProductListHtml(productData) {
      if (!productData || !productData.list || !productData.list.length) {
        return '<div class="product-list-empty">暂无产品信息</div>'
      }

      let html = '<div class="product-list">'
      productData.list.forEach(card => {
        const mainImage = card.list && card.list[0]?.itemImg || ''
        const cardCode = card.list && card.list[0]?.cardCode || ''
        const cardName = card.cardName || ''
        const price = card.price || '0'

        html += `
          <div class="product-card" data-product-code="${cardCode}" data-product-name="${cardName}">
            ${mainImage ? `<div class="product-image"><img src="${mainImage}" alt="${cardName}" loading="lazy"></div>` : ''}
            <div class="product-info">
              <div class="product-title">${escapeHtml(cardName)}</div>
              <div class="product-price">¥${parseFloat(price).toFixed(2)}</div>
              <button class="product-buy-btn" data-product-code="${cardCode}" data-product-name="${cardName}">立即购买</button>
            </div>
          </div>
        `
      })
      html += '</div>'
      return html
    },

    async fetchAndShowProducts(userQuestion) {
      this.isLoading = true
      try {
        const response = await getServiceCardList()
        if (response.success && response.data && response.data.list) {
          const productHtml = this.buildProductListHtml(response.data)
          const messageContent = `
            <div class="product-intro">根据您的问题“${escapeHtml(userQuestion)}”，为您推荐以下产品：</div>
            ${productHtml}
          `
          this.messages.push({
            role: 'assistant',
            content: messageContent,
            isProductList: true
          })
        } else {
          this.messages.push({
            role: 'assistant',
            content: '抱歉，获取产品列表失败，请稍后重试。',
            isProductList: false
          })
        }
        this.scrollToBottom()
      } catch (error) {
        console.error('获取产品列表失败:', error)
        this.messages.push({
          role: 'assistant',
          content: '获取产品列表失败，请检查网络后重试。',
          isProductList: false
        })
        this.scrollToBottom()
      } finally {
        this.isLoading = false
      }
    },

    handleProductClick(event) {
      const target = event.target
      let productElement = target.closest('.product-buy-btn') || target.closest('.product-card')
      if (!productElement) return

      let productCode = productElement.dataset.productCode
      if (!productCode) {
        const card = productElement.closest('.product-card')
        if (card) productCode = card.dataset.productCode
      }

      if (productCode) {
        const buyUrl = `https://hoservice.ydhomeoffice.cn/ydMall/productDetail?cardCode=${productCode}`
        window.open(buyUrl, '_blank')
      } else {
        console.warn('缺少产品标识，无法跳转')
      }
    },

    async sendMessage() {
      if (!this.question.trim() || this.isLoading) return;

      const userQuestion = this.question.trim();
      this.messages.push({ role: 'user', content: userQuestion });
      this.question = '';
      this.scrollToBottom();

      this.isLoading = true;
      const assistantMessageIndex = this.messages.length;
      this.messages.push({ role: 'assistant', content: '', isProductList: false });

      try {
        // 1. 启动流式生成，获取 sessionId
        const { startStream } = await import('@/api/ai/ai');
        const sessionId = await startStream(userQuestion);

        // 2. 开始轮询
        const pollInterval = 300; // 毫秒
        const maxPolls = 600;     // 最多轮询 600 次（3分钟）
        let pollCount = 0;

        const poll = async () => {
          try {
            const { pollContent } = await import('@/api/ai/ai');
            const { content, finished } = await pollContent(sessionId);

            // 检查敏感词通知标记
            if (pollCount === 0 && content.includes('__SENSITIVE_NOTIFICATION__')) {
              this.messages.pop();
              await this.fetchAndShowProducts(userQuestion);
              this.isLoading = false;
              return;
            }

            this.messages[assistantMessageIndex].content = content;
            this.scrollToBottom();

            if (finished || pollCount >= maxPolls) {
              this.isLoading = false;
              return;
            }
            pollCount++;
            setTimeout(poll, pollInterval);
          } catch (err) {
            console.error('轮询出错', err);
            this.messages[assistantMessageIndex].content = '❌ 获取内容失败';
            this.isLoading = false;
          }
        };

        poll();
      } catch (error) {
        console.error('启动流式生成失败:', error);
        this.messages[assistantMessageIndex].content = '❌ 请求失败';
        this.isLoading = false;
      }
    },

    clearChat() {
      this.messages = []
      this.messages.push({
        role: 'assistant',
        content: '对话已清空，有什么可以帮你的吗？'
      })
      this.scrollToBottom()
    }
  }
}

// HTML 转义函数
function escapeHtml(str) {
  if (!str) return ''
  return str
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;')
}
</script>

<style scoped>
.ai-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: linear-gradient(135deg, #f5f7fa 0%, #f0f2f5 100%);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

.chat-header {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  padding: 0 24px;
  position: sticky;
  top: 0;
  z-index: 10;
}

.header-content {
  max-width: 900px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 60px;
}

.logo-area {
  display: flex;
  align-items: center;
  gap: 10px;
}

.logo-icon {
  width: 28px;
  height: 28px;
}

.logo-text {
  font-size: 18px;
  font-weight: 600;
  background: linear-gradient(135deg, #6c5ce7, #a855f7);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.action-btn {
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 8px;
  border-radius: 8px;
  color: #666;
  transition: all 0.2s;
}

.action-btn:hover {
  background: #f0f0f0;
  color: #6c5ce7;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  max-width: 1000px;
  margin: 0 auto;
  width: 100%;
}

.message {
  display: flex;
  gap: 12px;
  margin-bottom: 24px;
  animation: fadeIn 0.3s ease;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.message.user {
  flex-direction: row-reverse;
}

.message-avatar {
  flex-shrink: 0;
}

.user-avatar {
  width: 36px;
  height: 36px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 600;
  font-size: 14px;
}

.ai-avatar {
  width: 36px;
  height: 36px;
  background: linear-gradient(135deg, #6c5ce7, #a855f7);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.message-content {
  max-width: 85%;
  padding: 12px 16px;
  border-radius: 18px;
  line-height: 1.6;
  font-size: 15px;
}

.message.user .message-content {
  background: linear-gradient(135deg, #6c5ce7, #7c3aed);
  color: white;
  border-bottom-right-radius: 4px;
}

.message.assistant .message-content {
  background: white;
  color: #2d2d2d;
  border-bottom-left-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

/* 产品列表样式 */
.message-content :deep(.product-list) {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
  margin-top: 12px;
}

.message-content :deep(.product-card) {
  background: #fff;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  transition: transform 0.2s, box-shadow 0.2s;
  cursor: pointer;
  border: 1px solid #f0f0f0;
}

.message-content :deep(.product-card:hover) {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(108, 92, 231, 0.15);
}

.message-content :deep(.product-image) {
  width: 100%;
  height: 160px;
  overflow: hidden;
  background: #f5f5f5;
}

.message-content :deep(.product-image img) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s;
}

.message-content :deep(.product-card:hover .product-image img) {
  transform: scale(1.05);
}

.message-content :deep(.product-info) {
  padding: 12px;
}

.message-content :deep(.product-title) {
  font-size: 15px;
  font-weight: 600;
  color: #1a1a2e;
  margin-bottom: 8px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.message-content :deep(.product-price) {
  font-size: 18px;
  font-weight: 700;
  color: #6c5ce7;
  margin-bottom: 12px;
}

.message-content :deep(.product-buy-btn) {
  width: 100%;
  padding: 8px 0;
  background: linear-gradient(135deg, #6c5ce7, #a855f7);
  border: none;
  border-radius: 24px;
  color: white;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.2s;
}

.message-content :deep(.product-buy-btn:hover) {
  opacity: 0.9;
}

.message-content :deep(.product-intro) {
  font-size: 14px;
  color: #6c757d;
  margin-bottom: 12px;
  padding: 8px 0;
  border-bottom: 1px solid #e9ecef;
}

.message-content :deep(.product-list-empty) {
  text-align: center;
  padding: 32px;
  color: #94a3b8;
  font-size: 14px;
}

.chat-input-area {
  background: white;
  border-top: 1px solid rgba(0, 0, 0, 0.05);
  padding: 16px 24px;
  position: sticky;
  bottom: 0;
}

.suggestions-area {
  max-width: 900px;
  margin: 0 auto 12px auto;
  background: #f8f9fa;
  border-radius: 16px;
  padding: 12px 16px;
  border: 1px solid #e9ecef;
}

.suggestions-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
  font-size: 13px;
  color: #6c757d;
}

.suggestions-title {
  font-weight: 500;
}

.refresh-suggestions {
  display: flex;
  align-items: center;
  gap: 4px;
  background: transparent;
  border: none;
  color: #6c5ce7;
  font-size: 12px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 20px;
  transition: all 0.2s;
}

.refresh-suggestions:hover:not(:disabled) {
  background: rgba(108, 92, 231, 0.1);
}

.refresh-suggestions:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.suggestions-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  min-height: 36px;
}

.suggestion-chip {
  background: white;
  border: 1px solid #e2e8f0;
  border-radius: 24px;
  padding: 6px 14px;
  font-size: 13px;
  color: #2d3748;
  cursor: pointer;
  transition: all 0.2s;
  max-width: 260px;
  white-space: normal;
  word-break: break-word;
  text-align: left;
  line-height: 1.4;
}

.suggestion-chip:hover:not(:disabled) {
  background: #6c5ce7;
  color: white;
  border-color: #6c5ce7;
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(108, 92, 231, 0.2);
}

.suggestion-chip:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

.suggestions-loading {
  display: flex;
  gap: 6px;
  padding: 6px 0;
}

.loading-dot {
  width: 6px;
  height: 6px;
  background: #6c5ce7;
  border-radius: 50%;
  animation: pulse 1.4s infinite ease-in-out;
}

.loading-dot:nth-child(2) { animation-delay: 0.2s; }
.loading-dot:nth-child(3) { animation-delay: 0.4s; }

@keyframes pulse {
  0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); }
  40% { opacity: 1; transform: scale(1); }
}

.suggestions-empty {
  font-size: 12px;
  color: #94a3b8;
  padding: 6px 0;
}

.input-wrapper {
  max-width: 900px;
  margin: 0 auto;
  display: flex;
  align-items: flex-end;
  gap: 12px;
  background: #f8f9fa;
  border-radius: 24px;
  padding: 8px 16px;
  border: 1px solid #e9ecef;
  transition: all 0.2s;
}

.input-wrapper:focus-within {
  border-color: #6c5ce7;
  box-shadow: 0 0 0 3px rgba(108, 92, 231, 0.1);
}

.input-wrapper textarea {
  flex: 1;
  border: none;
  background: transparent;
  padding: 8px 0;
  font-size: 15px;
  resize: none;
  outline: none;
  font-family: inherit;
  max-height: 120px;
  line-height: 1.5;
}

.send-btn {
  background: #6c5ce7;
  border: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: white;
  transition: all 0.2s;
  flex-shrink: 0;
}

.send-btn:hover:not(:disabled) {
  background: #5b4cc4;
  transform: scale(1.02);
}

.send-btn:disabled {
  background: #cbd5e0;
  cursor: not-allowed;
}

.input-hint {
  max-width: 900px;
  margin: 8px auto 0;
  font-size: 12px;
  color: #94a3b8;
  text-align: center;
}

.typing-indicator {
  display: flex;
  gap: 4px;
  padding: 4px 0;
}

.typing-indicator span {
  width: 8px;
  height: 8px;
  background: #6c5ce7;
  border-radius: 50%;
  animation: typing 1.4s infinite;
}

.typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
.typing-indicator span:nth-child(3) { animation-delay: 0.4s; }

@keyframes typing {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
  30% { transform: translateY(-8px); opacity: 1; }
}

/* Markdown 内容样式（包括表格） */
.message-content :deep(h1) {
  font-size: 1.5em;
  font-weight: 600;
  margin: 0.8em 0 0.4em;
  color: #1a1a2e;
}

.message-content :deep(h2) {
  font-size: 1.3em;
  font-weight: 600;
  margin: 0.7em 0 0.35em;
  color: #1a1a2e;
}

.message-content :deep(h3) {
  font-size: 1.1em;
  font-weight: 600;
  margin: 0.6em 0 0.3em;
  color: #1a1a2e;
}

.message-content :deep(p) {
  margin: 0.6em 0;
}

.message-content :deep(code) {
  background-color: #f1f3f5;
  padding: 0.2em 0.4em;
  border-radius: 4px;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 0.9em;
  color: #e83e8c;
}

.message-content :deep(pre) {
  background-color: #1e1e1e;
  padding: 16px;
  border-radius: 12px;
  overflow-x: auto;
  margin: 0.8em 0;
}

.message-content :deep(pre code) {
  background-color: transparent;
  padding: 0;
  color: #d4d4d4;
  font-size: 13px;
  line-height: 1.5;
}

.message-content :deep(ul), .message-content :deep(ol) {
  padding-left: 1.5em;
  margin: 0.6em 0;
}

.message-content :deep(li) {
  margin: 0.25em 0;
}

.message-content :deep(blockquote) {
  border-left: 3px solid #6c5ce7;
  padding-left: 1em;
  margin: 0.8em 0;
  color: #6c757d;
  font-style: italic;
}

/* 表格样式 - 关键修复 */
.message-content :deep(table) {
  border-collapse: collapse;
  width: 100%;
  margin: 1em 0;
  font-size: 14px;
  display: block;
  overflow-x: auto;
}

.message-content :deep(th),
.message-content :deep(td) {
  border: 1px solid #dee2e6;
  padding: 8px 12px;
  text-align: left;
}

.message-content :deep(th) {
  background-color: #f8f9fa;
  font-weight: 600;
}

.message-content :deep(a) {
  color: #6c5ce7;
  text-decoration: none;
}

.message-content :deep(a:hover) {
  text-decoration: underline;
}

.message-content :deep(hr) {
  border: none;
  border-top: 1px solid #e9ecef;
  margin: 1em 0;
}

.message.user .message-content :deep(code) {
  background-color: rgba(255, 255, 255, 0.2);
  color: #ffe0b5;
}

.message.user .message-content :deep(pre) {
  background-color: rgba(0, 0, 0, 0.3);
}

.message.user .message-content :deep(a) {
  color: #ffe0b5;
}

/* 滚动条样式 */
.chat-messages::-webkit-scrollbar {
  width: 6px;
}

.chat-messages::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.chat-messages::-webkit-scrollbar-thumb {
  background: #cbd5e0;
  border-radius: 3px;
}

.chat-messages::-webkit-scrollbar-thumb:hover {
  background: #94a3b8;
}

@media (max-width: 768px) {
  .message-content {
    max-width: 90%;
  }
  .chat-messages {
    max-width: 100%;
    padding: 16px;
  }
}
</style>