<script setup lang="ts">
import { ref } from 'vue'
import {
  ChevronRight,
  Send,
  Sparkles,
  CornerDownLeft,
  Paperclip,
  Smile,
  X,
} from 'lucide-vue-next'
import EmojiPicker from '@/components/chat/EmojiPicker.vue'
import FileMessage from '@/components/chat/FileMessage.vue'
import KnowledgeHudPanel from '@/components/chat/KnowledgeHudPanel.vue'
import KnowledgeSlidePanel from '@/components/chat/KnowledgeSlidePanel.vue'
import KnowledgeHUDPreview from '@/components/chat/KnowledgeHUDPreview.vue'
import OrchestrationPanel from '@/components/chat/OrchestrationPanel.vue'
import KanbanPanel from '@/components/chat/KanbanPanel.vue'
import KanbanDetail from '@/components/chat/KanbanDetail.vue'
import TelemetrySparkline from '@/components/chat/TelemetrySparkline.vue'
import NavShortcutRow from '@/components/navigation/NavShortcutRow.vue'
import DailyDigestCard from '@/components/memory/DailyDigestCard.vue'
import ReminderToast from '@/components/memory/ReminderToast.vue'
import { useChatView } from '@/pages/chat/composables/useChatView'
import { useKnowledgeView } from '@/pages/knowledge/composables/useKnowledgeView'
import { useDailyDigest } from '@/pages/chat/composables/useDailyDigest'
import { useClientTime, formatNetworkRate } from '@/pages/chat/composables/useClientTime'
import { useSidebarPlan } from '@/pages/chat/composables/useSidebarPlan'

// --- Chat view (core messaging logic) ---
const {
  store,
  inputMessage,
  isSending,
  chatContainer,
  inputRef,
  isTyping,
  fileInputRef,
  showEmojiPicker,
  chatModels,
  selectedModelName,
  selectedModel,
  isLoadingModels,
  orchestrationStatus,
  orchestrationInsight,
  activeAgent,
  visitedAgents,
  orchestrationEventFeed,
  systemMeta,
  systemTelemetry,
  sessionTelemetry,
  sendMessage,
  selectConversation,
  newConversation,
  loadConversations,
  formatTime,
  autoResize,
  handleFileSelect,
  insertEmoji,
  openFilePicker,
} = useChatView()

// --- Knowledge view ---
const {
  showNewFolderDialog, newFolderName, createFolder, openNewFolderDialog,
  triggerUpload, handleUpload, uploadInput
} = useKnowledgeView()

// --- Client time & weather ---
const { clientTime, city, weatherIcon, weatherSummary, formatClientDate, formatClientClock } = useClientTime()

// --- Daily digest & reminders ---
const { dailyDigest, digestLoading, activeReminder, reminderVisible, loadDailyDigest, handleSnooze, handleDismiss } = useDailyDigest()

// --- Sidebar plan (calendar, focus, review) ---
const {
  calendarCells, calendarYear, calendarMonth, todayPlanCounters,
  sidebarWeekLabels, sidebarStatusHeadline, sidebarStatusBreakdown,
  sidebarFocusItems, sidebarReviewAchievements, sidebarReviewReflections,
  sidebarFeedItems, topbarFeedItems, sidebarCollapsedModules,
  selectedDate, selectCalendarDate
} = useSidebarPlan(clientTime, loadDailyDigest, store.conversations)

// --- Local UI state ---
const sidebarCollapsed = ref(false)
const orchestrationDrawerOpen = ref(false)
const kanbanDrawerOpen = ref(false)
const kanbanDetailOpen = ref(false)
const kanbanDetailQuadrant = ref<{ id: string; title: string; color: string } | null>(null)
const knowledgeHudOpen = ref(false)
const selectedFolder = ref<any>(null)
const previewDoc = ref<any>(null)

function openOrchestrationDrawer() { orchestrationDrawerOpen.value = true }
function closeOrchestrationDrawer() { orchestrationDrawerOpen.value = false }
function openKanbanDrawer() { kanbanDrawerOpen.value = true }
function closeKanbanDrawer() { kanbanDrawerOpen.value = false }
function openKanbanDetail(quadrantId: string) {
  const quadrantMap: Record<string, { title: string; color: string }> = {
    'urgent-important': { title: '重要且紧急', color: '#f56565' },
    'not-urgent-important': { title: '重要不紧急', color: '#ecc94b' },
    'urgent-not-important': { title: '紧急不重要', color: '#42b9f5' },
    'not-urgent-not-important': { title: '不重要不紧急', color: '#97c950' },
  }
  kanbanDetailQuadrant.value = { id: quadrantId, ...quadrantMap[quadrantId] }
  kanbanDetailOpen.value = true
}
function closeKanbanDetail() { kanbanDetailOpen.value = false }
function openKnowledgeHud() {
  selectedFolder.value = null
  previewDoc.value = null
  knowledgeHudOpen.value = true
}
function closeKnowledgeHud() { knowledgeHudOpen.value = false }
function handleSelectFolder(folder: any) { selectedFolder.value = folder }
function handleOpenPreview(doc: any) { previewDoc.value = doc }

function handleCalendarDateSelect(dateKey: string) {
  selectCalendarDate(dateKey)

  // Reload conversations to get latest data
  loadConversations().then(() => {
    // Find conversation that matches the selected date (by updated_at)
    // Use UTC to avoid timezone issues
    const [year, month, day] = dateKey.split('-').map(Number)
    const targetDateStart = new Date(Date.UTC(year, month - 1, day))
    const targetDateEnd = new Date(Date.UTC(year, month - 1, day + 1))

    // Find conversation that falls on the selected date
    const conversations = store.conversations.value ?? store.conversations
    const conversation = conversations.find((conv) => {
      const convDate = new Date(conv.updated_at)
      return convDate >= targetDateStart && convDate < targetDateEnd
    })

    if (conversation) {
      selectConversation(conversation.id)
    } else {
      // No conversation for this date, create a new one
      newConversation()
    }
  }).catch((err) => {
    console.error('[Calendar] Error loading conversations:', err)
  })
}

// --- Message rendering utilities (kept inline for clarity) ---
function formatUptime(seconds: number) {
  const days = Math.floor(seconds / 86400)
  const hours = Math.floor((seconds % 86400) / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  if (days > 0) return `${days}d ${hours}h ${minutes}m`
  if (hours > 0) return `${hours}h ${minutes}m`
  return `${minutes}m`
}

function currentIp() {
  if (typeof window === 'undefined') return '--'
  return window.location.hostname || '--'
}

function currentPort() {
  if (typeof window === 'undefined') return '--'
  return window.location.port || (window.location.protocol === 'https:' ? '443' : '80')
}

function formatMemoryMb(value: number | null) {
  if (value === null) return '--'
  if (value >= 1024) return `${(value / 1024).toFixed(1)} GB`
  return `${Math.round(value)} MB`
}

function formatDiskGb(value: number) {
  if (value >= 1024) return `${(value / 1024).toFixed(1)} TB`
  return `${value.toFixed(1)} GB`
}

function extractThinkParts(content: string) {
  const thinkPattern = /<think>([\s\S]*?)<\/think>/gi
  const thinkBlocks = Array.from(content.matchAll(thinkPattern))
    .map((match) => match[1]?.trim())
    .filter((block): block is string => Boolean(block))
  const visibleContent = content.replace(thinkPattern, '').trim()
  return { hasThink: thinkBlocks.length > 0, thinkBlocks, visibleContent }
}

function escapeHtml(content: string) {
  return content
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&#39;')
}

function renderInlineMarkdown(content: string) {
  return content
    .replace(/`([^`]+)`/g, '<code>$1</code>')
    .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
    .replace(/\*([^*]+)\*/g, '<em>$1</em>')
}

function isMarkdownTable(lines: string[]) {
  return lines.length >= 2
    && lines[0].includes('|')
    && lines[1].includes('|')
    && lines[1].split('|').filter(Boolean).every((cell) => /^\s*:?-{3,}:?\s*$/.test(cell))
}

function splitTableRow(line: string) {
  return line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|').map((cell) => cell.trim())
}

function renderMarkdown(content: string) {
  const normalizedContent = content.replace(/\\r\\n/g, '\n').replace(/\\n/g, '\n').replace(/\r\n/g, '\n')
  const normalized = escapeHtml(normalizedContent)
  const blocks = normalized.split(/\n\n+/)

  return blocks.map((block) => {
    const trimmed = block.trim()
    if (!trimmed) return ''

    if (/^```[\s\S]*```$/.test(trimmed)) {
      const code = trimmed.replace(/^```\w*\n?/, '').replace(/```$/, '').trimEnd()
      return `<pre class="md-pre"><code>${code}</code></pre>`
    }

    const lines = trimmed.split('\n')

    if (isMarkdownTable(lines)) {
      const [headerLine, , ...bodyLines] = lines
      const headers = splitTableRow(headerLine)
      const thead = `<thead><tr>${headers.map((cell) => `<th>${renderInlineMarkdown(cell)}</th>`).join('')}</tr></thead>`
      const tbody = bodyLines.length
        ? `<tbody>${bodyLines.map((line) => `<tr>${splitTableRow(line).map((cell) => `<td>${renderInlineMarkdown(cell)}</td>`).join('')}</tr>`).join('')}</tbody>`
        : ''
      return `<div class="md-table-wrap"><table class="md-table">${thead}${tbody}</table></div>`
    }

    if (lines.every((line) => /^\s*[-*]\s+/.test(line))) {
      const items = lines.map((line) => `<li>${renderInlineMarkdown(line.replace(/^\s*[-*]\s+/, '').trim())}</li>`).join('')
      return `<ul class="md-list">${items}</ul>`
    }

    if (lines.every((line) => /^\s*\d+\.\s+/.test(line))) {
      const items = lines.map((line) => `<li>${renderInlineMarkdown(line.replace(/^\s*\d+\.\s+/, '').trim())}</li>`).join('')
      return `<ol class="md-list">${items}</ol>`
    }

    if (/^#{1,3}\s+/.test(trimmed)) {
      const level = Math.min((trimmed.match(/^#+/)?.[0].length || 1) + 1, 6)
      const text = trimmed.replace(/^#{1,3}\s+/, '')
      return `<h${level} class="md-heading">${renderInlineMarkdown(text)}</h${level}>`
    }

    return `<p>${renderInlineMarkdown(trimmed).replace(/\n/g, '<br>')}</p>`
  }).join('')
}
</script>

<template>
  <div class="chat-view" :class="{ 'blur-when-modal': kanbanDetailOpen }">
    <!-- Conversation list sidebar -->
    <aside class="conv-sidebar jarvis-sidebar" :class="{ collapsed: sidebarCollapsed }">
      <div v-if="sidebarCollapsed" class="jarvis-sidebar-icon-rail">
        <button
          v-for="module in sidebarCollapsedModules"
          :key="module.id"
          class="jarvis-sidebar-icon-btn"
          type="button"
          :title="module.label"
          :aria-label="module.label"
          @click="module.id === 'kanban' ? openKanbanDrawer() : (sidebarCollapsed = false)"
        >
          <component :is="module.icon" :size="18" />
        </button>
      </div>

      <div v-else class="jarvis-sidebar-scroll">
        <div class="section-label">// DAILY STATUS</div>
        <div class="jarvis-panel jarvis-date-panel">
          <div class="jarvis-date-row">
            <div class="jarvis-date-meta">
              <div class="jarvis-month">{{ clientTime.toLocaleString('en-US', { month: 'long', year: 'numeric' }) }}</div>
              <div class="jarvis-time">{{ clientTime.toLocaleTimeString('en-US', { hour12: true }) }}</div>
            </div>
            <div class="jarvis-location">
              <div class="location-info">
                <span class="location-name">{{ city }}</span>
                <span class="location-weather-text">{{ weatherSummary }}</span>
              </div>
              <i :class="['wi', weatherIcon, 'location-icon']"></i>
            </div>
          </div>

          <div class="jarvis-calendar">
            <div class="calendar-header">
              <span v-for="item in sidebarWeekLabels" :key="item.label" :class="{ 'is-weekend': item.isWeekend }">{{ item.label }}</span>
            </div>
            <div class="calendar-grid">
              <span
                v-for="cell in calendarCells"
                :key="cell.key"
                class="calendar-day"
                :class="{ active: cell.active, busy: cell.busy, muted: cell.value === null, selected: cell.selected, clickable: cell.active || cell.hasConversation }"
                @click="(cell.active || cell.hasConversation) && handleCalendarDateSelect(cell.key)"
              >
                {{ cell.value ?? '' }}
                <span v-if="cell.hasConversation" class="conv-indicator"></span>
              </span>
            </div>
          </div>

        </div>

        <div class="jarvis-panel jarvis-plan-panel" @click="openKanbanDrawer" style="cursor: pointer;">
          <div class="jarvis-section-title">TODAY'S STATUS</div>
          <div class="jarvis-status-shell">
            <div class="jarvis-progress-ring" :style="{ '--completion': `${todayPlanCounters.completion}%` }">
              <div class="jarvis-progress-core">
                <strong>{{ todayPlanCounters.completion }}%</strong>
                <span>COMPLETION</span>
              </div>
            </div>

            <div class="jarvis-status-copy">
              <div v-if="sidebarStatusHeadline" class="jarvis-status-headline">
                {{ sidebarStatusHeadline }}
              </div>
              <ul class="jarvis-status-list">
                <li v-for="item in sidebarStatusBreakdown" :key="item.key" class="jarvis-status-item" :class="{ 'is-total': item.key === 'total' }">
                  <span class="status-dot" :class="item.tone"></span>
                  <span class="status-label">{{ item.label }}</span>
                  <strong class="status-value">{{ item.value }}</strong>
                </li>
              </ul>
            </div>
          </div>
        </div>

        <div class="jarvis-panel jarvis-focus-panel">
          <div class="jarvis-section-title">TODAY'S FOCUS</div>
          <ul v-if="sidebarFocusItems.length > 0" class="jarvis-focus-list">
            <li v-for="(item, index) in sidebarFocusItems" :key="item.id" class="jarvis-focus-item" :class="`is-${item.tone}`">
              <span class="focus-order" :class="{ 'is-done': item.tone === 'done' }">
                <span v-if="item.tone === 'done'" class="focus-check">✓</span>
                <span v-else>{{ String(index + 1).padStart(2, '0') }}</span>
              </span>
              <div class="focus-copy">
                <div class="focus-label">{{ item.label }}</div>
                <div class="focus-title" :class="{ 'is-done': item.tone === 'done' }">{{ item.title }}</div>
                <div class="focus-meta">{{ item.meta }}</div>
              </div>
            </li>
          </ul>
          <div v-else class="jarvis-empty-state">&#x6682;&#x65E0;&#x4ECA;&#x65E5;&#x91CD;&#x70B9;&#xFF0C;&#x7B49;&#x5F85;&#x65E5;&#x7A0B;&#x4E2D;&#x5FC3;&#x8FD4;&#x56DE;&#x6570;&#x636E;&#x3002;</div>
        </div>

        <div class="jarvis-panel jarvis-review-panel">
          <div class="jarvis-section-title">MONTHLY REVIEW</div>
          <div class="jarvis-review-group">
            <div class="jarvis-review-subtitle">ACHIEVEMENTS</div>
            <ul class="jarvis-review-list">
              <li v-for="item in sidebarReviewAchievements" :key="item" class="jarvis-review-item">{{ item }}</li>
            </ul>
          </div>
          <div class="jarvis-review-group">
            <div class="jarvis-review-subtitle">REFLECTIONS</div>
            <ul class="jarvis-review-list reflection">
              <li v-for="item in sidebarReviewReflections" :key="item" class="jarvis-review-item">{{ item }}</li>
            </ul>
          </div>
        </div>

      </div>
    </aside>

    <!-- Chat area -->
    <section class="chat-area">
      <div class="chat-shell">
        <div class="chat-main">
          <!-- Top bar -->
          <div class="chat-topbar">
            <div class="chat-shortcuts">
              <NavShortcutRow
                @select-folder="handleSelectFolder"
                @open-knowledge-hud="openKnowledgeHud"
              />
            </div>
            <div class="chat-model-panel">
              <label class="chat-model-label" for="chat-model-select">
                <Sparkles :size="12" />
                <span>MODEL</span>
              </label>
              <div class="chat-model-display">
                <Sparkles :size="12" />
                <span>{{ selectedModel?.model || selectedModelName || 'Default' }}</span>
              </div>
            </div>
          </div>

          <div class="chat-intel-strip" v-if="sidebarFeedItems.length > 0">
            <div class="chat-intel-label">RSS NEWS</div>
            <div class="chat-intel-marquee">
              <div class="chat-intel-track">
                <span v-for="(item, index) in topbarFeedItems" :key="`${item.id}-${index}`" class="chat-intel-item">
                  <span class="chat-intel-item-meta">{{ item.meta }}</span>
                  <span class="chat-intel-item-title">{{ item.title }}</span>
                </span>
              </div>
            </div>
          </div>

          <!-- Messages -->
          <div ref="chatContainer" class="messages-area">
            <!-- Welcome screen -->
            <div v-if="store.messages.length === 0" class="welcome-screen">
              <div class="welcome-icon">
                <div class="welcome-ring r1"></div>
                <div class="welcome-ring r2"></div>
                <div class="welcome-ring r3"></div>
                <div class="welcome-core">
                  <Sparkles :size="28" />
                </div>
              </div>
              <div class="welcome-title">JARVIS</div>
              <div class="welcome-sub">Strategic Thinking Partner</div>
              <div class="welcome-hint">把目标给我，我先帮您收束重点，再往下推进。</div>
            </div>

            <!-- Daily Digest Card -->
            <DailyDigestCard
              v-if="dailyDigest"
              :digest="dailyDigest"
              :loading="digestLoading"
            />

            <!-- Message bubbles -->
            <div
              v-for="(msg, i) in store.messages"
              :key="msg.id"
              class="message-row"
              :class="msg.role"
              :style="{ animationDelay: `${i * 30}ms` }"
            >
              <div class="msg-avatar">
                <span v-if="msg.role === 'user'">{{ '>' }}</span>
                <span v-else class="ai-icon">J</span>
              </div>
              <div class="msg-content">
                <div class="msg-meta">
                  <span class="msg-role">{{ msg.role === 'user' ? 'YOU' : 'JARVIS' }}</span>
                  <span v-if="msg.role === 'assistant' && msg.model" class="msg-model">{{ msg.model }}</span>
                  <span class="msg-time">{{ formatTime(msg.created_at) }}</span>
                </div>
                <template v-if="msg.role === 'assistant' && extractThinkParts(msg.content).hasThink">
                  <details class="think-panel">
                    <summary class="think-summary">
                      <span class="think-chip">
                        <span class="think-chip-dot"></span>
                        <span>THINK</span>
                      </span>
                    </summary>
                    <div class="think-content">
                      <div
                        v-for="(block, index) in extractThinkParts(msg.content).thinkBlocks"
                        :key="index"
                        class="think-block"
                        v-html="renderMarkdown(block)"
                      ></div>
                    </div>
                  </details>
                  <div
                    v-if="extractThinkParts(msg.content).visibleContent"
                    class="msg-bubble markdown-body"
                    v-html="renderMarkdown(extractThinkParts(msg.content).visibleContent)"
                  ></div>
                </template>
                <div v-else class="msg-bubble markdown-body" v-html="renderMarkdown(msg.content)"></div>
                <div v-if="msg.role === 'user' && msg.attachments?.length" class="msg-attachments">
                  <FileMessage
                    v-for="att in msg.attachments"
                    :key="att.id"
                    :filename="att.name"
                    :file-type="att.type"
                    :file-size="att.size"
                  />
                </div>
              </div>
            </div>

            <div v-if="isTyping" class="message-row assistant thinking-row">
              <div class="msg-avatar">
                <span class="ai-icon">J</span>
              </div>
              <div class="msg-content">
                <div class="msg-meta">
                  <span class="msg-role">JARVIS</span>
                  <span class="msg-model">thinking</span>
                </div>
                <div class="msg-bubble thinking-bubble">
                  <div class="thinking-hud">
                    <div class="thinking-core">
                      <span class="thinking-ring ring-1"></span>
                      <span class="thinking-ring ring-2"></span>
                      <span class="thinking-ring ring-3"></span>
                      <span class="thinking-dot"></span>
                    </div>
                    <div class="thinking-copy">
                      <div class="thinking-title">JARVIS THINKING</div>
                      <div class="thinking-subtitle">正在分析请求并准备响应</div>
                    </div>
                    <div class="typing-inline" aria-hidden="true">
                      <span class="dot"></span>
                      <span class="dot"></span>
                      <span class="dot"></span>
                    </div>
                  </div>
                </div>
              </div>
            </div>

          </div>

          <!-- Top buttons above input -->
          <div class="top-buttons-row">
            <button class="top-action-btn" @click="$router.push('/temple')" title="Temple">
              <span class="btn-icon temple-icon">◈</span>
            </button>
            <button class="top-action-btn" @click="$router.push('/knowledge')" title="Knowledge">
              <span class="btn-icon knowledge-icon">◉</span>
            </button>
            <button class="top-action-btn" @click="$router.push('/war-room')" title="War Room">
              <span class="btn-icon war-icon">⬡</span>
            </button>
          </div>

          <!-- Input area -->
          <div class="input-area">
            <div class="input-frame">
              <div class="input-corners tl"></div>
              <div class="input-corners tr"></div>
              <div class="input-corners bl"></div>
              <div class="input-corners br"></div>
              <textarea
                ref="inputRef"
                v-model="inputMessage"
                placeholder="输入指令，按 Enter 发送..."
                :disabled="isSending"
                rows="1"
                @keydown.enter.exact.prevent="sendMessage"
                @input="autoResize"
              ></textarea>
              <input
                ref="fileInputRef"
                type="file"
                multiple
                accept=".jpg,.jpeg,.png,.gif,.webp,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt"
                style="display: none"
                @change="handleFileSelect"
              />
              <button class="attach-btn" @click="openFilePicker" title="上传文件">
                <Paperclip :size="15" />
              </button>
              <div class="emoji-wrapper">
                <button
                  class="emoji-btn"
                  :class="{ active: showEmojiPicker }"
                  @click="showEmojiPicker = !showEmojiPicker"
                  title="表情包"
                >
                  <Smile :size="15" />
                </button>
                <EmojiPicker
                  :visible="showEmojiPicker"
                  @select="insertEmoji"
                  @close="showEmojiPicker = false"
                />
              </div>
              <button
                class="send-btn"
                :class="{ active: inputMessage.trim() }"
                :disabled="!inputMessage.trim() || isSending"
                @click="sendMessage"
              >
                <Send :size="15" />
                <CornerDownLeft :size="12" class="enter-hint" />
              </button>
            </div>
            <div class="input-hints">
              <span class="hint-item">ENTER 发送</span>
              <span class="hint-sep">|</span>
              <span class="hint-item">SHIFT+ENTER 换行</span>
            </div>
          </div>
        </div>

        <aside class="runtime-sidebar">
          <div class="sidebar-runtime-panel" :class="`is-${orchestrationStatus}`">
            <div class="section-label">// RUNTIME STATUS</div>
            <div class="runtime-meta-panel runtime-meta-panel-merged">
              <div class="runtime-panel-title">SYSTEM</div>
              <div class="runtime-meta-item">
                <span class="runtime-meta-key">OS</span>
                <span class="runtime-meta-value">{{ systemMeta.systemName }}</span>
              </div>
              <div class="runtime-meta-item">
                <span class="runtime-meta-key">VERSION</span>
                <span class="runtime-meta-value">{{ systemMeta.systemVersion }}</span>
              </div>
              <div class="runtime-meta-item">
                <span class="runtime-meta-key">IP</span>
                <span class="runtime-meta-value">{{ currentIp() }}</span>
              </div>
              <div class="runtime-meta-item">
                <span class="runtime-meta-key">PORT</span>
                <span class="runtime-meta-value">{{ currentPort() }}</span>
              </div>
              <div class="runtime-meta-item">
                <span class="runtime-meta-key">UPTIME</span>
                <span class="runtime-meta-value">{{ formatUptime(systemMeta.uptimeSeconds) }}</span>
              </div>
            </div>
            <div class="runtime-grid">
              <div class="runtime-card cpu-card">
                <div class="runtime-topline">
                  <span class="runtime-label">CPU</span>
                  <span class="runtime-value">{{ systemTelemetry.cpu.online && systemTelemetry.cpu.current !== null ? `${systemTelemetry.cpu.current}%` : 'OFFLINE' }}</span>
                </div>
                <TelemetrySparkline :points="systemTelemetry.cpu.series" stroke="#22d3ee" fill="rgba(34, 211, 238, 0.16)" />
              </div>
              <div class="runtime-card gpu-card">
                <div class="runtime-topline">
                  <span class="runtime-label">GPU</span>
                  <span class="runtime-value">{{ systemMeta.gpuUtilPercent !== null ? `${Math.round(systemMeta.gpuUtilPercent)}%` : 'N/A' }}</span>
                </div>
                <div class="gpu-info-stats">
                  <div class="gpu-info-row">
                    <span class="gpu-info-key">DEVICE</span>
                    <span class="gpu-info-value gpu-info-copy">{{ systemMeta.gpuName || 'GPU unavailable' }}</span>
                  </div>
                  <div class="gpu-info-row">
                    <span class="gpu-info-key">VRAM</span>
                    <span class="gpu-info-value">{{ formatMemoryMb(systemMeta.gpuMemoryUsedMb) }} / {{ formatMemoryMb(systemMeta.gpuMemoryTotalMb) }}</span>
                  </div>
                </div>
                <TelemetrySparkline
                  :points="systemTelemetry.gpu.series"
                  stroke="#f472b6"
                  fill="rgba(244, 114, 182, 0.16)"
                />
              </div>
              <div class="runtime-card mem-card">
                <div class="runtime-topline">
                  <span class="runtime-label">MEM</span>
                  <span class="runtime-value">{{ systemTelemetry.memory.online && systemTelemetry.memory.current !== null ? `${systemTelemetry.memory.current}%` : 'OFFLINE' }}</span>
                </div>
                <TelemetrySparkline :points="systemTelemetry.memory.series" stroke="#a78bfa" fill="rgba(167, 139, 250, 0.14)" />
              </div>
              <div class="runtime-card disk-card">
                <div class="runtime-topline">
                  <span class="runtime-label">DISK</span>
                  <span class="runtime-value">{{ systemTelemetry.disk.online && systemTelemetry.disk.current !== null ? `${systemTelemetry.disk.current}%` : 'OFFLINE' }}</span>
                </div>
                <div class="gpu-info-stats">
                  <div class="gpu-info-row">
                    <span class="gpu-info-key">CAPACITY</span>
                    <span class="gpu-info-value">{{ `${formatDiskGb(systemMeta.diskUsedGb)} / ${formatDiskGb(systemMeta.diskTotalGb)}` }}</span>
                  </div>
                </div>
                <TelemetrySparkline :points="systemTelemetry.disk.series" stroke="#4ade80" fill="rgba(74, 222, 128, 0.14)" />
              </div>
              <div class="runtime-card network-card">
                <div class="runtime-topline">
                  <span class="runtime-label">NETWORK</span>
                  <span class="runtime-value">{{ systemTelemetry.network.upload.online ? 'LIVE' : 'OFFLINE' }}</span>
                </div>
                <div class="network-metric-head">
                  <div class="network-legend">
                    <span class="network-direction up">↑</span>
                    <span class="network-speed up">{{ formatNetworkRate(systemTelemetry.network.upload.current, systemTelemetry.network.upload.online) }}</span>
                  </div>
                  <div class="network-legend">
                    <span class="network-direction down">↓</span>
                    <span class="network-speed down">{{ formatNetworkRate(systemTelemetry.network.download.current, systemTelemetry.network.download.online) }}</span>
                  </div>
                </div>
                <div class="network-overlay-chart">
                  <TelemetrySparkline :points="systemTelemetry.network.upload.series" stroke="#2563eb" fill="rgba(37, 99, 235, 0.10)" />
                  <TelemetrySparkline :points="systemTelemetry.network.download.series" stroke="#38bdf8" fill="rgba(56, 189, 248, 0.06)" />
                </div>
              </div>
            </div>
          </div>
          <div class="runtime-sidebar-footer">
            <button class="event-feed runtime-feed runtime-feed-launch" type="button" @click="openOrchestrationDrawer">
              <div class="feed-hero">
                <div class="feed-title">Recent Events</div>
                <div class="feed-hero-meta">
                  <div class="runtime-log-count">{{ orchestrationEventFeed.length }}</div>
                  <ChevronRight :size="16" class="feed-launch-arrow" />
                </div>
              </div>
            </button>
          </div>
        </aside>
        <div class="knowledge-hud-shell" :class="{ open: knowledgeHudOpen }">
          <button
            v-if="knowledgeHudOpen"
            class="knowledge-hud-backdrop"
            type="button"
            aria-label="Close knowledge HUD"
            @click="closeKnowledgeHud"
          ></button>
          <section class="knowledge-hud" :class="{ open: knowledgeHudOpen }">
            <div class="knowledge-hud-frame">
              <div class="knowledge-hud-chrome">
                <div class="knowledge-hud-title">
                  <Database :size="14" />
                  <span>KNOWLEDGE ARCHIVE HUD</span>
                </div>
                <button class="knowledge-hud-close" type="button" aria-label="Close knowledge HUD" @click="closeKnowledgeHud">
                  <X :size="16" />
                </button>
              </div>
              <div class="knowledge-hud-body">
                <KnowledgeHudPanel />
              </div>
            </div>
          </section>
        </div>

        <div class="agent-drawer-shell" :class="{ open: orchestrationDrawerOpen }">
          <button
            v-if="orchestrationDrawerOpen"
            class="agent-drawer-backdrop"
            type="button"
            aria-label="Close agent drawer"
            @click="closeOrchestrationDrawer"
          ></button>
          <aside class="agent-drawer" :class="{ open: orchestrationDrawerOpen }">
            <OrchestrationPanel
              :visible="true"
              :status="orchestrationStatus"
              :insight="orchestrationInsight"
              :active-agent="activeAgent"
              :visited-agents="visitedAgents"
              :events="orchestrationEventFeed"
              :system-telemetry="{
                cpu: systemTelemetry.cpu,
                memory: systemTelemetry.memory,
                disk: systemTelemetry.disk,
              }"
              :session-telemetry="sessionTelemetry"
            />
          </aside>
        </div>

        <!-- Kanban Drawer (四象限任务管理) -->
        <div class="kanban-drawer-shell" :class="{ open: kanbanDrawerOpen }">
          <button
            v-if="kanbanDrawerOpen"
            class="kanban-drawer-backdrop"
            type="button"
            aria-label="Close kanban"
            @click="closeKanbanDrawer"
          ></button>
          <aside class="kanban-drawer" :class="{ open: kanbanDrawerOpen }">
            <KanbanPanel
              :visible="kanbanDrawerOpen"
              @close="closeKanbanDrawer"
              @open-detail="openKanbanDetail"
            />
          </aside>
        </div>

        <!-- Kanban Detail Modal (Teleported to body to avoid blur) -->
        <Teleport to="body">
          <KanbanDetail
          v-if="kanbanDetailQuadrant"
          :visible="kanbanDetailOpen"
          :quadrant-id="kanbanDetailQuadrant.id"
          :quadrant-title="kanbanDetailQuadrant.title"
          :quadrant-color="kanbanDetailQuadrant.color"
          @close="closeKanbanDetail"
        />
        </Teleport>

        <!-- Knowledge Side Panel (Phase 02) -->
        <Transition name="slide">
          <KnowledgeSlidePanel 
            v-if="selectedFolder" 
            :folder="selectedFolder" 
            @close="selectedFolder = null"
            @open-preview="handleOpenPreview"
            @trigger-new-folder="openNewFolderDialog"
            @trigger-upload="triggerUpload"
          />
        </Transition>

        <!-- Knowledge HUD Preview (Phase 03) -->
        <Transition name="fade">
          <KnowledgeHUDPreview 
            v-if="previewDoc" 
            :doc="previewDoc" 
            @close="previewDoc = null"
          />
        </Transition>

        <!-- Global Dialogs for Knowledge -->
        <input ref="uploadInput" type="file" class="hidden-upload" accept=".pdf,.md,.txt,.doc,.docx,.csv,.xlsx" @change="handleUpload" />

        <!-- Reminder Toast -->
        <ReminderToast
          :reminder="activeReminder"
          :visible="reminderVisible"
          @snooze="handleSnooze"
          @dismiss="handleDismiss"
        />

        <div v-if="showNewFolderDialog" class="knowledge-hud-preview" @click.self="showNewFolderDialog = false">
          <div class="hud-dialog-jarvis">
            <div class="dialog-header-tech">
              <span class="sub-kicker">INIT_NODE_PROCEDURE</span>
              <button class="close-jarvis-btn small" @click="showNewFolderDialog = false"><X :size="14" /></button>
            </div>
            <div class="dialog-body-tech">
              <p class="dialog-label">ENTER_VIRTUAL_ADDRESS_NAME</p>
              <input v-model="newFolderName" class="jarvis-input" placeholder="SECTOR_NAME..." @keyup.enter="createFolder" autofocus />
            </div>
            <div class="dialog-actions-tech">
              <button class="action-btn-jarvis small" @click="showNewFolderDialog = false">ABORT</button>
              <button class="action-btn-jarvis amber small" @click="createFolder">INITIALIZE</button>
            </div>
          </div>
        </div>
        </div>
        </section>
        </div>
        </template>

        <style scoped src="./chatPage.css">
        </style>
