<template>
  <div class="space-y-5">
    <div>
      <div class="text-[10px] uppercase tracking-[0.3em] text-indigo-700 mb-1">Configuration</div>
      <h2 class="text-2xl font-extrabold text-ink-950 tracking-tight">设置</h2>
      <p class="text-sm text-ink-500 mt-1">管理员登录、巡检策略、邮箱后端、生命周期参数,皆可在此调整。</p>
    </div>

    <!-- F3 — 共享父级 master-health banner -->
    <MasterHealthBanner
      :master-health="masterHealth"
      :min-grace-until="minGraceUntil"
      :loading="masterHealthLoading"
      @refresh="onReloadMasterHealth" />

    <div class="glass rounded-lg p-5">
      <div class="flex items-center justify-between gap-4 mb-4">
        <div>
          <h2 class="text-lg font-semibold text-ink-950">管理员登录</h2>
          <p class="text-sm text-ink-500 mt-1">
            首次启动先在这里完成主号登录，系统会统一写入单个 state.json 文件，保存邮箱、session、workspace ID、workspace 名称；如果你走了密码登录，也会保留密码供主号 Codex 复用。
          </p>
        </div>
        <span
          class="min-w-[72px] px-3 py-1.5 rounded-full text-xs text-center whitespace-nowrap border"
          :class="adminConfigured
            ? 'bg-emerald-50 text-emerald-700 border-emerald-200'
            : adminBusy
              ? 'bg-amber-50 text-amber-700 border-amber-200'
              : 'bg-surface-hover text-ink-500 border-hairline'"
        >
          {{ adminConfigured ? '已配置' : adminBusy ? '登录中' : '未配置' }}
        </span>
      </div>

      <div v-if="message" class="mb-4 px-4 py-3 rounded-lg text-sm border" :class="messageClass">
        {{ message }}
      </div>

      <div v-if="adminConfigured && !adminBusy" class="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
        <div class="px-3 py-3 bg-surface-hover border border-hairline rounded-lg">
          <div class="text-gray-500 mb-1">管理员邮箱</div>
          <div class="font-mono text-ink-950 break-all">{{ props.adminStatus?.email || '-' }}</div>
        </div>
        <div class="px-3 py-3 bg-surface-hover border border-hairline rounded-lg">
          <div class="text-gray-500 mb-1">Workspace ID</div>
          <div class="font-mono text-ink-950 break-all">{{ props.adminStatus?.account_id || '-' }}</div>
        </div>
        <div class="px-3 py-3 bg-surface-hover border border-hairline rounded-lg md:col-span-2">
          <div class="text-gray-500 mb-1">Workspace 名称</div>
          <div class="text-ink-700">{{ props.adminStatus?.workspace_name || '未识别' }}</div>
        </div>
        <div class="px-3 py-3 bg-surface-hover border border-hairline rounded-lg md:col-span-2">
          <div class="text-gray-500 mb-1">Session Token</div>
          <div v-if="props.adminStatus?.session_present" class="text-emerald-700 text-xs">已配置</div>
          <div v-else class="space-y-2">
            <div class="text-amber-400 text-xs">未配置（Team 管理功能需要 session token）</div>
            <div class="text-ink-500 text-xs space-y-2">
              <div>获取方式：</div>
              <ol class="list-decimal list-inside space-y-1">
                <li>
                  在浏览器中打开
                  <a href="https://chatgpt.com" target="_blank" rel="noreferrer" class="text-blue-400 hover:underline">
                    chatgpt.com
                  </a>
                  并登录管理员账号
                </li>
                <li>按 F12 打开开发者工具 → Application → Cookies → chatgpt.com</li>
                <li>找到 <code class="bg-surface-hover px-1 rounded">__Secure-next-auth.session-token</code></li>
                <li>
                  如果有 <code class="bg-surface-hover px-1 rounded">.0</code> 和
                  <code class="bg-surface-hover px-1 rounded">.1</code> 两个，将值按顺序拼接在一起
                </li>
                <li>粘贴到下方输入框</li>
              </ol>
            </div>
            <div class="space-y-2">
              <input
                v-model.trim="sessionToken"
                type="password"
                placeholder="粘贴 session token"
                class="w-full px-2 py-1.5 bg-surface-hover border border-hairline rounded text-xs text-ink-950 font-mono focus:outline-none focus:border-indigo-500"
              />
              <div class="flex justify-end">
                <button
                  @click="importSessionToken"
                  :disabled="submitting || !sessionEmail || !sessionToken"
                  class="px-3 py-1.5 bg-indigo-600 hover:bg-indigo-500 text-on-accent text-xs rounded transition disabled:opacity-50"
                >
                  {{ submitting ? '校验中...' : '保存' }}
                </button>
              </div>
            </div>
          </div>
        </div>
        <div class="px-3 py-3 bg-surface-hover border border-hairline rounded-lg md:col-span-2">
          <div class="text-gray-500 mb-1">管理员密码</div>
          <div class="text-ink-700">{{ props.adminStatus?.password_saved ? '已保存，可用于主号 Codex 登录' : '未保存' }}</div>
        </div>
      </div>

      <div v-if="!adminBusy" class="mt-4">
        <div v-if="!adminConfigured" class="space-y-4">
          <div class="flex flex-col sm:flex-row gap-3">
            <input
              v-model.trim="email"
              type="email"
              autocomplete="username"
              placeholder="输入主号邮箱"
              class="flex-1 px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500"
            />
            <button
              @click="startLogin"
              :disabled="submitting || !email"
              class="px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-on-accent text-sm rounded-lg transition disabled:opacity-50"
            >
              {{ submitting ? '提交中...' : '开始登录' }}
            </button>
          </div>

          <div class="border border-hairline rounded-lg p-4 bg-surface-hover">
            <div class="text-sm font-medium text-ink-950">或手动导入 session_token</div>
            <p class="text-xs text-ink-500 mt-1 mb-3">
              适合你已经在浏览器里拿到 <span class="font-mono">__Secure-next-auth.session-token</span> 的场景。系统会校验 token，并自动识别 workspace ID / 名称。
            </p>
            <div class="text-ink-500 text-xs space-y-2 mb-3">
              <div>获取方式：</div>
              <ol class="list-decimal list-inside space-y-1">
                <li>
                  在浏览器中打开
                  <a href="https://chatgpt.com" target="_blank" rel="noreferrer" class="text-blue-400 hover:underline">
                    chatgpt.com
                  </a>
                  并登录管理员账号
                </li>
                <li>按 F12 打开开发者工具 → Application → Cookies → chatgpt.com</li>
                <li>找到 <code class="bg-surface-hover px-1 rounded">__Secure-next-auth.session-token</code></li>
                <li>
                  如果有 <code class="bg-surface-hover px-1 rounded">.0</code> 和
                  <code class="bg-surface-hover px-1 rounded">.1</code> 两个，将值按顺序拼接在一起
                </li>
                <li>粘贴到下方输入框</li>
              </ol>
            </div>
            <div class="space-y-3">
              <input
                v-model.trim="sessionEmail"
                type="email"
                autocomplete="username"
                placeholder="输入主号邮箱"
                class="w-full px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-cyan-500"
              />
              <textarea
                v-model.trim="sessionToken"
                rows="4"
                spellcheck="false"
                placeholder="粘贴完整 session_token"
                class="w-full px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 font-mono focus:outline-none focus:border-cyan-500"
              ></textarea>
              <div class="flex justify-end">
                <button
                  @click="importSessionToken"
                  :disabled="submitting || !sessionEmail || !sessionToken"
                  class="px-4 py-2 bg-cyan-700 hover:bg-cyan-600 text-on-accent text-sm rounded-lg transition disabled:opacity-50"
                >
                  {{ submitting ? '校验中...' : '导入 session_token' }}
                </button>
              </div>
            </div>
          </div>
        </div>

        <div v-else-if="!codexBusy" class="flex flex-wrap gap-3">
          <button
            @click="syncMainCodex"
            :disabled="submitting || syncingMain"
            class="px-4 py-2 bg-cyan-700 hover:bg-cyan-600 text-on-accent text-sm rounded-lg transition disabled:opacity-50"
          >
            {{ syncingMain ? '同步中...' : '同步主号 Codex 到 CPA' }}
          </button>
          <button
            @click="logoutAdmin"
            :disabled="submitting || syncingMain"
            class="px-4 py-2 bg-rose-700/80 hover:bg-rose-700 text-on-accent text-sm rounded-lg transition disabled:opacity-50"
          >
            {{ submitting ? '处理中...' : '清除登录态' }}
          </button>
        </div>
      </div>

      <div v-if="adminBusy" class="space-y-4">
        <div class="text-sm text-ink-700">
          当前邮箱: <span class="font-mono">{{ loginEmail || props.adminStatus?.email || '-' }}</span>
        </div>

        <div v-if="props.adminStatus?.login_step === 'password_required'" class="flex flex-col sm:flex-row gap-3">
          <input
            v-model="password"
            type="password"
            autocomplete="current-password"
            placeholder="输入主号密码"
            :disabled="submitting"
            class="flex-1 px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500"
          />
          <button
            @click="submitPassword"
            :disabled="submitting || !password"
            class="px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-on-accent text-sm rounded-lg transition disabled:opacity-50"
          >
            {{ submitting ? '提交中...' : '提交密码' }}
          </button>
        </div>

        <div v-else-if="props.adminStatus?.login_step === 'code_required'" class="flex flex-col sm:flex-row gap-3">
          <input
            v-model.trim="code"
            type="text"
            inputmode="numeric"
            autocomplete="one-time-code"
            placeholder="输入邮箱验证码"
            :disabled="submitting"
            class="flex-1 px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500"
          />
          <button
            @click="submitCode"
            :disabled="submitting || !code"
            class="px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-on-accent text-sm rounded-lg transition disabled:opacity-50 disabled:bg-ink-100 disabled:hover:bg-ink-100"
          >
            {{ submitting ? '提交中...' : '提交验证码' }}
          </button>
        </div>

        <div v-else-if="props.adminStatus?.login_step === 'workspace_required'" class="space-y-3">
          <div class="text-sm text-ink-700">
            请选择要进入的组织 / workspace
          </div>
          <select
            v-model="workspaceOptionId"
            :disabled="submitting"
            class="w-full px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500"
          >
            <option disabled value="">请选择组织</option>
            <option
              v-for="opt in props.adminStatus?.workspace_options || []"
              :key="opt.id"
              :value="opt.id"
            >
              {{ opt.label }}{{ opt.kind === 'fallback' ? ' (可能是个人/免费)' : '' }}
            </option>
          </select>
          <button
            @click="submitWorkspace"
            :disabled="submitting || !workspaceOptionId"
            class="px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-on-accent text-sm rounded-lg transition disabled:opacity-50 disabled:bg-ink-100 disabled:hover:bg-ink-100"
          >
            {{ submitting ? '提交中...' : '确认组织选择' }}
          </button>
        </div>

        <div v-if="submitting && adminSubmittingHint" class="text-xs text-sky-700">
          {{ adminSubmittingHint }}
        </div>

        <div class="flex justify-end">
          <button
            @click="cancelLogin"
            :disabled="submitting"
            class="px-4 py-2 bg-surface-hover hover:bg-hairline text-sm text-ink-700 rounded-lg border border-hairline transition disabled:opacity-50"
          >
            取消登录
          </button>
        </div>
      </div>

      <div v-if="codexBusy" class="mt-4 space-y-4 border-t border-hairline pt-4">
        <div class="text-sm text-ink-700">
          主号 Codex 登录继续中
        </div>

        <div v-if="props.codexStatus?.step === 'password_required'" class="flex flex-col sm:flex-row gap-3">
          <input
            v-model="codexPassword"
            type="password"
            autocomplete="current-password"
            placeholder="输入主号密码"
            :disabled="syncingMain"
            class="flex-1 px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500"
          />
          <button
            @click="submitMainCodexPassword"
            :disabled="syncingMain || !codexPassword"
            class="px-4 py-2 bg-cyan-700 hover:bg-cyan-600 text-on-accent text-sm rounded-lg transition disabled:opacity-50"
          >
            {{ syncingMain ? '提交中...' : '提交密码' }}
          </button>
        </div>

        <div v-else-if="props.codexStatus?.step === 'code_required'" class="flex flex-col sm:flex-row gap-3">
          <input
            v-model.trim="codexCode"
            type="text"
            inputmode="numeric"
            autocomplete="one-time-code"
            placeholder="输入主号 Codex 验证码"
            :disabled="syncingMain"
            class="flex-1 px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500"
          />
          <button
            @click="submitMainCodexCode"
            :disabled="syncingMain || !codexCode"
            class="px-4 py-2 bg-cyan-700 hover:bg-cyan-600 text-on-accent text-sm rounded-lg transition disabled:opacity-50"
          >
            {{ syncingMain ? '提交中...' : '提交验证码' }}
          </button>
        </div>

        <div v-if="syncingMain && codexSubmittingHint" class="text-xs text-cyan-700">
          {{ codexSubmittingHint }}
        </div>

        <div class="flex justify-end">
          <button
            @click="cancelMainCodexSync"
            :disabled="syncingMain"
            class="px-4 py-2 bg-surface-hover hover:bg-hairline text-sm text-ink-700 rounded-lg border border-hairline transition disabled:opacity-50"
          >
            取消主号 Codex 登录
          </button>
        </div>
      </div>
    </div>

    <div class="glass rounded-lg p-5">
      <div class="flex items-center justify-between mb-4">
        <h2 class="text-lg font-semibold text-ink-950">巡检设置</h2>
        <span v-if="saved" class="text-xs text-emerald-700 transition">已保存</span>
      </div>

      <div class="grid grid-cols-1 sm:grid-cols-4 gap-4">
        <div>
          <label class="block text-sm text-ink-500 mb-1">巡检间隔</label>
          <div class="flex items-center gap-2">
            <input v-model.number="form.interval" type="number" min="1"
              class="w-full px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500" />
            <span class="text-sm text-gray-500 shrink-0">分钟</span>
          </div>
        </div>
        <div>
          <label class="block text-sm text-ink-500 mb-1">目标席位</label>
          <div class="flex items-center gap-2">
            <input v-model.number="form.target_seats" type="number" min="1" max="3"
              class="w-full px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500" />
            <span class="text-sm text-gray-500 shrink-0">席</span>
          </div>
        </div>
        <div>
          <label class="block text-sm text-ink-500 mb-1">额度阈值</label>
          <div class="flex items-center gap-2">
            <input v-model.number="form.threshold" type="number" min="1" max="100"
              class="w-full px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500" />
            <span class="text-sm text-gray-500 shrink-0">%</span>
          </div>
        </div>
        <div>
          <label class="block text-sm text-ink-500 mb-1">触发账号数</label>
          <div class="flex items-center gap-2">
            <input v-model.number="form.min_low" type="number" min="1"
              class="w-full px-3 py-2 bg-surface-hover border border-hairline rounded-lg text-sm text-ink-950 focus:outline-none focus:border-indigo-500" />
            <span class="text-sm text-gray-500 shrink-0">个</span>
          </div>
        </div>
      </div>

      <div class="mt-3 flex items-center justify-between gap-3">
        <p class="text-xs text-gray-500">
          每 {{ form.interval }} 分钟检查一次，目标 {{ form.target_seats }} 席（1 母 + 最多 2 子），{{ form.min_low }} 个以上账号剩余低于 {{ form.threshold }}% 时自动轮转
        </p>
        <button @click="save" :disabled="saving"
          class="px-4 py-1.5 bg-indigo-600 hover:bg-indigo-500 text-on-accent text-sm rounded-lg transition disabled:opacity-50">
          {{ saving ? '保存中...' : '保存' }}
        </button>
      </div>
    </div>

    <!-- SPEC-1 §FR-008 / AC-017 — 邮箱后端切换 (Settings 复用 SetupPage 4 步状态机) -->
    <div class="glass rounded-lg p-5">
      <div class="flex items-center justify-between gap-4 mb-4">
        <div>
          <h2 class="text-lg font-semibold text-ink-950">邮箱后端</h2>
          <p class="text-sm text-ink-500 mt-1">
            切换或重新配置临时邮箱服务（cf_temp_email / maillab）。SetupPage 完成后所有字段已落盘，这里仅在需要更换服务时使用。
          </p>
        </div>
        <span
          class="min-w-[72px] px-3 py-1.5 rounded-full text-xs text-center whitespace-nowrap border"
          :class="mailFormDirty
            ? 'bg-amber-50 text-amber-700 border-amber-200'
              : 'bg-surface-hover text-ink-500 border-hairline'"
        >
          {{ mailFormDirty ? '有改动' : '已配置' }}
        </span>
      </div>

      <div v-if="mailMessage" class="mb-4 px-4 py-3 rounded-lg text-sm border" :class="mailMessageClass">
        {{ mailMessage }}
      </div>

      <!-- 步骤 1+2+3:Provider 选择 / 连接 / 域名(Round 7 P2.2 抽 MailProviderCard) -->
      <MailProviderCard
        ref="mailCardRef"
        v-model="mailForm"
        mode="settings"
        @state-change="onMailStateChange"
        @verified="onMailVerified"
        @error="onMailError" />

      <div class="flex justify-end gap-3">
        <button
          @click="resetMailForm"
          :disabled="mailSaving"
          class="px-4 py-1.5 bg-surface-hover hover:bg-hairline text-sm text-ink-700 rounded-lg border border-hairline transition disabled:opacity-50">
          重置
        </button>
        <button
          @click="saveMailConfig"
          :disabled="mailSaving || mailState !== 'SAVE'"
          class="px-4 py-1.5 bg-indigo-600 hover:bg-indigo-500 text-on-accent text-sm rounded-lg transition disabled:opacity-50">
          {{ mailSaving ? '保存中...' : '保存邮箱后端配置' }}
        </button>
      </div>
    </div>

    <!-- SPEC-2 §席位策略 + 探测节流 -->
    <div class="glass rounded-lg p-5">
      <div class="mb-4">
        <h2 class="text-lg font-semibold text-ink-950">账号生命周期</h2>
        <p class="text-sm text-ink-500 mt-1">
          控制邀请席位偏好(完整 ChatGPT 席位 vs 仅 Codex 席位),以及 sync 巡检识别"被踢"的探测节流。
        </p>
      </div>

      <div v-if="lifecycleMessage" class="mb-3 px-4 py-3 rounded-lg text-sm border" :class="lifecycleMessageClass">
        {{ lifecycleMessage }}
      </div>

      <div class="mb-4 p-3 bg-surface-hover/60 border border-hairline rounded">
        <div class="flex items-center justify-between mb-2">
          <span class="text-sm text-ink-950">邀请席位偏好</span>
          <span class="text-xs text-ink-500">{{ preferredSeatType === 'codex' ? '锁定 Codex 席位' : '优先 ChatGPT 完整席位' }}</span>
        </div>
        <div class="flex gap-2">
          <button
            @click="setPreferredSeatType('default')"
            :class="preferredSeatType === 'default' ? 'bg-indigo-600 border-indigo-500 text-on-accent' : 'bg-surface-hover border-hairline text-ink-700'"
            class="flex-1 px-3 py-2 border rounded text-sm transition">
            <div class="font-medium">default</div>
            <div class="text-xs opacity-75 mt-0.5">优先 PATCH 升级到 ChatGPT 席位(老行为)</div>
          </button>
          <button
            @click="setPreferredSeatType('codex')"
            :class="preferredSeatType === 'codex' ? 'bg-indigo-600 border-indigo-500 text-on-accent' : 'bg-surface-hover border-hairline text-ink-700'"
            class="flex-1 px-3 py-2 border rounded text-sm transition">
            <div class="font-medium">codex</div>
            <div class="text-xs opacity-75 mt-0.5">锁 codex-only 席位,跳过 PATCH(节约 ChatGPT 席位)</div>
          </button>
        </div>
      </div>

      <div class="p-3 bg-surface-hover/60 border border-hairline rounded">
        <div class="text-sm text-ink-950 mb-2">sync 探测节流</div>
        <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
          <div>
            <div class="text-xs text-ink-500 mb-1">并发上限 (1-16)</div>
            <input
              v-model.number="syncProbeConcurrency"
              type="number"
              min="1" max="16"
              class="w-full px-2 py-1.5 bg-surface-hover border border-hairline rounded text-sm text-ink-950" />
          </div>
          <div>
            <div class="text-xs text-ink-500 mb-1">同号去重冷却 (分钟,1-1440)</div>
            <input
              v-model.number="syncProbeCooldown"
              type="number"
              min="1" max="1440"
              class="w-full px-2 py-1.5 bg-surface-hover border border-hairline rounded text-sm text-ink-950" />
          </div>
        </div>
        <div class="flex justify-end mt-3">
          <button
            @click="saveSyncProbe"
            :disabled="lifecycleSaving"
            class="px-3 py-1.5 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-on-accent text-xs rounded">
            {{ lifecycleSaving ? '保存中...' : '保存探测节流' }}
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, ref, watch, onMounted } from 'vue'
import { api } from '../api.js'
import MailProviderCard from './MailProviderCard.vue'
import MasterHealthBanner from './MasterHealthBanner.vue'

const props = defineProps({
  adminStatus: { type: Object, default: null },
  codexStatus: { type: Object, default: null },
  masterHealth: { type: Object, default: null },
  status: { type: Object, default: null },
})

const emit = defineEmits(['refresh', 'admin-progress', 'reload-master-health'])

// F3 — minGraceUntil 派生(父级传 status,这里取最早 grace_until)
const minGraceUntil = computed(() => {
  let min = null
  for (const acc of props.status?.accounts || []) {
    if (acc.status === 'degraded_grace' && typeof acc.grace_until === 'number') {
      if (min === null || acc.grace_until < min) min = acc.grace_until
    }
  }
  return min
})

const masterHealthLoading = ref(false)
async function onReloadMasterHealth() {
  masterHealthLoading.value = true
  try { emit('reload-master-health', true) }
  finally { setTimeout(() => { masterHealthLoading.value = false }, 1200) }
}

const form = ref({ interval: 5, target_seats: 3, threshold: 10, min_low: 2 })
const saving = ref(false)
const saved = ref(false)

const email = ref('')
const sessionEmail = ref('')
const sessionToken = ref('')
const password = ref('')
const code = ref('')
const workspaceOptionId = ref('')
const loginEmail = ref('')
const codexPassword = ref('')
const codexCode = ref('')
const submitting = ref(false)
const syncingMain = ref(false)
const message = ref('')
const messageClass = ref('')
const adminSubmittingHint = ref('')
const codexSubmittingHint = ref('')

const adminConfigured = computed(() => !!props.adminStatus?.configured)
const adminBusy = computed(() => !!props.adminStatus?.login_in_progress)
const codexBusy = computed(() => !!props.codexStatus?.in_progress)

watch(
  () => props.adminStatus,
  (next) => {
    if (next?.configured && next.email) {
      email.value = next.email
      sessionEmail.value = next.email
    }
    if (!next?.login_in_progress) {
      password.value = ''
      code.value = ''
      workspaceOptionId.value = ''
      adminSubmittingHint.value = ''
      loginEmail.value = next?.email || loginEmail.value
    }
    if (next?.login_step === 'workspace_required' && !workspaceOptionId.value) {
      const preferred = next?.workspace_options?.find(opt => opt.kind === 'preferred')
      workspaceOptionId.value = preferred?.id || next?.workspace_options?.[0]?.id || ''
    }
  },
  { immediate: true },
)

watch(
  () => props.codexStatus,
  (next) => {
    if (!next?.in_progress) {
      codexPassword.value = ''
      codexCode.value = ''
      codexSubmittingHint.value = ''
    }
  },
  { immediate: true },
)

// SPEC-2 — 席位偏好 + sync 探测节流(本块独立于上面的 mailForm)
const preferredSeatType = ref('default')
const syncProbeConcurrency = ref(5)
const syncProbeCooldown = ref(30)
const lifecycleSaving = ref(false)
const lifecycleMessage = ref('')
const lifecycleMessageClass = ref('')

function setLifecycleMessage(text, type = 'success') {
  lifecycleMessage.value = text
  lifecycleMessageClass.value = type === 'success'
    ? 'bg-emerald-50 text-emerald-700 border-emerald-200'
    : 'bg-rose-50 text-rose-700 border-rose-200'
  window.clearTimeout(setLifecycleMessage._t)
  setLifecycleMessage._t = window.setTimeout(() => { lifecycleMessage.value = '' }, 8000)
}

async function setPreferredSeatType(value) {
  if (preferredSeatType.value === value) return
  lifecycleSaving.value = true
  try {
    const resp = await api.putPreferredSeatType(value)
    preferredSeatType.value = resp.value
    setLifecycleMessage(resp.message || `已设为 ${resp.value}`)
  } catch (e) {
    setLifecycleMessage(e.message || '保存失败', 'error')
  } finally {
    lifecycleSaving.value = false
  }
}

async function saveSyncProbe() {
  lifecycleSaving.value = true
  try {
    const resp = await api.putSyncProbe({
      concurrency: syncProbeConcurrency.value,
      cooldown_minutes: syncProbeCooldown.value,
    })
    syncProbeConcurrency.value = resp.concurrency
    syncProbeCooldown.value = resp.cooldown_minutes
    setLifecycleMessage(resp.message || '已保存')
  } catch (e) {
    setLifecycleMessage(e.message || '保存失败', 'error')
  } finally {
    lifecycleSaving.value = false
  }
}

onMounted(async () => {
  try {
    const cfg = await api.getAutoCheckConfig()
    form.value = {
      interval: Math.round(cfg.interval / 60),
      target_seats: cfg.target_seats ?? 3,
      threshold: cfg.threshold,
      min_low: cfg.min_low,
    }
  } catch {}
  try {
    const seat = await api.getPreferredSeatType()
    preferredSeatType.value = seat?.value || 'default'
  } catch {}
  try {
    const sp = await api.getSyncProbe()
    syncProbeConcurrency.value = sp?.concurrency ?? 5
    syncProbeCooldown.value = sp?.cooldown_minutes ?? 30
  } catch {}
  // F3 — 母号订阅健康度由 App 级共享 props.masterHealth,不再本组件自管
})

function setMessage(text, type = 'success') {
  message.value = text
  messageClass.value = type === 'success'
    ? 'bg-emerald-50 text-emerald-700 border-emerald-200'
    : 'bg-rose-50 text-rose-700 border-rose-200'
  window.clearTimeout(setMessage._timer)
  setMessage._timer = window.setTimeout(() => {
    message.value = ''
  }, 8000)
}

async function startLogin() {
  submitting.value = true
  adminSubmittingHint.value = '正在打开管理员登录页...'
  try {
    loginEmail.value = email.value
    const result = await api.startAdminLogin(email.value)
    setMessage(result.status === 'completed' ? '管理员登录完成' : '已进入下一步登录流程')
    emit('admin-progress')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    submitting.value = false
    adminSubmittingHint.value = ''
  }
}

async function importSessionToken() {
  submitting.value = true
  adminSubmittingHint.value = '正在校验 session_token 并识别 workspace...'
  try {
    loginEmail.value = sessionEmail.value
    const result = await api.submitAdminSession(sessionEmail.value, sessionToken.value)
    sessionToken.value = ''
    setMessage(result.status === 'completed' ? 'session_token 导入成功' : 'session_token 已提交')
    emit('refresh')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    submitting.value = false
    adminSubmittingHint.value = ''
  }
}

async function submitPassword() {
  submitting.value = true
  adminSubmittingHint.value = '密码已提交，正在等待登录页响应...'
  try {
    const result = await api.submitAdminPassword(password.value)
    setMessage(result.status === 'completed' ? '管理员登录完成' : '密码已提交，请继续下一步')
    emit('admin-progress')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    submitting.value = false
    adminSubmittingHint.value = ''
  }
}

async function submitCode() {
  submitting.value = true
  adminSubmittingHint.value = '验证码已提交，正在等待登录页响应，通常需要 5 到 10 秒...'
  try {
    const result = await api.submitAdminCode(code.value)
    setMessage(result.status === 'completed' ? '管理员登录完成' : '验证码已提交，请继续下一步')
    emit('admin-progress')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    submitting.value = false
    adminSubmittingHint.value = ''
  }
}

async function submitWorkspace() {
  submitting.value = true
  adminSubmittingHint.value = '组织选择已提交，正在等待登录页响应...'
  try {
    const result = await api.submitAdminWorkspace(workspaceOptionId.value)
    setMessage(result.status === 'completed' ? '管理员登录完成' : '组织选择已提交，请继续下一步')
    emit('admin-progress')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    submitting.value = false
    adminSubmittingHint.value = ''
  }
}

async function cancelLogin() {
  submitting.value = true
  try {
    await api.cancelAdminLogin()
    password.value = ''
    code.value = ''
    setMessage('管理员登录已取消')
    emit('refresh')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    submitting.value = false
  }
}

async function logoutAdmin() {
  submitting.value = true
  try {
    await api.logoutAdmin()
    password.value = ''
    code.value = ''
    setMessage('管理员登录态已清除')
    emit('refresh')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    submitting.value = false
  }
}

async function syncMainCodex() {
  syncingMain.value = true
  codexSubmittingHint.value = '正在打开主号 Codex 登录页...'
  try {
    const result = await api.startMainCodexSync()
    setMessage(result.status === 'completed' ? (result.message || '主号 Codex 已同步') : '主号 Codex 登录进入下一步')
    emit('admin-progress')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    syncingMain.value = false
    codexSubmittingHint.value = ''
  }
}

async function submitMainCodexPassword() {
  syncingMain.value = true
  codexSubmittingHint.value = '密码已提交，正在等待主号 Codex 登录页响应...'
  try {
    const result = await api.submitMainCodexPassword(codexPassword.value)
    setMessage(result.status === 'completed' ? (result.message || '主号 Codex 已同步') : '主号 Codex 密码已提交')
    emit('admin-progress')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    syncingMain.value = false
    codexSubmittingHint.value = ''
  }
}

async function submitMainCodexCode() {
  syncingMain.value = true
  codexSubmittingHint.value = '验证码已提交，正在等待主号 Codex 登录页响应，通常需要 5 到 10 秒...'
  try {
    const result = await api.submitMainCodexCode(codexCode.value)
    setMessage(result.status === 'completed' ? (result.message || '主号 Codex 已同步') : '主号 Codex 验证码已提交')
    emit('admin-progress')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    syncingMain.value = false
    codexSubmittingHint.value = ''
  }
}

async function cancelMainCodexSync() {
  syncingMain.value = true
  try {
    await api.cancelMainCodexSync()
    setMessage('主号 Codex 登录已取消')
    emit('refresh')
  } catch (e) {
    setMessage(e.message, 'error')
  } finally {
    syncingMain.value = false
  }
}

async function save() {
  saving.value = true
  saved.value = false
  try {
    const cfg = await api.setAutoCheckConfig({
      interval: form.value.interval * 60,
      target_seats: form.value.target_seats,
      threshold: form.value.threshold,
      min_low: form.value.min_low,
    })
    form.value = {
      interval: Math.round(cfg.interval / 60),
      target_seats: cfg.target_seats ?? 3,
      threshold: cfg.threshold,
      min_low: cfg.min_low,
    }
    saved.value = true
    setTimeout(() => { saved.value = false }, 3000)
  } catch (e) {
    console.error('保存失败:', e)
  } finally {
    saving.value = false
  }
}

// ---------- SPEC-1 §FR-008 / AC-017 邮箱后端切换(Round 7 P2.2 抽 MailProviderCard) ----------
const mailState = ref('PROVIDER')
const mailForm = ref({
  MAIL_PROVIDER: 'cf_temp_email',
  CLOUDMAIL_BASE_URL: '',
  CLOUDMAIL_PASSWORD: '',
  CLOUDMAIL_DOMAIN: '',
  MAILLAB_API_URL: '',
  MAILLAB_USERNAME: '',
  MAILLAB_PASSWORD: '',
  MAILLAB_DOMAIN: '',
})
const mailInitialSnapshot = ref(null)
const mailSaving = ref(false)
const mailMessage = ref('')
const mailMessageClass = ref('')
const mailCardRef = ref(null)

const mailFormDirty = computed(() => {
  if (!mailInitialSnapshot.value) return false
  return JSON.stringify(mailForm.value) !== mailInitialSnapshot.value
})

function setMailMessage(text, type = 'success') {
  mailMessage.value = text
  if (type === 'success') mailMessageClass.value = 'bg-emerald-50 text-emerald-700 border-emerald-200'
  else if (type === 'warning') mailMessageClass.value = 'bg-amber-50 text-amber-700 border-amber-200'
  else mailMessageClass.value = 'bg-rose-50 text-rose-700 border-rose-200'
  window.clearTimeout(setMailMessage._timer)
  setMailMessage._timer = window.setTimeout(() => { mailMessage.value = '' }, 10000)
}

function onMailStateChange(s) {
  mailState.value = s
}

function onMailVerified(payload) {
  if (payload?.leakedProbe) {
    setMailMessage(`提醒: 探测邮箱回收失败,请到后台手动删除: ${payload.leakedProbe.email}`, 'warning')
  }
}

function onMailError(resp) {
  if (resp?.soft && resp.warnings) {
    setMailMessage('提醒: ' + resp.warnings.join('; '), 'warning')
    return
  }
  setMailMessage(`${resp.error_code || 'ERROR'}: ${resp.message || '未知错误'}` +
    (resp.hint ? ` — ${resp.hint}` : ''), 'error')
}

async function saveMailConfig() {
  mailSaving.value = true
  try {
    await api.saveSetup({ ...mailForm.value })
    mailInitialSnapshot.value = JSON.stringify(mailForm.value)
    setMailMessage('保存成功 — 重启服务后生效', 'success')
  } catch (e) {
    setMailMessage('保存失败: ' + e.message, 'error')
  } finally {
    mailSaving.value = false
  }
}

function resetMailForm() {
  if (!mailInitialSnapshot.value) return
  mailForm.value = JSON.parse(mailInitialSnapshot.value)
  mailCardRef.value?.reset?.()
  mailState.value = 'PROVIDER'
  mailMessage.value = ''
}

async function loadMailSetup() {
  try {
    const result = await api.getSetupStatus()
    if (result?.fields) {
      for (const f of result.fields) {
        if (f.key in mailForm.value) {
          mailForm.value[f.key] = f.default || ''
        }
      }
    }
    if (result?.provider) mailForm.value.MAIL_PROVIDER = result.provider
    mailInitialSnapshot.value = JSON.stringify(mailForm.value)
  } catch (e) {
    console.error('加载邮箱后端配置失败:', e)
  }
}

onMounted(loadMailSetup)
</script>
