<template>
  <div class="h-full w-full overflow-hidden bg-gradient-to-br from-slate-100 to-slate-200">
    <div v-if="pageMode === 'config'" class="h-full overflow-auto p-6">
      <div class="mx-auto max-w-5xl pb-8">
        <div class="rounded-2xl bg-white p-8 shadow-xl">
          <div class="mb-4 flex items-end justify-between gap-6">
            <div>
              <h1 class="text-2xl font-semibold text-gray-900">自动私信工作台（TK版）</h1>
            </div>
            <div class="flex items-center gap-3">
              <span :class="statusChipClass">{{ statusText }}</span>
              <button @click="handlePrepareViews" :disabled="isPrepareButtonDisabled"
                class="flex items-center gap-2 rounded-lg bg-gradient-to-r from-emerald-500 to-teal-500 px-4 py-2 text-sm text-white shadow-sm transition-all hover:from-emerald-600 hover:to-teal-600 disabled:cursor-not-allowed disabled:opacity-60">
                <span>{{ isPreparing ? '预热中...' : '预热视图' }}</span>
              </button>
              <button @click="openBrowserView" :disabled="isPreparing || !isElectronEnv"
                class="flex items-center gap-2 rounded-lg bg-gradient-to-r from-blue-500 to-cyan-500 px-4 py-2 text-sm text-white shadow-sm transition-all hover:from-blue-600 hover:to-cyan-600 disabled:cursor-not-allowed disabled:opacity-60">
                <span>打开浏览器视图</span>
              </button>
            </div>
          </div>

          <div
            class="mb-6 flex w-fit items-center gap-2 rounded-full border border-blue-200 bg-gradient-to-r from-blue-50 to-green-50 px-4 py-2 text-sm text-gray-700">
            <span class="h-2 w-2 animate-pulse rounded-full bg-green-500" />
            先填写配置，再预热视图，登录完成后再启动脚本。
          </div>

          <div v-if="isConfigLocked"
            class="mb-6 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm leading-6 text-amber-800">
            当前配置已锁定。停止任务成功后，才可以修改配置、重新预热并再次启动。
          </div>

          <div class="grid grid-cols-3 gap-6">
            <div class="col-span-2 space-y-6">
              <section class="rounded-xl border border-gray-200 bg-gradient-to-b from-white to-gray-50 p-6 shadow-sm">
                <div class="mb-6 flex items-center justify-between">
                  <div class="flex items-center gap-2">
                    <span class="h-4 w-1 rounded-full bg-gradient-to-b from-blue-500 to-green-500" />
                    <span class="font-medium text-gray-900">运行参数</span>
                  </div>
                  <div class="grid grid-cols-3 gap-3 text-center">
                    <div class="min-w-[88px] rounded-lg border border-gray-200 bg-white px-3 py-2">
                      <div class="text-[10px] text-gray-500">话术数</div>
                      <div class="mt-1 text-base font-semibold text-gray-800">{{ greetingCount }}</div>
                    </div>
                    <div class="min-w-[88px] rounded-lg border border-gray-200 bg-white px-3 py-2">
                      <div class="text-[10px] text-gray-500">数据池</div>
                      <div class="mt-1 text-base font-semibold text-gray-800">{{ dataPoolLabel }}</div>
                    </div>
                    <div class="min-w-[88px] rounded-lg border border-gray-200 bg-white px-3 py-2">
                      <div class="text-[10px] text-gray-500">开启视图</div>
                      <div class="mt-1 text-base font-semibold text-gray-800">{{ totalEnabledViews }}</div>
                    </div>
                  </div>
                </div>

                <div class="space-y-5">
                  <div class="rounded-xl border border-gray-200 bg-white p-4">
                    <div class="flex items-center justify-between gap-4">
                      <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700">打招呼内容</label>
                      </div>
                      <button @click="showGreetingDialog = true" :disabled="isConfigControlDisabled"
                        class="rounded-lg border border-blue-200 bg-blue-50 px-4 py-2 text-sm font-medium text-blue-600 transition-colors hover:bg-blue-100 disabled:cursor-not-allowed disabled:opacity-60">
                        打招呼内容配置
                      </button>
                    </div>
                    <div class="mt-3 flex items-center gap-3 text-xs text-gray-500">
                      <span class="rounded-full border border-gray-200 bg-gray-100 px-3 py-1">基础话术 {{ greetingCount }}
                        条</span>
                      <span class="rounded-full border border-gray-200 bg-gray-100 px-3 py-1">翻译 {{
                        configForm.needTranslate ? '已开启' : '未开启' }}</span>
                      <span class="rounded-full border border-gray-200 bg-gray-100 px-3 py-1">语种 {{ languageCount
                      }}</span>
                    </div>
                  </div>

                  <div
                    class="rounded-xl border border-gray-200 bg-gradient-to-br from-slate-50 via-white to-blue-50/40 p-4">
                    <div class="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between">
                      <div>
                        <div class="text-sm font-medium text-gray-900">运行设置</div>
                        <p class="text-xs text-gray-500">控制分组轮换、单用户节奏，以及首次进入全流程的分组。</p>
                      </div>
                      <span
                        class="rounded-full border border-gray-200 bg-white px-3 py-1 text-xs text-gray-600">启动前生效</span>
                    </div>
                    <div class="mt-4 grid grid-cols-1 gap-3 md:grid-cols-2">
                      <div class="rounded-xl border border-gray-200 bg-white/90 p-3 shadow-sm">
                        <div class="mb-2 flex items-center justify-between gap-2">
                          <span class="text-xs font-medium text-gray-500">轮换间隔</span>
                          <span class="text-[11px] text-gray-400">分钟</span>
                        </div>
                        <input v-model.number="configForm.groupSwitchMinutes" :disabled="isConfigControlDisabled"
                          type="number" min="1" step="1"
                          class="h-11 w-full rounded-lg border border-gray-300 bg-white px-4 text-sm text-gray-800 outline-none focus:border-blue-500 disabled:cursor-not-allowed disabled:opacity-60"
                          @blur="handleSwitchMinutesBlur" />
                      </div>
                      <div class="rounded-xl border border-gray-200 bg-white/90 p-3 shadow-sm">
                        <div class="mb-2 flex items-center justify-between gap-2">
                          <span class="text-xs font-medium text-gray-500">用户休眠</span>
                          <span class="text-[11px] text-gray-400">秒</span>
                        </div>
                        <input v-model.number="configForm.postUserSleepSeconds" :disabled="isConfigControlDisabled"
                          type="number" min="1" step="1"
                          class="h-11 w-full rounded-lg border border-gray-300 bg-white px-4 text-sm text-gray-800 outline-none focus:border-blue-500 disabled:cursor-not-allowed disabled:opacity-60"
                          @blur="handlePostUserSleepBlur" />
                      </div>

                      <label v-if="!isBrotherInfoMode"
                        class="flex min-h-[92px] flex-col justify-between rounded-xl border border-gray-200 bg-white/90 p-3 shadow-sm">
                        <span class="text-xs font-medium text-gray-500">未读消息处理</span>
                        <span
                          class="flex h-11 items-center gap-3 rounded-lg border border-gray-200 bg-gray-50 px-4 text-sm text-gray-700">
                          <input v-model="configForm.replyUnreadMessages" :disabled="isConfigControlDisabled"
                            type="checkbox" class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
                          <span>开启 AI 回复未读消息</span>
                        </span>
                      </label>
                    </div>
                  </div>

                  <div class="rounded-xl border border-gray-200 bg-white p-4">
                    <div class="mb-4 flex items-center justify-between gap-4">
                      <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700">数据池来源</label>
                        <p class="text-xs text-gray-500">启动时只需告诉后端用主播池还是大哥池。</p>
                      </div>
                      <span class="rounded-full border border-gray-200 bg-gray-100 px-3 py-1 text-xs text-gray-600">{{
                        dataPoolLabel }}</span>
                    </div>
                    <div class="grid grid-cols-1 gap-3 sm:grid-cols-2">
                      <label class="flex items-center gap-3 rounded-lg border px-4 py-3 text-sm transition-colors"
                        :class="configForm.dataPoolSource === 'anchor_hosts' ? 'border-blue-500 bg-blue-50 text-blue-700' : 'border-gray-200 bg-gray-50 text-gray-700'">
                        <input v-model="configForm.dataPoolSource" :disabled="isConfigControlDisabled" type="radio"
                          value="anchor_hosts" class="h-4 w-4 border-gray-300 text-blue-600 focus:ring-blue-500" />
                        <span>主播池</span>
                      </label>
                      <label class="flex items-center gap-3 rounded-lg border px-4 py-3 text-sm transition-colors"
                        :class="configForm.dataPoolSource === 'brother_info' ? 'border-purple-500 bg-purple-50 text-purple-700' : 'border-gray-200 bg-gray-50 text-gray-700'">
                        <input v-model="configForm.dataPoolSource" :disabled="isConfigControlDisabled" type="radio"
                          value="brother_info" class="h-4 w-4 border-gray-300 text-purple-600 focus:ring-purple-500" />
                        <span>大哥池</span>
                      </label>
                    </div>
                    <!-- <div v-if="isBrotherInfoMode" class="mt-4">
                      <div class="mb-2 flex items-center justify-between gap-3">
                        <label class="block text-sm font-medium text-gray-700">大哥随机回复话术</label>
                        <span class="rounded-full border border-gray-200 bg-gray-100 px-3 py-1 text-xs text-gray-600">{{
                          replyMessageCount }} 条</span>
                      </div>
                      <textarea v-model="configForm.replyMessagesText" :disabled="isConfigControlDisabled" rows="5"
                        placeholder="一行一条回复话术，启动时传给后端 replyMessages"
                        class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-sm text-gray-800 outline-none focus:border-purple-500 disabled:cursor-not-allowed disabled:opacity-60" />
                    </div> -->
                  </div>
                </div>
              </section>

              <section class="rounded-xl border border-gray-200 bg-gradient-to-b from-white to-gray-50 p-6 shadow-sm">
                <div class="mb-4 flex items-center justify-between">
                  <div class="flex items-center gap-2">
                    <span class="h-4 w-1 rounded-full bg-gradient-to-b from-purple-500 to-blue-500" />
                    <span class="font-medium text-gray-900">视图分组</span>
                  </div>
                  <span class="text-xs text-gray-500">每组支持 0-3 个视图</span>
                  <div class="mt-2 text-sm font-medium text-gray-800">第 {{ effectiveInitialFullGroupNumber }} 组起始全流程
                  </div>
                </div>

                <div class="grid grid-cols-3 gap-4">
                  <div v-for="(count, index) in configForm.groupViewCounts" :key="index"
                    :class="['rounded-xl border p-4 transition-all', count > 0 ? 'cursor-pointer bg-white hover:border-blue-300 hover:shadow-sm' : 'bg-gray-50', effectiveInitialFullGroupNumber === index + 1 ? 'border-blue-500 ring-2 ring-blue-100' : 'border-gray-200']"
                    @click="handleSelectInitialFullGroup(index)">
                    <div class="flex items-center justify-between gap-2">
                      <div>
                        <div class="text-sm font-medium text-gray-800">第 {{ index + 1 }} 组</div>
                        <div class="mt-1 text-xs text-gray-500">{{ groupRangeLabel(index) }}</div>
                      </div>
                      <span
                        :class="['rounded-full px-2 py-1 text-[10px]', effectiveInitialFullGroupNumber === index + 1 ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 text-gray-600']">
                        {{ effectiveInitialFullGroupNumber === index + 1 ? '全流程' : groupViewText(count) }}
                      </span>
                    </div>
                    <div class="mt-3 text-[11px] text-gray-500">
                      {{ count > 0 ? '点击此卡片设为起始全流程组' : '当前分组未启用，无法作为起始组' }}
                    </div>
                    <input v-model.number="configForm.groupViewCounts[index]" :disabled="isConfigControlDisabled"
                      type="number" min="0" max="3" step="1"
                      class="mt-4 h-11 w-full rounded-lg border border-gray-300 bg-gray-50 px-4 text-sm text-gray-800 outline-none focus:border-blue-500 disabled:cursor-not-allowed disabled:opacity-60"
                      @click.stop @blur="handleGroupCountBlur(index)" />
                  </div>
                </div>
              </section>
            </div>

            <div class="space-y-6">
              <section class="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
                <div class="flex items-center justify-between">
                  <div>
                    <div class="text-sm font-medium text-gray-900">AI 人设</div>
                  </div>
                  <span
                    :class="['rounded-full px-3 py-1 text-xs font-medium', aiConfigured ? 'bg-green-100 text-green-700' : 'bg-yellow-100 text-yellow-700']">{{
                      aiConfigured ? '已配置' : '未配置' }}</span>
                </div>
                <button @click="showAIDialog = true" :disabled="isConfigControlDisabled"
                  class="mt-4 w-full rounded-lg border border-blue-200 bg-blue-50 px-4 py-3 text-sm font-medium text-blue-600 transition-colors hover:bg-blue-100">配置
                  / 修改 AI 人设</button>
              </section>

              <section class="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
                <div class="text-sm font-medium text-gray-900">执行主播库</div>
                <button @click="showHostDialog = true"
                  class="mt-4 w-full rounded-lg border border-purple-200 bg-purple-50 px-4 py-3 text-sm font-medium text-purple-600 transition-colors hover:bg-purple-100">打开执行主播库</button>
              </section>

              <section class="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
                <div class="flex items-start justify-between gap-3">
                  <div>
                    <div class="text-sm font-medium text-gray-900">大哥池</div>
                    <p class="mt-1 text-xs leading-5 text-gray-500">参考 brother_info 数据池，维护大哥列表并支持切换为大哥池模式启动任务。</p>
                  </div>
                  <span
                    :class="['rounded-full px-3 py-1 text-xs font-medium', isBrotherInfoMode ? 'bg-fuchsia-100 text-fuchsia-700' : 'bg-gray-100 text-gray-600']">{{
                      isBrotherInfoMode ? '当前使用中' : '可切换' }}</span>
                </div>
                <button @click="showBrotherInfoDialog = true"
                  class="mt-4 w-full rounded-lg border border-fuchsia-200 bg-fuchsia-50 px-4 py-3 text-sm font-medium text-fuchsia-600 transition-colors hover:bg-fuchsia-100">打开大哥池</button>
              </section>

              <!-- <section class="rounded-xl bg-slate-950 p-5 shadow-sm">
                <div class="text-sm font-medium text-slate-100">本次提交参数</div>
                <pre class="mt-3 overflow-x-auto text-xs leading-6 text-slate-300">{{ payloadPreview }}</pre>
              </section> -->
            </div>
          </div>

          <div v-if="!isElectronEnv"
            class="mt-6 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-xs leading-5 text-amber-700">当前是
            Web 环境，无法调用 Electron 的 TikTok 自动私信能力。</div>
        </div>
      </div>
    </div>

    <div v-else class="flex h-full w-full bg-gradient-to-br from-gray-50 to-gray-100 animate-fadeIn">
      <aside :style="sidebarStyle" class="h-full flex-shrink-0 border-r border-gray-200 bg-white shadow-sm">
        <div class="m-3 mb-0 flex gap-2">
          <button @click="backToConfig"
            class="flex-1 rounded-lg border border-gray-200 bg-gray-100 px-3 py-2 text-left text-xs text-gray-700 transition-colors hover:bg-gray-200">返回配置</button>
          <button @click="handleStop" :disabled="isStopping || !isElectronEnv"
            class="rounded-lg bg-red-500 px-3 py-2 text-xs text-white transition-colors hover:bg-red-600 disabled:cursor-not-allowed disabled:opacity-50">{{
              isStopping ? '停止中' : '停止任务' }}</button>
        </div>
        <div class="border-b border-gray-200 p-4">
          <h1 class="bg-gradient-to-r from-blue-600 to-cyan-500 bg-clip-text text-lg font-bold text-transparent">
            自动私信（TK版）</h1>
          <p class="mt-1 text-xs text-gray-500">浏览器视图页，位置与 BrowserView 完全对齐</p>
        </div>
        <div class="space-y-4 overflow-auto p-4">
          <div class="rounded-xl border border-gray-200 bg-gray-50 p-4">
            <div class="mb-3 text-xs font-semibold uppercase tracking-wider text-gray-500">视图分组</div>
            <div class="space-y-3">
              <div v-for="group in browserViewGroups" :key="group.groupIndex"
                class="rounded-lg border border-gray-200 bg-white p-3">
                <div class="mb-2 flex items-center justify-between">
                  <span class="text-sm font-medium text-gray-800">第 {{ group.groupIndex + 1 }} 组</span>
                  <span class="text-xs text-gray-500">{{ group.label }}</span>
                </div>
                <div class="grid grid-cols-3 gap-2">
                  <button v-for="view in group.views" :key="view.viewId"
                    :disabled="!view.enabled || isSwitchingView || !isElectronEnv"
                    @click="handleSwitchView(view.viewId)"
                    :class="['h-10 rounded-lg border text-sm font-medium transition-all disabled:cursor-not-allowed', view.active ? 'border-blue-500 bg-blue-500 text-white shadow-sm' : view.enabled ? 'border-gray-200 bg-gray-50 text-gray-700 hover:border-blue-300 hover:bg-blue-50' : 'border-dashed border-gray-200 bg-gray-100 text-gray-400 opacity-70']">{{
                      view.viewId }}</button>
                </div>
              </div>
            </div>
          </div>
          <div class="rounded-xl border border-gray-200 bg-gray-50 p-4">
            <div class="mb-3 text-xs font-semibold uppercase tracking-wider text-gray-500">快速操作</div>
            <div class="space-y-3">
              <label
                class="flex items-center gap-3 rounded-lg border border-gray-200 bg-white px-3 py-3 text-sm text-gray-700">
                <input v-model="loginConfirmed" :disabled="isStarting || !isElectronEnv" type="checkbox"
                  class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
                <span>当前视图已完成手动登录</span>
              </label>
              <button
                class="h-9 w-full rounded-lg border border-blue-600 bg-blue-600 text-sm text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60"
                :disabled="isStarting || !isElectronEnv" @click="handleStart">{{ isStarting ? '启动中...' : '启动任务'
                }}</button>
              <div class="text-xs leading-5 text-gray-500">先打开浏览器视图，在当前视图里手动登录账号；确认登录完成后，再勾选并启动脚本。</div>
            </div>
          </div>
        </div>
      </aside>

      <main class="relative flex min-w-0 flex-1 flex-col">
        <div class="flex h-12 items-center gap-2 border-b border-gray-200 bg-white px-4 shadow-sm">
          <span class="mr-2 text-sm text-gray-500">视图:</span>
          <button v-for="viewId in viewIds" :key="viewId" @click="handleSwitchView(viewId)"
            :disabled="isSwitchingView || !isElectronEnv"
            :class="['rounded-lg px-3 py-1.5 text-sm font-medium transition-all disabled:cursor-not-allowed disabled:opacity-60', activeViewId === viewId ? 'bg-blue-500 text-white shadow-md' : 'border border-gray-200 bg-gray-100 text-gray-600 hover:bg-gray-200']">视图
            {{ viewId }}</button>
          <div class="flex-1" />
          <span class="rounded border border-gray-200 bg-gray-100 px-2 py-1 text-xs text-gray-500">{{ statusText
          }}</span>
          <span v-if="isSwitchingView"
            class="rounded border border-blue-200 bg-blue-50 px-2 py-1 text-xs text-blue-600">切换中...</span>
        </div>
        <div class="relative flex-1">
          <ViewPlaceholder class="absolute inset-0" />
        </div>
      </main>
    </div>

    <AIConfigDialog :visible="showAIDialog" :config="aiConfig" @close="showAIDialog = false" @save="handleSaveAIConfig"
      @change="(key, value) => aiConfig[key] = value" />
    <HostListDialog :visible="showHostDialog" @close="showHostDialog = false" @save="() => { }" />
    <BrotherInfoDialog :visible="showBrotherInfoDialog" @close="showBrotherInfoDialog = false" />
    <GreetingDialog :visible="showGreetingDialog" @close="showGreetingDialog = false"
      @confirm="handleGreetingConfirm" />
  </div>
</template>

<script setup>
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { isElectron } from '@/utils/electronBridge'
import ViewPlaceholder from '@/components/ViewPlaceholder.vue'
import HostListDialog from '@/components/HostListDialog.vue'
import AIConfigDialog from '@/components/AIConfigDialog.vue'
import GreetingDialog from '@/components/GreetingDialog.vue'
import BrotherInfoDialog from '@/components/BrotherInfoDialog.vue'

const props = defineProps({ navSidebarWidth: { type: Number, default: 144 } })
const TIKTOK_VIEW_IDS = Array.from({ length: 9 }, (_, index) => index + 10)
const DEFAULT_GROUP_COUNTS = [3, 3, 3]
const DEFAULT_INITIAL_FULL_GROUP_NUMBER = 1
const isElectronEnv = isElectron()
const pageMode = ref('config')
const activeViewId = ref(TIKTOK_VIEW_IDS[0])
const statusText = ref('待启动')
const showAIDialog = ref(false)
const showHostDialog = ref(false)
const showGreetingDialog = ref(false)
const showBrotherInfoDialog = ref(false)
const aiConfigured = ref(false)
const loginConfirmed = ref(false)
const preparedConfigKey = ref('')
const workbenchPhase = ref('idle')
const isPreparing = ref(false)
const isStarting = ref(false)
const isStopping = ref(false)
const isSwitchingView = ref(false)
const configForm = reactive({ prologueList: {}, needTranslate: false, dataPoolSource: 'anchor_hosts', replyMessagesText: '', replyUnreadMessages: true, groupSwitchMinutes: 10, initialFullGroupNumber: DEFAULT_INITIAL_FULL_GROUP_NUMBER, postUserSleepSeconds: 6, groupViewCounts: [...DEFAULT_GROUP_COUNTS] })
const aiConfig = ref({ agentName: '', guildName: '', contactTool: '', contact: '' })
const sidebarStyle = computed(() => ({ width: `${props.navSidebarWidth}px`, minWidth: '96px', maxWidth: '400px' }))
const greetingMessages = computed(() => {
  const baseMessages = Array.isArray(configForm.prologueList?.yolo) ? configForm.prologueList.yolo : []
  return baseMessages.map(item => String(item || '').trim()).filter(Boolean)
})
const replyMessages = computed(() => String(configForm.replyMessagesText || '').split(/\r?\n/).map(item => item.trim()).filter(Boolean))
const greetingCount = computed(() => greetingMessages.value.length)
const replyMessageCount = computed(() => replyMessages.value.length)
const languageCount = computed(() => Object.keys(configForm.prologueList || {}).length)
const isBrotherInfoMode = computed(() => configForm.dataPoolSource === 'brother_info')
const effectiveReplyUnreadMessages = computed(() => !isBrotherInfoMode.value && Boolean(configForm.replyUnreadMessages))
const dataPoolLabel = computed(() => (isBrotherInfoMode.value ? '大哥池' : '主播池'))
const normalizedGroupSwitchMinutes = computed(() => clampMinutes(configForm.groupSwitchMinutes))
const normalizedGroupViewCounts = computed(() => normalizeGroupViewCounts(configForm.groupViewCounts))
const effectiveInitialFullGroupNumber = computed(() => resolveInitialFullGroupNumber(configForm.initialFullGroupNumber, normalizedGroupViewCounts.value))
const browserViewGroups = computed(() => normalizedGroupViewCounts.value.map((enabledCount, groupIndex) => {
  const baseViewId = TIKTOK_VIEW_IDS[groupIndex * 3]
  return { groupIndex, label: `视图 ${baseViewId}-${baseViewId + 2}`, views: Array.from({ length: 3 }, (_, offset) => ({ viewId: baseViewId + offset, enabled: offset < enabledCount, active: activeViewId.value === baseViewId + offset })) }
}))
const viewIds = computed(() => browserViewGroups.value.flatMap(group => group.views.filter(view => view.enabled).map(view => view.viewId)))
const totalEnabledViews = computed(() => normalizedGroupViewCounts.value.reduce((sum, count) => sum + count, 0))
const payloadPreview = computed(() => JSON.stringify(buildStartPayload(), null, 2))
const currentPrepareKey = computed(() => JSON.stringify({ groupViewCounts: normalizedGroupViewCounts.value, groupSwitchMinutes: normalizedGroupSwitchMinutes.value, initialFullGroupNumber: effectiveInitialFullGroupNumber.value, postUserSleepSeconds: normalizedPostUserSleepSeconds.value, replyUnreadMessages: effectiveReplyUnreadMessages.value, dataPoolSource: configForm.dataPoolSource, replyMessages: replyMessages.value, prologueList: configForm.prologueList || {}, needTranslate: Boolean(configForm.needTranslate) }))
const hasPreparedViews = computed(() => preparedConfigKey.value === currentPrepareKey.value)
const isConfigLocked = computed(() => workbenchPhase.value !== 'idle')
const isConfigControlDisabled = computed(() => !isElectronEnv || isPreparing.value || isStarting.value || isStopping.value || isConfigLocked.value)
const isPrepareButtonDisabled = computed(() => !isElectronEnv || isPreparing.value || isStarting.value || isStopping.value || isConfigLocked.value)
const statusChipClass = computed(() => statusText.value.includes('运行') ? 'rounded-full border border-emerald-200 bg-emerald-50 px-3 py-1 text-xs font-medium text-emerald-700' : statusText.value.includes('失败') ? 'rounded-full border border-rose-200 bg-rose-50 px-3 py-1 text-xs font-medium text-rose-700' : 'rounded-full border border-amber-200 bg-amber-50 px-3 py-1 text-xs font-medium text-amber-700')
function clampMinutes(value) { const numericValue = Number(value); return !Number.isFinite(numericValue) || numericValue <= 0 ? 10 : Math.max(1, Math.round(numericValue)) }
function clampPositiveSeconds(value, fallback = 6) { const numericValue = Number(value); return !Number.isFinite(numericValue) || numericValue <= 0 ? fallback : Math.max(1, Math.round(numericValue)) }
function clampGroupCount(value) { const numericValue = Number(value); return !Number.isFinite(numericValue) ? 0 : Math.min(3, Math.max(0, Math.round(numericValue))) }
function clampInitialFullGroupNumber(value) { const numericValue = Number(value); return !Number.isFinite(numericValue) ? DEFAULT_INITIAL_FULL_GROUP_NUMBER : Math.min(DEFAULT_GROUP_COUNTS.length, Math.max(1, Math.round(numericValue))) }
function normalizeGroupViewCounts(values) { const safeValues = Array.isArray(values) ? values.slice(0, 3) : []; while (safeValues.length < 3) safeValues.push(0); return safeValues.map(clampGroupCount) }
function resolveInitialFullGroupNumber(value, groupViewCounts) { const requestedGroupNumber = clampInitialFullGroupNumber(value); for (let offset = 0; offset < groupViewCounts.length; offset += 1) { const candidateIndex = (requestedGroupNumber - 1 + offset) % groupViewCounts.length; if ((groupViewCounts[candidateIndex] || 0) > 0) return candidateIndex + 1 } return requestedGroupNumber }
const normalizedPostUserSleepSeconds = computed(() => clampPositiveSeconds(configForm.postUserSleepSeconds, 6))
function buildStartPayload() {
  const payload = { dataPoolSource: configForm.dataPoolSource, replyUnreadMessages: effectiveReplyUnreadMessages.value, groupSwitchMinutes: normalizedGroupSwitchMinutes.value, initialFullGroupNumber: effectiveInitialFullGroupNumber.value, postUserSleepSeconds: normalizedPostUserSleepSeconds.value, groupViewCounts: normalizedGroupViewCounts.value, prologueList: JSON.parse(JSON.stringify(configForm.prologueList || {})), needTranslate: Boolean(configForm.needTranslate) }
  if (greetingMessages.value.length > 0) payload.greetingMessages = greetingMessages.value
  if (replyMessages.value.length > 0) payload.replyMessages = replyMessages.value
  return payload
}
function ensureElectronCapability(methodName) { if (!isElectronEnv || !window.electronAPI?.[methodName]) { ElMessage.error('当前环境不支持该功能'); return false } return true }
function invalidatePreparedState(nextStatus = '配置已变更，请重新预热视图') { preparedConfigKey.value = ''; loginConfirmed.value = false; if (!statusText.value.includes('运行')) statusText.value = nextStatus }
async function syncWorkbenchState() {
  if (!isElectronEnv || !window.electronAPI?.getStandaloneTikTokWorkbenchState) return
  try {
    const state = await window.electronAPI.getStandaloneTikTokWorkbenchState()
    workbenchPhase.value = state?.phase || 'idle'
    if (state?.locked) {
      preparedConfigKey.value = currentPrepareKey.value
      if (state.phase === 'running') {
        statusText.value = '运行中'
      } else if (!statusText.value.includes('运行')) {
        statusText.value = '视图已预热，当前配置已锁定'
      }
    } else {
      preparedConfigKey.value = ''
    }
  } catch (error) {
    console.error('sync standalone tiktok workbench state failed:', error)
  }
}
async function showBrowserWorkspace(viewId, fallbackStatusText) {
  pageMode.value = 'browser'
  await window.electronAPI.switchToView(viewId)
  await window.electronAPI.showViews()
  if (!statusText.value.includes('运行')) statusText.value = fallbackStatusText
}
function handleGreetingConfirm(data) { configForm.prologueList = { yolo: data.sentences || [], ...(data.translations || {}) }; configForm.needTranslate = Boolean(data.needTranslate); showGreetingDialog.value = false; invalidatePreparedState(); void saveSharedConfig() }
function handleSwitchMinutesBlur() { configForm.groupSwitchMinutes = clampMinutes(configForm.groupSwitchMinutes); invalidatePreparedState() }
function handleSelectInitialFullGroup(index) { if (isConfigControlDisabled.value) return; if ((normalizedGroupViewCounts.value[index] || 0) <= 0) return; const nextGroupNumber = index + 1; if (configForm.initialFullGroupNumber === nextGroupNumber) return; configForm.initialFullGroupNumber = nextGroupNumber; invalidatePreparedState('全流程起始分组已变更，请重新预热视图'); void saveSharedConfig() }
function handlePostUserSleepBlur() { configForm.postUserSleepSeconds = clampPositiveSeconds(configForm.postUserSleepSeconds, 6); invalidatePreparedState() }
function handleGroupCountBlur(index) { configForm.groupViewCounts[index] = clampGroupCount(configForm.groupViewCounts[index]); configForm.initialFullGroupNumber = effectiveInitialFullGroupNumber.value; invalidatePreparedState('视图配置已变更，请重新预热视图') }
function groupViewText(count) { return count <= 0 ? '不启用' : `开启 ${count} 个` }
function groupRangeLabel(index) { const startViewId = TIKTOK_VIEW_IDS[index * 3]; const endViewId = TIKTOK_VIEW_IDS[index * 3 + 2]; return `视图 ${startViewId}-${endViewId}` }
async function checkAIConfig() {
  if (!isElectronEnv || !window.electronAPI?.loadAIConfig) return
  try {
    const saved = await window.electronAPI.loadAIConfig()
    aiConfigured.value = Boolean(saved && (saved.agentName || saved.guildName || saved.contactTool || saved.contact))
    if (aiConfigured.value) aiConfig.value = saved
  } catch {
    aiConfigured.value = false
  }
}
async function handleSaveAIConfig() {
  if (isElectronEnv && window.electronAPI?.saveAIConfig) {
    await window.electronAPI.saveAIConfig(JSON.parse(JSON.stringify(aiConfig.value)))
  }
  aiConfigured.value = true
  showAIDialog.value = false
}
async function loadSharedConfig() {
  if (!isElectronEnv || !window.electronAPI?.loadRunConfig) return
  try {
    const saved = await window.electronAPI.loadRunConfig()
    if (saved?.prologueList && typeof saved.prologueList === 'object') configForm.prologueList = JSON.parse(JSON.stringify(saved.prologueList))
    if (typeof saved?.needTranslate === 'boolean') configForm.needTranslate = saved.needTranslate
    if (saved?.standaloneTikTokDataPoolSource === 'anchor_hosts' || saved?.standaloneTikTokDataPoolSource === 'brother_info') configForm.dataPoolSource = saved.standaloneTikTokDataPoolSource
    if (Array.isArray(saved?.standaloneTikTokReplyMessages)) configForm.replyMessagesText = saved.standaloneTikTokReplyMessages.join('\n')
    if (saved?.standaloneTikTokInitialFullGroupNumber !== undefined) configForm.initialFullGroupNumber = clampInitialFullGroupNumber(saved.standaloneTikTokInitialFullGroupNumber)
    if (saved?.standaloneTikTokPostUserSleepSeconds !== undefined) configForm.postUserSleepSeconds = clampPositiveSeconds(saved.standaloneTikTokPostUserSleepSeconds, 6)
  } catch (error) {
    console.error('load shared config failed:', error)
  }
}
async function saveSharedConfig() {
  if (!isElectronEnv || !window.electronAPI?.saveRunConfig || !window.electronAPI?.loadRunConfig) return
  try {
    const saved = await window.electronAPI.loadRunConfig()
    const nextConfig = {
      ...(saved || {}),
      prologueList: JSON.parse(JSON.stringify(configForm.prologueList || {})),
      needTranslate: Boolean(configForm.needTranslate),
      standaloneTikTokDataPoolSource: configForm.dataPoolSource,
      standaloneTikTokReplyMessages: replyMessages.value,
      standaloneTikTokInitialFullGroupNumber: effectiveInitialFullGroupNumber.value,
      standaloneTikTokPostUserSleepSeconds: normalizedPostUserSleepSeconds.value
    }
    await window.electronAPI.saveRunConfig(nextConfig)
  } catch (error) {
    console.error('save shared config failed:', error)
  }
}
async function handlePrepareViews() {
  if (!ensureElectronCapability('prepareStandaloneTikTokViews')) return
  if (isConfigLocked.value) {
    ElMessage.warning('当前配置已锁定，请先停止任务后再修改配置或重新预热')
    return
  }
  if (viewIds.value.length === 0) {
    ElMessage.warning('请至少启用一个视图后再预热')
    return
  }
  loginConfirmed.value = false
  isPreparing.value = true
  try {
    const result = await window.electronAPI.prepareStandaloneTikTokViews({ groupViewCounts: normalizedGroupViewCounts.value, targetViewId: activeViewId.value })
    if (!result?.success) throw new Error(result?.error || 'prepare standalone tiktok views failed')
    if (result.currentViewId) activeViewId.value = result.currentViewId
    workbenchPhase.value = 'prepared'
    preparedConfigKey.value = currentPrepareKey.value
    await saveSharedConfig()
    if (pageMode.value === 'config') {
      await window.electronAPI.hideViews()
    }
    statusText.value = `视图已预热，请先在视图 ${activeViewId.value} 手动登录，再启动脚本`
    ElMessage.success('视图预热完成，请切换到浏览器视图')
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error)
    ElMessage.error(`预热视图失败：${message}`)
  } finally {
    isPreparing.value = false
  }
}
async function openBrowserView() {
  if (!ensureElectronCapability('switchToView')) return
  if (isPreparing.value) {
    ElMessage.warning('视图预热中，请等待预热完成后再打开浏览器视图')
    return
  }
  try {
    await showBrowserWorkspace(
      activeViewId.value,
      hasPreparedViews.value
        ? `已打开预热视图 ${activeViewId.value}，请手动登录后启动脚本`
        : '当前配置尚未预热，请先返回工作台执行预热视图'
    )
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error)
    pageMode.value = 'config'
    ElMessage.error(`打开浏览器视图失败：${message}`)
  }
}
async function backToConfig() {
  loginConfirmed.value = false
  pageMode.value = 'config'
  if (!isElectronEnv || !window.electronAPI?.hideViews) return
  try {
    await window.electronAPI.hideViews()
  } catch (error) {
    console.error('hide views failed:', error)
  }
}
async function handleSwitchView(viewId) {
  if (!ensureElectronCapability('switchToView')) return
  isSwitchingView.value = true
  try {
    await window.electronAPI.switchToView(viewId)
    loginConfirmed.value = false
    activeViewId.value = viewId
    statusText.value = `已切换到视图 ${viewId}，请先手动登录再启动脚本`
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error)
    statusText.value = '切换失败'
    ElMessage.error(`切换视图失败：${message}`)
  } finally {
    isSwitchingView.value = false
  }
}
async function handleStart() {
  if (!ensureElectronCapability('startStandaloneTikTokAutomationAll')) return
  if (workbenchPhase.value === 'running') {
    ElMessage.warning('当前任务已在运行中，请先停止后再重新启动')
    return
  }
  if (!hasPreparedViews.value) {
    ElMessage.warning('请先完成当前配置对应的视图预热，再启动脚本')
    return
  }
  if (!loginConfirmed.value) {
    ElMessage.warning('请先在当前视图手动登录，并勾选“当前视图已完成手动登录”后再启动脚本')
    return
  }
  isStarting.value = true
  try {
    await saveSharedConfig()
    await showBrowserWorkspace(activeViewId.value, `已打开预热视图 ${activeViewId.value}，请手动登录后启动脚本`)
    const result = await window.electronAPI.startStandaloneTikTokAutomationAll(buildStartPayload())
    if (!result?.success) {
      statusText.value = '启动失败'
      ElMessage.error(result?.error || '启动自动私信（TK版）失败')
      return
    }
    workbenchPhase.value = 'running'
    statusText.value = `运行中（视图 ${activeViewId.value}）`
    ElMessage.success('自动私信（TK版）已启动')
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error)
    statusText.value = '启动失败'
    ElMessage.error(`启动失败：${message}`)
  } finally {
    isStarting.value = false
  }
}
async function handleStop() {
  if (!ensureElectronCapability('stopStandaloneTikTokAutomationAll')) return
  isStopping.value = true
  try {
    const result = await window.electronAPI.stopStandaloneTikTokAutomationAll()
    if (!result?.success) {
      statusText.value = '停止失败'
      ElMessage.error(result?.error || '停止自动私信（TK版）失败')
      return
    }
    workbenchPhase.value = 'idle'
    preparedConfigKey.value = ''
    loginConfirmed.value = false
    statusText.value = result?.message?.includes('取消预热状态') ? '已解锁' : '已停止'
    ElMessage.success('自动私信（TK版）已停止')
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error)
    statusText.value = '停止失败'
    ElMessage.error(`停止失败：${message}`)
  } finally {
    isStopping.value = false
  }
}
watch(currentPrepareKey, (nextKey, prevKey) => {
  if (!prevKey) return
  if (preparedConfigKey.value && preparedConfigKey.value !== nextKey) invalidatePreparedState()
})
watch(() => configForm.dataPoolSource, () => {
  if (isBrotherInfoMode.value && configForm.replyUnreadMessages) configForm.replyUnreadMessages = false
  invalidatePreparedState()
  void saveSharedConfig()
})
watch(() => configForm.replyMessagesText, () => {
  if (!isBrotherInfoMode.value) return
  invalidatePreparedState()
})
watch(normalizedGroupViewCounts, () => {
  const nextGroupNumber = effectiveInitialFullGroupNumber.value
  if (configForm.initialFullGroupNumber !== nextGroupNumber) configForm.initialFullGroupNumber = nextGroupNumber
})
watch(viewIds, (nextViewIds) => {
  if (nextViewIds.length === 0) {
    activeViewId.value = TIKTOK_VIEW_IDS[0]
    return
  }
  if (!nextViewIds.includes(activeViewId.value)) activeViewId.value = nextViewIds[0]
}, { immediate: true })
watch(pageMode, async (newVal) => {
  if (!isElectronEnv) return
  if (newVal === 'config' && window.electronAPI?.hideViews) await window.electronAPI.hideViews().catch(() => { })
})
onMounted(async () => {
  await checkAIConfig()
  await loadSharedConfig()
  await syncWorkbenchState()
  if (!isElectronEnv || !window.electronAPI?.hideViews) return
  await window.electronAPI.hideViews().catch(() => { })
})
onUnmounted(async () => {
  if (!isElectronEnv || !window.electronAPI?.hideViews) return
  await window.electronAPI.hideViews().catch(() => { })
})
</script>
