<template>
  <transition name="personal-page-fade">
    <div
      class="personal-page-overlay"
      v-if="visible"
      @mousedown.self="personalization.handleOverlayPressStart($event)"
      @mouseup.self="personalization.handleOverlayPressEnd"
      @mouseleave.self="personalization.handleOverlayPressCancel"
      @touchstart.self.prevent="personalization.handleOverlayPressStart($event)"
      @touchend.self.prevent="personalization.handleOverlayPressEnd"
      @touchcancel.self="personalization.handleOverlayPressCancel"
    >
      <div class="personal-page-card">
        <div class="personal-page-header">
          <div>
            <h2>个人空间</h2>
            <p>配置 AI 智能体的个性化偏好</p>
          </div>
          <div class="personal-page-actions">
            <button type="button" class="personal-page-logout" @click="personalization.logout()">退出登录</button>
            <button type="button" class="personal-page-close" @click="personalization.closeDrawer()">返回工作区</button>
          </div>
        </div>
        <div class="personalization-body" v-if="!loading">
          <form class="personal-form" @submit.prevent="personalization.save()">
            <div class="personalization-layout">
              <nav class="personal-page-tabs" aria-label="个人空间分组切换">
                <button
                  v-for="tab in personalTabs"
                  :key="tab.id"
                  type="button"
                  class="personal-tab-button"
                  :class="{ active: activeTab === tab.id }"
                  :aria-pressed="activeTab === tab.id"
                  @click.prevent="setActiveTab(tab.id)"
                >
                  <span>{{ tab.label }}</span>
                  <small v-if="tab.description" class="personal-tab-desc">{{ tab.description }}</small>
                </button>
              </nav>
              <div class="personalization-content-shell">
                <div
                  class="personalization-content"
                  @touchstart.passive="handleSwipeStart"
                  @touchend.passive="handleSwipeEnd"
                >
                  <transition name="personal-page-vertical" mode="out-in">
                    <section v-if="activeTab === 'preferences'" key="preferences" class="personal-page personal-page-pref">
                    <div class="personal-toggle-row">
                      <label class="personal-toggle">
                        <span class="toggle-text">
                          <span class="toggle-title">启用个性化提示</span>
                          <span class="toggle-desc">开启后才会注入您的偏好</span>
                        </span>
                        <span class="toggle-switch">
                          <input
                            type="checkbox"
                            :checked="form.enabled"
                            :disabled="toggleUpdating"
                            @change="personalization.toggleEnabled()"
                          />
                          <span class="switch-slider"></span>
                        </span>
                      </label>
                    </div>
                    <p class="section-note">仅作用于当前工作区，可随时在左下角开关。</p>
                    <div class="personalization-sections">
                      <div class="personal-left-column">
                        <div class="personal-section personal-info">
                          <label class="personal-field">
                            <span>您希望AI智能体怎么自称？</span>
                            <input
                              type="text"
                              placeholder="如：小秘、助理小A"
                              :value="form.self_identify"
                              maxlength="20"
                              @input="personalization.updateField({ key: 'self_identify', value: $event.target.value })"
                              @focus="personalization.clearFeedback()"
                            />
                          </label>
                          <label class="personal-field">
                            <span>您希望AI智能体怎么称呼您？</span>
                            <input
                              type="text"
                              placeholder="如：Jojo、老师"
                              :value="form.user_name"
                              maxlength="20"
                              @input="personalization.updateField({ key: 'user_name', value: $event.target.value })"
                              @focus="personalization.clearFeedback()"
                            />
                          </label>
                          <label class="personal-field">
                            <span>您的职业是？</span>
                            <input
                              type="text"
                              placeholder="如：产品经理、设计师"
                              :value="form.profession"
                              maxlength="20"
                              @input="personalization.updateField({ key: 'profession', value: $event.target.value })"
                              @focus="personalization.clearFeedback()"
                            />
                          </label>
                          <div class="personal-field">
                            <label>
                              <span>您希望AI智能体用何种语气与您交流？</span>
                              <input
                                type="text"
                                placeholder="请选择或输入语气"
                                :value="form.tone"
                                maxlength="20"
                                @input="personalization.updateField({ key: 'tone', value: $event.target.value })"
                                @focus="personalization.clearFeedback()"
                              />
                            </label>
                            <div class="tone-preset-row">
                              <span>快速填入：</span>
                              <div class="tone-preset-buttons">
                                <button type="button" v-for="preset in tonePresets" :key="preset" @click.prevent="personalization.applyTonePreset(preset)">
                                  {{ preset }}
                                </button>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                      <div class="personal-right-column">
                        <div class="personal-section personal-considerations">
                          <div class="personal-field">
                            <span>您希望AI智能体在回答问题时必须考虑的信息是？</span>
                            <div class="consideration-input">
                              <input
                                type="text"
                                :value="newConsideration"
                                maxlength="50"
                                placeholder="输入后点击 + 号添加"
                                @input="personalization.updateNewConsideration($event.target.value)"
                                @focus="personalization.clearFeedback()"
                              />
                              <button
                                type="button"
                                class="consideration-add"
                                :disabled="!newConsideration || form.considerations.length >= maxConsiderations"
                                @click="personalization.addConsideration()"
                              >
                                +
                              </button>
                            </div>
                            <ul class="consideration-list" v-if="form.considerations.length">
                              <li
                                v-for="(item, idx) in form.considerations"
                                :key="`consideration-${idx}`"
                                class="consideration-item"
                                draggable="true"
                                @dragstart="personalization.considerationDragStart(idx, $event)"
                                @dragover.prevent="personalization.considerationDragOver(idx, $event)"
                                @drop.prevent="personalization.considerationDrop(idx, $event)"
                                @dragend="personalization.considerationDragEnd()"
                              >
                                <span class="drag-handle" aria-hidden="true">≡</span>
                                <span class="consideration-text">{{ item }}</span>
                                <button type="button" class="consideration-remove" @click="personalization.removeConsideration(idx)">
                                  −
                                </button>
                              </li>
                            </ul>
                            <p class="consideration-hint" v-else>尚未添加任何必备信息</p>
                            <p class="consideration-limit">最多 {{ maxConsiderations }} 条，可拖动排序</p>
                          </div>
                        </div>
                        <div class="personal-form-actions card-aligned">
                          <div class="personal-status-group">
                            <transition name="personal-status-fade">
                              <span class="status success" v-if="status">{{ status }}</span>
                            </transition>
                            <transition name="personal-status-fade">
                              <span class="status error" v-if="error">{{ error }}</span>
                            </transition>
                          </div>
                          <button type="submit" class="primary" :disabled="saving">
                            {{ saving ? '保存中...' : '保存设置' }}
                          </button>
                        </div>
                      </div>
                    </div>
                  </section>
                  <section v-else-if="activeTab === 'image'" key="image" class="personal-page behavior-page">
                    <div class="behavior-section">
                      <div class="behavior-field">
                        <div class="behavior-field-header">
                          <span class="field-title">图片压缩</span>
                          <p class="behavior-desc">发送图片或调用 view_image 时自动等比缩放，防止大图占用过多 tokens。</p>
                        </div>
                        <div class="run-mode-options">
                          <button
                            v-for="option in imageCompressionOptions"
                            :key="option.id"
                            type="button"
                            class="run-mode-card"
                            :class="{ active: form.image_compression === option.id }"
                            :aria-pressed="form.image_compression === option.id"
                            @click.prevent="personalization.setImageCompression(option.id)"
                          >
                            <div class="run-mode-card-header">
                              <span class="run-mode-title">{{ option.label }}</span>
                            </div>
                            <p class="run-mode-desc">{{ option.desc }}</p>
                          </button>
                        </div>
                        <p class="behavior-hint">缩放保持原始比例；若原图已低于目标分辨率，将直接使用原图。</p>
                      </div>
                    </div>
                    <div class="personal-actions-row">
                      <div class="personal-form-actions card-aligned">
                        <div class="personal-status-group">
                          <transition name="personal-status-fade">
                            <span class="status success" v-if="status">{{ status }}</span>
                          </transition>
                          <transition name="personal-status-fade">
                            <span class="status error" v-if="error">{{ error }}</span>
                          </transition>
                        </div>
                        <button type="submit" class="primary" :disabled="saving">
                          {{ saving ? '保存中...' : '保存设置' }}
                        </button>
                      </div>
                    </div>
                  </section>
                  <section v-else-if="activeTab === 'model'" key="model" class="personal-page behavior-page">
                    <div class="behavior-section">
                      <div class="behavior-field">
                        <div class="behavior-field-header">
                          <span class="field-title">默认模型</span>
                          <p class="field-desc">为新对话/登录后首次请求选择首选模型，会与默认思考模式一起生效。</p>
                        </div>
                        <div class="run-mode-options model-options">
                          <button
                            v-for="option in filteredModelOptions"
                            :key="option.id"
                            type="button"
                            class="run-mode-card"
                            :class="[{ active: form.default_model === option.value }, { disabled: option.disabled }]"
                            :aria-pressed="form.default_model === option.value"
                            :disabled="option.disabled"
                            @click.prevent="!option.disabled && setDefaultModel(option.value)"
                          >
                            <div class="run-mode-card-header">
                              <span class="run-mode-title">{{ option.label }}</span>
                              <span v-if="option.badge" class="run-mode-badge">{{ option.badge }}</span>
                              <span v-if="option.disabled" class="run-mode-badge danger">已禁用</span>
                            </div>
                            <p class="run-mode-desc">{{ option.desc }}</p>
                          </button>
                        </div>
                        <p class="behavior-hint">
                          MiniMax-M2.5 仅支持深度思考模式，选择时会给出提示。
                        </p>
                      </div>
                      <div class="behavior-field">
                        <div class="behavior-field-header">
                          <span class="field-title">默认思考模型</span>
                          <p class="field-desc">设定登录或新建任务时的初始运行模式，仍可通过主界面随时切换。</p>
                        </div>
                        <div class="run-mode-options">
                          <button
                            v-for="option in runModeOptions"
                            :key="option.id"
                            type="button"
                            class="run-mode-card"
                            :class="{ active: isRunModeActive(option.value) }"
                            :aria-pressed="isRunModeActive(option.value)"
                            @click.prevent="setDefaultRunMode(option.value)"
                          >
                            <div class="run-mode-card-header">
                              <span class="run-mode-title">{{ option.label }}</span>
                              <span v-if="option.badge" class="run-mode-badge">{{ option.badge }}</span>
                            </div>
                            <p class="run-mode-desc">{{ option.desc }}</p>
                          </button>
                        </div>
                      </div>
                      <div class="behavior-field">
                        <div class="behavior-field-header">
                          <span class="field-title">思考频率</span>
                          <p class="field-desc">控制连续快速模式运行多少轮后，系统会强制切换到思考模型。</p>
                        </div>
                        <div class="thinking-presets">
                          <button
                            v-for="preset in thinkingPresets"
                            :key="preset.id"
                            type="button"
                            :class="{ active: isPresetActive(preset.value) }"
                            @click.prevent="applyThinkingPreset(preset.value)"
                          >
                            {{ preset.label }}
                            <small>{{ preset.value }} 轮</small>
                          </button>
                        </div>
                        <div class="thinking-input-row">
                          <label>
                            <span>自定义轮数</span>
                            <input
                              type="number"
                              :min="thinkingIntervalRange.min"
                              :max="thinkingIntervalRange.max"
                              :placeholder="`默认 ${thinkingIntervalDefault} 轮`"
                              :value="form.thinking_interval ?? ''"
                              @input="handleThinkingInput"
                              @focus="personalization.clearFeedback()"
                            />
                          </label>
                          <span class="thinking-hint">范围 {{ thinkingIntervalRange.min }}~{{ thinkingIntervalRange.max }} 轮。</span>
                          <button type="button" class="link-button" @click.prevent="restoreThinkingInterval">
                            恢复默认
                          </button>
                        </div>
                      </div>
                    </div>
                    <div class="personal-actions-row">
                      <div class="personal-form-actions card-aligned">
                        <div class="personal-status-group">
                          <transition name="personal-status-fade">
                            <span class="status success" v-if="status">{{ status }}</span>
                          </transition>
                          <transition name="personal-status-fade">
                            <span class="status error" v-if="error">{{ error }}</span>
                          </transition>
                        </div>
                        <button type="submit" class="primary" :disabled="saving">
                          {{ saving ? '保存中...' : '保存设置' }}
                        </button>
                      </div>
                    </div>
                  </section>
                  <section v-else-if="activeTab === 'behavior'" key="behavior" class="personal-page behavior-page">
                    <div class="behavior-section">
                      <div class="behavior-field">
                        <div class="behavior-field-header">
                          <span class="field-title">堆叠块显示</span>
                          <p class="field-desc">使用新版堆叠动画展示思考/工具块，超过 6 条自动收纳为“更多”。默认开启。</p>
                        </div>
                        <label class="toggle-row">
                          <input
                            type="checkbox"
                            :checked="experiments.stackedBlocksEnabled"
                            @change="handleStackedBlocksToggle($event)"
                          />
                          <span class="fancy-check" aria-hidden="true">
                            <svg viewBox="0 0 64 64">
                              <path
                                d="M 0 16 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 16 L 32 48 L 64 16 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 16"
                                pathLength="575.0541381835938"
                                class="fancy-path"
                          ></path>
                        </svg>
                      </span>
                      <span>在对话区使用堆叠动画（可随时切换回传统列表）</span>
                    </label>
                  </div>
                  <div class="behavior-field">
                    <div class="behavior-field-header">
                      <span class="field-title">静默禁用</span>
                      <p class="field-desc">禁用工具时不再注入提示消息，模型不会感知被禁用项。</p>
                    </div>
                    <label class="toggle-row">
                      <input
                        type="checkbox"
                        :checked="form.silent_tool_disable"
                        @change="personalization.updateField({ key: 'silent_tool_disable', value: $event.target.checked })"
                      />
                      <span class="fancy-check" aria-hidden="true">
                        <svg viewBox="0 0 64 64">
                          <path
                            d="M 0 16 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 16 L 32 48 L 64 16 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 16"
                            pathLength="575.0541381835938"
                            class="fancy-path"
                          ></path>
                        </svg>
                      </span>
                      <span>静默禁用工具（不向模型提示）</span>
                    </label>
                  </div>
                  <div class="behavior-field">
                    <div class="behavior-field-header">
                      <span class="field-title">自动生成对话标题</span>
                      <p class="field-desc">默认开启；关闭后标题将沿用首条消息。</p>
                    </div>
                        <label class="toggle-row">
                          <input
                            type="checkbox"
                            :checked="form.auto_generate_title"
                            @change="personalization.updateField({ key: 'auto_generate_title', value: $event.target.checked })"
                          />
                          <span class="fancy-check" aria-hidden="true">
                            <svg viewBox="0 0 64 64">
                              <path
                                d="M 0 16 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 16 L 32 48 L 64 16 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 16"
                                pathLength="575.0541381835938"
                                class="fancy-path"
                              ></path>
                            </svg>
                          </span>
                          <span>使用快速模型为新对话生成含 emoji 的简短标题</span>
                        </label>
                      </div>
                      <div class="behavior-field">
                        <div class="behavior-field-header">
                          <span class="field-title">工具意图提示</span>
                          <p class="field-desc">开启后，调用工具时会先用约15字告诉你要做什么，替代“正在/完成”文案。</p>
                        </div>
                        <label class="toggle-row">
                          <input
                            type="checkbox"
                            :checked="form.tool_intent_enabled"
                            @change="personalization.updateField({ key: 'tool_intent_enabled', value: $event.target.checked })"
                          />
                          <span class="fancy-check" aria-hidden="true">
                            <svg viewBox="0 0 64 64">
                              <path
                                d="M 0 16 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 16 L 32 48 L 64 16 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 16"
                                pathLength="575.0541381835938"
                                class="fancy-path"
                          ></path>
                        </svg>
                      </span>
                      <span>在工具块显示“我要做什么”的简短提示</span>
                    </label>
                  </div>
                  <div class="behavior-field">
                    <div class="behavior-field-header">
                      <span class="field-title">默认禁用工具类别</span>
                      <p class="field-desc">选择后，这些类别在新任务中会保持关闭，也可随时通过快捷菜单临时开启。</p>
                    </div>
                        <div class="tool-category-grid" v-if="toolCategories.length">
                          <label
                            v-for="category in toolCategories"
                            :key="category.id"
                            class="tool-category-chip"
                          >
                            <input
                              type="checkbox"
                              :checked="form.disabled_tool_categories.includes(category.id)"
                              @change="toggleCategory(category.id)"
                            />
                            <span>{{ category.label }}</span>
                          </label>
                        </div>
                        <p class="behavior-hint" v-else>暂无可配置的工具类别。</p>
                      </div>
                    </div>
                    <div class="personal-actions-row">
                      <div class="personal-form-actions card-aligned">
                        <div class="personal-status-group">
                          <transition name="personal-status-fade">
                            <span class="status success" v-if="status">{{ status }}</span>
                          </transition>
                          <transition name="personal-status-fade">
                            <span class="status error" v-if="error">{{ error }}</span>
                          </transition>
                        </div>
                        <button type="submit" class="primary" :disabled="saving">
                          {{ saving ? '保存中...' : '保存设置' }}
                        </button>
                      </div>
                    </div>
                    </section>
                  <section v-else-if="activeTab === 'skills'" key="skills" class="personal-page behavior-page">
                    <div class="behavior-section">
                      <div class="behavior-field">
                        <div class="behavior-field-header">
                          <span class="field-title">可用 Skills</span>
                          <p class="field-desc">勾选后会注入 system prompt，并同步到工作区的 skills/ 目录。</p>
                        </div>
                        <div class="tool-category-grid" v-if="skillsCatalog.length">
                          <label
                            v-for="skill in skillsCatalog"
                            :key="skill.id"
                            class="tool-category-chip"
                          >
                            <input
                              type="checkbox"
                              :checked="form.enabled_skills.includes(skill.id)"
                              @change="personalization.toggleSkill(skill.id)"
                            />
                            <span>{{ skill.label }}</span>
                          </label>
                        </div>
                        <p class="behavior-hint" v-else>暂无可用的 skills。</p>
                      </div>
                    </div>
                    <div class="personal-actions-row">
                      <div class="personal-form-actions card-aligned">
                        <div class="personal-status-group">
                          <transition name="personal-status-fade">
                            <span class="status success" v-if="status">{{ status }}</span>
                          </transition>
                          <transition name="personal-status-fade">
                            <span class="status error" v-if="error">{{ error }}</span>
                          </transition>
                        </div>
                        <button type="submit" class="primary" :disabled="saving">
                          {{ saving ? '保存中...' : '保存设置' }}
                        </button>
                      </div>
                    </div>
                  </section>
                  <section v-else-if="activeTab === 'theme'" key="theme" class="personal-page theme-page">
                    <div class="theme-section">
                      <div class="theme-header">
                        <div>
                          <h3>界面主题</h3>
                          <p>在浅色、深色和 Claude 经典之间一键切换。会立即应用并保存在本地。</p>
                        </div>
                        <div class="theme-badge">Beta</div>
                      </div>
                      <div class="theme-grid">
                        <button
                          v-for="option in themeOptions"
                          :key="option.id"
                          type="button"
                          class="theme-card"
                          :class="{ active: activeTheme === option.id }"
                          @click.prevent="applyThemeOption(option.id)"
                        >
                          <div class="theme-card-head">
                            <div class="theme-dot-row">
                              <span
                                v-for="(color, idx) in option.swatches"
                                :key="`${option.id}-${idx}`"
                                class="theme-dot"
                                :style="{ background: color }"
                                aria-hidden="true"
                              ></span>
                            </div>
                            <span class="theme-check" v-if="activeTheme === option.id">✓</span>
                          </div>
                          <div class="theme-card-body">
                            <h4>{{ option.label }}</h4>
                            <p>{{ option.desc }}</p>
                          </div>
                        </button>
                      </div>
                      <p class="theme-note">虚拟显示器保持原样；仅主界面、侧边栏与个人空间配色随主题改变。</p>
                    </div>
                  </section>
                  <section v-else-if="activeTab === 'experiments'" key="experiments" class="personal-page experiment-page">
                      <div class="experiment-hero">
                        <div class="experiment-visual" aria-hidden="true">
                          <span class="experiment-visual-glow"></span>
                          <span class="experiment-orb orb-one"></span>
                          <span class="experiment-orb orb-two"></span>
                          <span class="experiment-grid"></span>
                        </div>
                        <div class="experiment-copy">
                          <p class="experiment-subtitle">Liquid Glass</p>
                          <h3>液态玻璃界面实验</h3>
                          <p>
                            引用 Apple 最新的液态玻璃语言，通过折射位移贴图让 Q 弹玻璃漂浮在屏幕中。开启后，全局会出现一个可拖拽的实验面板，方便随时观察效果。
                          </p>
                        </div>
                      </div>
                      <div class="experiment-toggle-card">
                        <div class="experiment-toggle-info">
                          <h4>在界面上悬浮显示</h4>
                          <p>开启后即使关闭个人空间，可拖动的玻璃面板依然驻留在当前页面。</p>
                        </div>
                        <label class="personal-toggle experiment-toggle">
                          <span class="toggle-text">
                            <span class="toggle-title">液态玻璃实验面板</span>
                            <span class="toggle-desc">点击开关投放一块可拖动的液态玻璃矩形</span>
                          </span>
                          <span class="toggle-switch">
                            <input
                              type="checkbox"
                              :checked="experiments.liquidGlassEnabled"
                              @change="handleLiquidGlassToggle($event)"
                            />
                            <span class="switch-slider"></span>
                          </span>
                        </label>
                      </div>
                      <div class="experiment-note">
                        <p>完成实验只需回到这里关闭开关，面板会立刻消失。</p>
                        <ul class="experiment-hint-list">
                          <li>可在屏幕任意位置拖动，超出边界会自动回弹。</li>
                          <li>记忆上次的位置，下次开启直接延续。</li>
                          <li>实验状态仅存储在本地浏览器，不会上报服务器。</li>
                        </ul>
                      </div>
                  </section>
                  <section v-else-if="activeTab === 'admin-monitor'" key="admin-monitor" class="personal-page admin-monitor-page">
                    <div class="admin-monitor-panel">
                      <div class="admin-monitor-heading">
                        <p class="admin-monitor-eyebrow">系统资源</p>
                        <div class="admin-monitor-title-row">
                          <h3>管理员监控入口</h3>
                          <span class="admin-monitor-chip">自动刷新</span>
                        </div>
                        <p class="admin-monitor-desc">独立面板集中展示配额趋势、容器运行、项目存储与上传安全。</p>
                      </div>
                      <div class="admin-monitor-highlights">
                        <span class="admin-monitor-tag">用量统计</span>
                        <span class="admin-monitor-tag">容器健康</span>
                        <span class="admin-monitor-tag">上传审计</span>
                        <span class="admin-monitor-tag">邀请码管理</span>
                      </div>
                      <div class="admin-monitor-actions">
                        <button type="button" class="admin-monitor-button" @click="openAdminPanel">
                          打开监控面板
                        </button>
                        <button type="button" class="admin-monitor-button ghost" @click="openApiAdmin">
                          API 管理
                        </button>
                        <p class="admin-monitor-hint">新窗口开启，不打断当前对话与配置。</p>
                      </div>
                    </div>
                    <div class="admin-monitor-panel secondary">
                      <div class="admin-monitor-heading">
                        <p class="admin-monitor-eyebrow">自定义工具</p>
                        <div class="admin-monitor-title-row">
                          <h3>自定义工具管理</h3>
                          <span class="admin-monitor-chip alt">低代码 · Python</span>
                        </div>
                        <p class="admin-monitor-desc">在线创建/编辑 definition.json、execution.py、return.json、meta.json，保存后自动生效。</p>
                      </div>
                      <div class="admin-monitor-highlights">
                        <span class="admin-monitor-tag">仅管理员可见</span>
                        <span class="admin-monitor-tag">容器内执行</span>
                        <span class="admin-monitor-tag">无需重启</span>
                        <span class="admin-monitor-tag">三层拆分</span>
                      </div>
                      <div class="admin-monitor-actions">
                        <button type="button" class="admin-monitor-button" @click="openCustomTools">
                          打开自定义工具
                        </button>
                        <p class="admin-monitor-hint">新窗口打开 /admin/custom-tools 页面。</p>
                      </div>
                    </div>
                  </section>
                  </transition>
                </div>
              </div>
            </div>
          </form>
        </div>
        <div class="personalization-loading" v-else>正在加载个性化配置...</div>
      </div>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import { storeToRefs } from 'pinia';
import { usePersonalizationStore } from '@/stores/personalization';
import { useResourceStore } from '@/stores/resource';
import { useUiStore } from '@/stores/ui';
import { usePolicyStore } from '@/stores/policy';
import { useTheme } from '@/utils/theme';
import type { ThemeKey } from '@/utils/theme';

defineOptions({ name: 'PersonalizationDrawer' });

const personalization = usePersonalizationStore();
const resourceStore = useResourceStore();
const uiStore = useUiStore();
const {
  visible,
  loading,
  form,
  tonePresets,
  newConsideration,
  maxConsiderations,
  status,
  error,
  saving,
  toggleUpdating,
  toolCategories,
  skillsCatalog,
  thinkingIntervalDefault,
  thinkingIntervalRange,
  experiments
} = storeToRefs(personalization);

const baseTabs = [
  { id: 'preferences', label: '个性化设置', description: '称呼、语气与注意事项' },
  { id: 'model', label: '模型偏好', description: '默认模型选择' },
  { id: 'behavior', label: '模型行为', description: '工具提示与界面表现' },
  { id: 'skills', label: 'Skills', description: '可用技能开关' },
  { id: 'image', label: '图片压缩', description: '发送图片的尺寸策略' },
  { id: 'theme', label: '主题切换', description: '浅色 / 深色 / Claude' },
  { id: 'experiments', label: '实验功能', description: 'Liquid Glass' }
] as const;

type PersonalTab = 'preferences' | 'model' | 'behavior' | 'skills' | 'image' | 'theme' | 'experiments' | 'admin-monitor';

const isAdmin = computed(() => (resourceStore.usageQuota.role || '').toLowerCase() === 'admin');

const personalTabs = computed(() => {
  const tabs = [...baseTabs];
  if (isAdmin.value) {
    tabs.push({ id: 'admin-monitor' as const, label: '管理员监控', description: '系统总览' });
  }
  return tabs;
});

const activeTab = ref<PersonalTab>('preferences');
const swipeState = ref<{ startY: number; active: boolean }>({ startY: 0, active: false });

type RunModeValue = 'fast' | 'thinking' | 'deep' | null;

const runModeOptions: Array<{ id: string; label: string; desc: string; value: RunModeValue; badge?: string }> = [
  { id: 'fast', label: '快速模式', desc: '追求响应速度，跳过思考模型', value: 'fast' },
  { id: 'thinking', label: '思考模式', desc: '首轮回复会先输出思考过程', value: 'thinking', badge: '推荐' },
  { id: 'deep', label: '深度思考', desc: '整轮对话都使用思考模型', value: 'deep' }
];

const policyStore = usePolicyStore();

const modelOptions = [
  { id: 'deepseek', label: 'DeepSeek', desc: '通用 + 思考强化', value: 'deepseek' },
  { id: 'kimi-k2.5', label: 'Kimi-k2.5', desc: '新版 Kimi，思考开关 + 图文多模态', value: 'kimi-k2.5', badge: '图文' },
  { id: 'kimi', label: 'Kimi-k2', desc: '旧版 Kimi-k2，兼顾通用对话', value: 'kimi' },
  { id: 'qwen3-vl-plus', label: 'Qwen3.5', desc: '图文多模态 + 深度思考', value: 'qwen3-vl-plus', badge: '图文' },
  { id: 'minimax-m2.5', label: 'MiniMax-M2.5', desc: '仅深度思考，超长上下文', value: 'minimax-m2.5', badge: '深度思考' }
] as const;

const filteredModelOptions = computed(() =>
  modelOptions.map((opt) => ({
    ...opt,
    disabled: policyStore.disabledModelSet.has(opt.value)
  }))
);

const thinkingPresets = [
  { id: 'low', label: '低', value: 10 },
  { id: 'medium', label: '中', value: 5 },
  { id: 'high', label: '高', value: 3 }
];

const imageCompressionOptions = [
  { id: 'original', label: '原图', desc: '不压缩' },
  { id: '1080p', label: '1080p', desc: '最长边不超过 1080p 等比缩放' },
  { id: '720p', label: '720p', desc: '最长边不超过 720p 等比缩放' },
  { id: '540p', label: '540p', desc: '最长边不超过 540p 等比缩放' }
] as const;

const setActiveTab = (tab: PersonalTab) => {
  activeTab.value = tab;
};

const shiftTab = (direction: 1 | -1) => {
  const tabs = personalTabs.value;
  const currentIndex = tabs.findIndex((tab) => tab.id === activeTab.value);
  if (currentIndex === -1) {
    return;
  }
  const nextIndex = currentIndex + direction;
  if (nextIndex < 0 || nextIndex >= tabs.length) {
    return;
  }
  activeTab.value = tabs[nextIndex].id as PersonalTab;
};

const handleSwipeStart = (event: TouchEvent) => {
  if (!event.touches.length) {
    return;
  }
  swipeState.value = { startY: event.touches[0].clientY, active: true };
};

const handleSwipeEnd = (event: TouchEvent) => {
  if (!swipeState.value.active || !event.changedTouches.length) {
    return;
  }
  const deltaY = event.changedTouches[0].clientY - swipeState.value.startY;
  swipeState.value.active = false;
  if (Math.abs(deltaY) < 60) {
    return;
  }
  shiftTab(deltaY < 0 ? 1 : -1);
};

const applyThinkingPreset = (value: number) => {
  personalization.setThinkingInterval(value);
};

const isRunModeActive = (value: RunModeValue) => {
  if (value === null) {
    return !form.value.default_run_mode;
  }
  return form.value.default_run_mode === value;
};

const setDefaultRunMode = (value: RunModeValue) => {
  if (checkModeModelConflict(value, form.value.default_model)) {
    return;
  }
  personalization.setDefaultRunMode(value);
};

const setDefaultModel = (value: string) => {
  if (policyStore.disabledModelSet.has(value)) {
    uiStore.pushToast({
      title: '模型被禁用',
      message: '已被管理员禁用，无法选择',
      type: 'warning'
    });
    return;
  }
  if (checkModeModelConflict(form.value.default_run_mode, value)) {
    return;
  }
  personalization.setDefaultModel(value);
};

const checkModeModelConflict = (mode: RunModeValue, model: string | null): boolean => {
  const warnings: string[] = [];
  if (model === 'minimax-m2.5' && mode && mode !== 'deep') {
    warnings.push('MiniMax-M2.5 仅支持深度思考模式，已保持原设置。');
  }
  if (warnings.length) {
    uiStore.pushToast({
      title: '模型/思考模式不兼容',
      message: warnings.join(' '),
      type: 'warning',
      duration: 6000
    });
    return true;
  }
  return false;
};

const handleThinkingInput = (event: Event) => {
  const target = event.target as HTMLInputElement;
  if (!target.value) {
    personalization.setThinkingInterval(null);
    return;
  }
  const parsed = Number(target.value);
  personalization.setThinkingInterval(Number.isNaN(parsed) ? null : parsed);
};

const restoreThinkingInterval = () => {
  personalization.setThinkingInterval(null);
};

const isPresetActive = (value: number) => {
  if (form.value.thinking_interval === null || typeof form.value.thinking_interval === 'undefined') {
    return value === thinkingIntervalDefault.value;
  }
  return form.value.thinking_interval === value;
};

const toggleCategory = (categoryId: string) => {
  personalization.toggleDefaultToolCategory(categoryId);
};

const handleLiquidGlassToggle = (event: Event) => {
  const target = event.target as HTMLInputElement | null;
  personalization.setLiquidGlassExperimentEnabled(!!target?.checked);
};

const handleStackedBlocksToggle = (event: Event) => {
  const target = event.target as HTMLInputElement | null;
  personalization.setStackedBlocksEnabled(!!target?.checked);
};

const openAdminPanel = () => {
  window.open('/admin/monitor', '_blank', 'noopener');
  personalization.closeDrawer();
};

const openCustomTools = () => {
  window.open('/admin/custom-tools', '_blank', 'noopener');
  personalization.closeDrawer();
};

const openApiAdmin = () => {
  window.open('/admin/api', '_blank', 'noopener');
  personalization.closeDrawer();
};

// ===== 主题切换 =====
import { useTheme } from '@/utils/theme';
import type { ThemeKey } from '@/utils/theme';

const { setTheme, loadTheme } = useTheme();
const themeOptions: Array<{ id: ThemeKey; label: string; desc: string; swatches: string[] }> = [
  {
    id: 'claude',
    label: 'Claude 经典',
    desc: '仿 Claude 的米色质感，柔和高对比',
    swatches: ['#eeece2', '#f7f3ea', '#da7756']
  },
  {
    id: 'light',
    label: '浅灰 · 明亮',
    desc: '浅灰 + 白，清晰对比适合日间工作',
    swatches: ['#f4f5f7', '#ffffff', '#4f8bff']
  },
  {
    id: 'dark',
    label: '深灰 · 夜间',
    desc: '深灰 + 黑，低亮度并保持彩色点缀',
    swatches: ['#0f1115', '#1d2230', '#5ad1c9']
  }
];

const activeTheme = ref<ThemeKey>(loadTheme());

const applyThemeOption = (theme: ThemeKey) => {
  activeTheme.value = theme;
  setTheme(theme);
};
</script>

<style scoped>
.admin-monitor-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: center;
  min-height: 320px;
  padding: 12px 0 24px;
}

.admin-monitor-panel {
  width: 100%;
  max-width: 640px;
  padding: 28px 32px;
  border-radius: 26px;
  border: 1px solid var(--claude-border);
  background: linear-gradient(145deg, rgba(255, 255, 255, 0.96), rgba(247, 243, 234, 0.92));
  box-shadow: var(--claude-shadow);
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.admin-monitor-panel.secondary {
  background: linear-gradient(145deg, rgba(255, 255, 255, 0.96), rgba(247, 243, 234, 0.92));
}

.admin-monitor-heading {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.admin-monitor-title-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.admin-monitor-title-row h3 {
  margin: 0;
  font-size: 24px;
}

.admin-monitor-desc {
  margin: 0;
  color: rgba(70, 56, 40, 0.82);
  max-width: 460px;
}

.admin-monitor-chip {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgba(61, 57, 41, 0.15);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--claude-text-secondary);
  background: rgba(255, 255, 255, 0.65);
}

.admin-monitor-eyebrow {
  font-size: 12px;
  color: var(--claude-accent-strong);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.admin-monitor-highlights {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.admin-monitor-tag {
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px dashed rgba(61, 57, 41, 0.18);
  background: rgba(255, 255, 255, 0.8);
  font-size: 13px;
  color: var(--claude-text-secondary);
}

.section-note {
  margin: 6px 0 14px;
  font-size: 12px;
  color: var(--claude-text-secondary);
}

.admin-monitor-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.admin-monitor-button {
  border: none;
  border-radius: 16px;
  padding: 11px 28px;
  background: linear-gradient(135deg, var(--claude-accent), var(--claude-accent-strong));
  color: #fff;
  font-weight: 600;
  letter-spacing: 0.04em;
  box-shadow: 0 14px 28px rgba(61, 57, 41, 0.18);
  cursor: pointer;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.admin-monitor-button.ghost {
  background: transparent;
  color: var(--claude-text);
  border: 1px dashed rgba(61, 57, 41, 0.25);
  box-shadow: none;
}

.admin-monitor-button:hover {
  transform: translateY(-1px);
  box-shadow: 0 18px 32px rgba(61, 57, 41, 0.24);
}

.admin-monitor-button:active {
  transform: translateY(0);
  box-shadow: 0 12px 20px rgba(61, 57, 41, 0.2);
}

.admin-monitor-hint {
  margin: 0;
  font-size: 13px;
  color: var(--claude-text-secondary);
}

@media (max-width: 640px) {
  .admin-monitor-panel {
    padding: 24px;
  }

  .admin-monitor-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .admin-monitor-button {
    width: 100%;
    justify-content: center;
  }

  .admin-monitor-hint {
    text-align: center;
  }
}
</style>
