<template>
  <div class="shell-page shell-page-fluid page-section websites-page">
    <div class="page-header surface-card page-block">
      <div class="page-heading">
        <p class="page-kicker">Sync Orchestration</p>
        <h2 class="page-title">网站管理</h2>
        <p class="page-desc">管理自己的 sub2api 网站，并把网站分组倍率同步到上游监听结果</p>
      </div>
      <el-button type="primary" @click="openWebsiteCreate">
        <el-icon><Plus /></el-icon> 新增网站
      </el-button>
    </div>

    <div class="panel">
      <div class="panel-head">
        <div class="panel-title">网站</div>
        <div class="panel-actions">
          <el-button size="small" text :disabled="websites.length === 0" @click="openImportGroups(selectedWebsite || websites[0])">导入上游分组</el-button>
          <el-button size="small" text :disabled="websites.length === 0" @click="openImportAccounts(selectedWebsite || websites[0])">导入为账号管理账号</el-button>
          <el-button size="small" text @click="loadAll">刷新</el-button>
        </div>
      </div>
      <el-table :data="websites" v-loading="websiteLoading" row-key="id" style="width:100%">
        <el-table-column label="名称" min-width="180">
          <template #default="{ row }">
            <div class="cell-name">{{ row.name }}</div>
            <div class="cell-url">{{ row.base_url }}</div>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="110">
          <template #default="{ row }">
            <span :class="['status-badge', row.last_status]"><span class="dot" />{{ statusLabel(row.last_status) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="自动同步" width="100">
          <template #default="{ row }">
            <el-switch v-model="row.auto_sync_enabled" @change="toggleWebsiteSync(row)" />
          </template>
        </el-table-column>
        <el-table-column label="超时" width="80">
          <template #default="{ row }">{{ row.timeout_seconds }}s</template>
        </el-table-column>
        <el-table-column label="最近错误" min-width="180">
          <template #default="{ row }">
            <el-tooltip v-if="row.last_error" :content="row.last_error" placement="top" :show-after="300">
              <span class="error-text">{{ row.last_error.substring(0, 42) }}…</span>
            </el-tooltip>
            <span v-else class="muted">—</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="240" align="right">
          <template #default="{ row }">
            <div class="action-row">
              <el-tooltip content="编辑网站配置" placement="top" :show-after="300">
                <el-button size="small" text class="btn-edit" @click="openWebsiteEdit(row)">
                  <el-icon class="btn-edit-icon"><Edit /></el-icon><span>编辑</span>
                </el-button>
              </el-tooltip>
              <el-tooltip content="查看分组" placement="top" :show-after="300">
                <el-button size="small" circle text @click="selectWebsite(row)">
                  <el-icon><Grid /></el-icon>
                </el-button>
              </el-tooltip>
              <el-dropdown trigger="click" @command="(cmd: string) => handleMoreAction(cmd, row)">
                <el-button size="small" text class="btn-more" :loading="row._testing">
                  更多<el-icon v-if="!row._testing" class="el-icon--right"><ArrowDown /></el-icon>
                </el-button>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item command="test" :disabled="row._testing">
                      <el-icon><Connection /></el-icon>连接测试
                    </el-dropdown-item>
                    <el-dropdown-item command="binding">
                      <el-icon><Link /></el-icon>新增绑定
                    </el-dropdown-item>
                    <el-dropdown-item command="importGroups">
                      <el-icon><Upload /></el-icon>导入上游分组
                    </el-dropdown-item>
                    <el-dropdown-item command="importAccounts">
                      <el-icon><Key /></el-icon>导入为账号管理账号
                    </el-dropdown-item>
                    <el-dropdown-item divided command="delete" class="btn-more-delete">
                      <el-icon><Delete /></el-icon>删除
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <div class="content-grid">
      <div class="panel">
        <div class="panel-head">
          <div>
            <div class="panel-title">我的网站分组</div>
            <div class="panel-sub">{{ selectedWebsite?.name || '请选择网站' }}</div>
          </div>
          <el-select
            :model-value="selectedWebsite?.id"
            size="small"
            filterable
            class="site-switcher"
            placeholder="切换网站"
            @change="onSelectedWebsiteChange"
          >
            <el-option v-for="site in websites" :key="site.id" :label="site.name" :value="site.id" />
          </el-select>
          <el-button size="small" :disabled="!selectedWebsite" :loading="groupsLoading" @click="loadWebsiteGroups">拉取分组</el-button>
        </div>
        <el-table :data="websiteGroups" v-loading="groupsLoading" row-key="id" size="small" style="width:100%">
          <el-table-column prop="name" label="分组" min-width="150" />
          <el-table-column prop="id" label="ID" min-width="130" />
          <el-table-column label="倍率" width="100">
            <template #default="{ row }"><span class="rate-value">{{ row.rate_multiplier ?? '—' }}</span></template>
          </el-table-column>
          <el-table-column label="操作" width="90">
            <template #default="{ row }">
              <el-button size="small" text :disabled="!selectedWebsite" @click="openBindingCreate(selectedWebsite, row)">绑定</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <div class="panel">
        <div class="panel-head">
          <div>
            <div class="panel-title">分组绑定</div>
            <div class="panel-sub">{{ selectedWebsite?.name || '请选择网站' }}</div>
          </div>
          <el-select
            :model-value="selectedWebsite?.id"
            size="small"
            filterable
            class="site-switcher"
            placeholder="切换网站"
            @change="onSelectedWebsiteChange"
          >
            <el-option v-for="site in websites" :key="site.id" :label="site.name" :value="site.id" />
          </el-select>
          <el-button size="small" text :disabled="websites.length === 0" @click="openBindingCreate(selectedWebsite || websites[0])">新增绑定</el-button>
        </div>
        <div class="binding-list" v-loading="bindingLoading">
          <div v-for="binding in selectedWebsiteBindings" :key="binding.id" class="binding-item">
            <div class="binding-main">
              <div class="binding-title">{{ binding.website_name }} / {{ binding.target_group_name || binding.target_group_id }}</div>
              <div class="binding-meta">
                {{ algorithmLabel(binding.algorithm) }} + {{ binding.percent }}% ·
                {{ binding.source_groups.length }} 个上游分组
              </div>
            </div>
            <div class="binding-actions">
              <el-switch v-model="binding.enabled" @change="toggleBinding(binding)" />
              <el-button size="small" text :loading="binding._syncing" @click="syncBinding(binding)">同步</el-button>
              <el-button size="small" text @click="openBindingEdit(binding)"><el-icon><Edit /></el-icon></el-button>
              <el-button size="small" text type="danger" @click="deleteBinding(binding)"><el-icon><Delete /></el-icon></el-button>
            </div>
          </div>
          <div v-if="!bindingLoading && selectedWebsiteBindings.length === 0" class="empty-hint">暂无绑定</div>
        </div>
      </div>
    </div>

    <div class="panel">
      <div class="panel-head">
        <div class="panel-title">最近同步结果</div>
        <el-button size="small" text @click="loadLogs">刷新</el-button>
      </div>
      <el-table :data="logs" v-loading="logLoading" row-key="id" size="small" style="width:100%">
        <el-table-column label="时间" width="150">
          <template #default="{ row }">{{ fmtTime(row.created_at) }}</template>
        </el-table-column>
        <el-table-column label="目标分组" min-width="160">
          <template #default="{ row }">{{ row.target_group_name || row.target_group_id }}</template>
        </el-table-column>
        <el-table-column label="倍率" width="130">
          <template #default="{ row }">
            <span class="rate-value">{{ row.old_rate ?? '—' }} → {{ row.new_rate ?? '—' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="90">
          <template #default="{ row }">
            <el-tag size="small" :type="row.status === 'success' ? 'success' : 'danger'">{{ row.status === 'success' ? '成功' : '失败' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="message" label="结果" min-width="220" />
      </el-table>
    </div>

    <el-drawer v-model="websiteDrawer" :title="editingWebsiteId ? '编辑网站' : '新增网站'" size="460px" destroy-on-close>
      <el-form ref="websiteFormRef" :model="websiteForm" :rules="websiteRules" label-position="top">
        <el-form-item label="名称" prop="name"><el-input v-model="websiteForm.name" placeholder="我的 sub2api" /></el-form-item>
        <el-form-item label="Base URL" prop="base_url"><el-input v-model="websiteForm.base_url" placeholder="https://sub2api.example.com" /></el-form-item>
        <el-form-item label="API Prefix"><el-input v-model="websiteForm.api_prefix" placeholder="/api/v1/admin" /></el-form-item>
        <el-form-item label="认证方式">
          <el-select v-model="websiteForm.auth_type" style="width:100%">
            <el-option label="x-api-key" value="api_key" />
            <el-option label="Bearer JWT" value="bearer" />
          </el-select>
        </el-form-item>
        <template v-if="websiteForm.auth_type === 'api_key'">
          <el-form-item label="Admin API Key"><el-input v-model="websiteForm.auth_config.key" type="password" show-password placeholder="admin-..." /></el-form-item>
          <el-form-item label="Header"><el-input v-model="websiteForm.auth_config.header" placeholder="x-api-key" /></el-form-item>
        </template>
        <template v-else>
          <el-form-item label="JWT"><el-input v-model="websiteForm.auth_config.token" type="password" show-password placeholder="***" /></el-form-item>
        </template>
        <el-row :gutter="12">
          <el-col :span="12"><el-form-item label="分组接口"><el-input v-model="websiteForm.groups_endpoint" /></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="更新接口"><el-input v-model="websiteForm.group_update_endpoint" /></el-form-item></el-col>
        </el-row>
        <el-form-item label="超时（秒）"><el-input-number v-model="websiteForm.timeout_seconds" :min="5" :max="120" style="width:100%" /></el-form-item>
        <div class="switch-line">
          <span>启用网站</span><el-switch v-model="websiteForm.enabled" />
        </div>
        <div class="switch-line">
          <span>启用自动同步</span><el-switch v-model="websiteForm.auto_sync_enabled" />
        </div>
      </el-form>
      <template #footer>
        <el-button @click="websiteDrawer = false">取消</el-button>
        <el-button type="primary" :loading="savingWebsite" @click="saveWebsite">保存</el-button>
      </template>
    </el-drawer>

    <el-drawer v-model="bindingDrawer" :title="editingBindingId ? '编辑绑定' : '新增绑定'" size="560px" destroy-on-close>
      <el-form ref="bindingFormRef" :model="bindingForm" :rules="bindingRules" label-position="top">
        <el-form-item label="目标网站">
          <el-select v-model="bindingForm.website_id" style="width:100%" @change="onBindingWebsiteChange">
            <el-option v-for="site in websites" :key="site.id" :label="site.name" :value="site.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="目标分组" prop="target_group_id">
          <el-select v-model="bindingForm.target_group_id" filterable style="width:100%" @change="onTargetGroupChange">
            <el-option v-for="group in bindingWebsiteGroups" :key="group.id" :label="`${group.name} (${group.rate_multiplier ?? '—'})`" :value="group.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="监听上游分组" prop="source_group_keys">
          <el-select v-model="sourceGroupKeys" multiple filterable style="width:100%" placeholder="选择一个或多个上游分组" @change="onSourceGroupsChange">
            <el-option v-for="item in upstreamGroupOptions" :key="item.key" :label="item.label" :value="item.key" />
          </el-select>
        </el-form-item>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="算法">
              <el-select v-model="bindingForm.algorithm" style="width:100%">
                <el-option label="最高倍率 + 百分比" value="max_plus_percent" />
                <el-option label="平均倍率 + 百分比" value="average_plus_percent" />
                <el-option label="最低倍率 + 百分比" value="min_plus_percent" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="百分比">
              <el-input-number v-model="bindingForm.percent" :min="0" :precision="2" style="width:100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="启用"><el-switch v-model="bindingForm.enabled" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="bindingDrawer = false">取消</el-button>
        <el-button type="primary" :loading="savingBinding" @click="saveBinding">保存</el-button>
      </template>
    </el-drawer>

    <el-dialog v-model="importGroupsDialog" title="导入上游分组" width="680px" destroy-on-close>
      <el-form label-position="top">
        <el-form-item label="目标网站">
          <el-select v-model="importGroupsForm.website_id" style="width:100%">
            <el-option v-for="site in websites" :key="site.id" :label="site.name" :value="site.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="来源上游">
          <el-select v-model="importGroupsForm.upstream_id" filterable style="width:100%" @change="importGroupsForm.group_ids = []">
            <el-option v-for="upstream in upstreams" :key="upstream.id" :label="upstream.name" :value="upstream.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="上游分组">
          <el-select v-model="importGroupsForm.group_ids" multiple filterable style="width:100%" placeholder="不选则导入全部分组">
            <el-option
              v-for="group in importSourceGroups"
              :key="sourceGroupId(group)"
              :label="`${sourceGroupName(group)} (${group.rate || group.rate_multiplier || '—'})`"
              :value="sourceGroupId(group)"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="分组名前缀">
          <el-input v-model="importGroupsForm.name_prefix" placeholder="可留空，参数和倍率保持上游一致" />
        </el-form-item>
      </el-form>
      <div v-if="importGroupResults.length" class="result-panel">
        <div class="result-title">导入结果</div>
        <el-table :data="importGroupResults" size="small">
          <el-table-column prop="source_group_name" label="上游分组" min-width="140" />
          <el-table-column prop="target_group_name" label="我的分组" min-width="160" />
          <el-table-column prop="target_group_id" label="目标 ID" width="100" />
          <el-table-column label="状态" width="90">
            <template #default="{ row }">
              <el-tag v-if="row.status === 'created'" size="small" type="success">已创建</el-tag>
              <el-tag v-else-if="row.status === 'exists'" size="small" type="info">已存在</el-tag>
              <el-tag v-else size="small" type="danger">失败</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="message" label="结果" min-width="160" />
        </el-table>
      </div>
      <template #footer>
        <el-button @click="importGroupsDialog = false">关闭</el-button>
        <el-button type="primary" :loading="importingGroups" @click="submitImportGroups">导入分组</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="importAccountsDialog" title="导入为账号管理账号" width="760px" destroy-on-close>
      <el-form label-position="top">
        <el-alert
          class="dialog-note"
          type="info"
          show-icon
          :closable="false"
          title="这里会把已生成的上游 Key 创建成 Sub2API 账号管理里的 apikey 账号，不会创建系统登录用户。"
        />
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="目标网站">
              <el-select v-model="importAccountsForm.website_id" style="width:100%" @change="onImportAccountWebsiteChange">
                <el-option v-for="site in websites" :key="site.id" :label="site.name" :value="site.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="账号平台">
              <el-select v-model="importAccountsForm.platform_mode" style="width:100%" @change="onPlatformModeChange">
                <el-option label="自动识别（按 Key/分组名判断）" value="auto" />
                <el-option label="手动选择" value="manual" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="固定平台（手动模式）">
              <el-select v-model="importAccountsForm.default_platform" style="width:100%" :disabled="importAccountsForm.platform_mode === 'auto'">
                <el-option label="OpenAI 兼容" value="openai" />
                <el-option label="Anthropic" value="anthropic" />
                <el-option label="Gemini" value="gemini" />
                <el-option label="Antigravity" value="antigravity" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24" style="margin-bottom:6px">
            <el-button size="small" text :loading="syncingImportStatus" @click="syncImportStatus">
              <el-icon><Refresh /></el-icon>刷新导入状态
            </el-button>
            <span v-if="importSyncStatus" style="font-size:12px;color:var(--text-muted);margin-left:8px">
              已校验已导入标记 {{ importSyncStatus.total }} 个，清除 {{ importSyncStatus.cleared }} 个失效标记
            </span>
          </el-col>
        </el-row>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="来源上游">
              <el-select v-model="importAccountsForm.upstream_id" filterable style="width:100%" @change="onImportAccountUpstreamChange">
                <el-option v-for="upstream in upstreams" :key="upstream.id" :label="upstream.name" :value="upstream.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="账号名前缀">
              <el-input v-model="importAccountsForm.account_name_prefix" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="并发/容量">
              <el-input-number v-model="importAccountsForm.concurrency" :min="1" style="width:100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="优先级">
              <el-input-number v-model="importAccountsForm.priority" :min="0" style="width:100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="已生成的上游 Key">
          <div style="display:flex;gap:8px;margin-bottom:6px">
            <el-button size="small" text @click="selectAllImportableKeys">全选可导入 Key</el-button>
            <el-button size="small" text @click="clearImportAccountSelection">清空</el-button>
          </div>
          <div v-if="importGeneratedKeys.length" class="import-stats">
            总计 {{ importGeneratedKeys.length }} 个，现可导入 {{ importableGeneratedKeys.length }} 个，已导入 {{ importedGeneratedKeyCount }} 个，无明文 {{ missingPlaintextKeyCount }} 个
          </div>
          <el-select
            v-model="importAccountsForm.upstream_key_ids"
            multiple
            filterable
            style="width:100%"
            placeholder="选择要导入为账号管理账号的 Key"
            :loading="generatedKeyLoading"
            @change="autoFillAccountTargetGroups()"
          >
            <el-option
              v-for="item in importableGeneratedKeys"
              :key="item.id!"
              :label="`${item.group_name || item.group_id} / ${detectPlatform(item)} / ${item.key_name} / ${item.masked_key}`"
              :value="item.id!"
            />
          </el-select>
        </el-form-item>
        <div v-if="selectedAccountGroups.length" class="mapping-panel">
          <div class="result-title">目标分组映射</div>
          <div v-for="group in selectedAccountGroups" :key="group.group_id" class="mapping-row">
            <span class="mapping-label">{{ group.group_name || group.group_id }}</span>
            <el-select v-model="importAccountsForm.target_group_map[group.group_id]" clearable filterable placeholder="可不选" style="width:280px">
              <el-option v-for="target in importTargetGroups" :key="target.id" :label="`${target.name} (${target.rate_multiplier ?? '—'})`" :value="target.id" />
            </el-select>
          </div>
        </div>
      </el-form>
      <div v-if="importAccountResults.length" class="result-panel">
        <div class="result-title">创建结果</div>
        <el-table :data="importAccountResults" size="small">
          <el-table-column prop="source_group_name" label="来源分组" min-width="130" />
          <el-table-column prop="account_name" label="账号管理账号" min-width="180" />
          <el-table-column label="识别平台" width="120">
            <template #default="{ row }">
              <span>{{ platformLabel(row.platform) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="请求地址" min-width="180">
            <template #default="{ row }">
              <span class="mono" style="font-size:12px">{{ row.upstream_base_url || '—' }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="account_id" label="账号 ID" width="110" />
          <el-table-column label="状态" width="90">
            <template #default="{ row }">
              <el-tag v-if="row.status === 'created'" size="small" type="success">成功</el-tag>
              <el-tag v-else-if="row.status === 'exists'" size="small" type="info">已存在</el-tag>
              <el-tag v-else size="small" type="danger">失败</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="message" label="结果" min-width="160" />
        </el-table>
      </div>
      <template #footer>
        <el-button @click="importAccountsDialog = false">关闭</el-button>
        <el-button type="primary" :loading="importingAccounts" :disabled="importingAccounts" @click="submitImportAccounts">创建账号管理账号</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
import dayjs from 'dayjs'
import { ArrowDown, Delete, Edit, Plus, Grid, Connection, Link, Upload, Key, Refresh } from '@element-plus/icons-vue'
import {
  upstreamsApi,
  websitesApi,
  type BindingSourceGroup,
  type GeneratedUpstreamKey,
  type GroupBindingData,
  type GroupBindingForm,
  type ImportAccountItem,
  type ImportGroupItem,
  type UpstreamData,
  type WebsiteData,
  type WebsiteForm,
  type WebsiteGroup,
  type WebsiteSyncLog,
} from '@/api'

const websites = ref<(WebsiteData & { _testing?: boolean })[]>([])
const upstreams = ref<UpstreamData[]>([])
const selectedWebsite = ref<WebsiteData | null>(null)
const websiteGroups = ref<WebsiteGroup[]>([])
const bindingWebsiteGroups = ref<WebsiteGroup[]>([])
const bindings = ref<(GroupBindingData & { _syncing?: boolean })[]>([])
const logs = ref<WebsiteSyncLog[]>([])
const snapshotsByUpstream = ref<Record<number, any[]>>({})
const importTargetGroups = ref<WebsiteGroup[]>([])
const importGeneratedKeys = ref<GeneratedUpstreamKey[]>([])

const websiteLoading = ref(false)
const groupsLoading = ref(false)
const bindingLoading = ref(false)
const logLoading = ref(false)
const importingGroups = ref(false)
const importingAccounts = ref(false)
const generatedKeyLoading = ref(false)
const importSyncStatus = ref<{ total: number; cleared: number; failed: number } | null>(null)
const syncingImportStatus = ref(false)

const statusLabel = (s: string) => ({ healthy: '健康', unhealthy: '异常', unknown: '未知' }[s] || s)
const algorithmLabel = (s: string) => ({ max_plus_percent: '最高倍率', average_plus_percent: '平均倍率', min_plus_percent: '最低倍率' }[s] || s)
const toUTC = (t: string) => /[Z+\-]\d*$/.test(t.trim()) ? t : t + 'Z'
const fmtTime = (t: string) => dayjs(toUTC(t)).format('MM-DD HH:mm:ss')
const sourceGroupId = (group: any) => String(group?.group_id || group?.id || group?.name || '')
const sourceGroupName = (group: any) => String(group?.group_name || group?.name || sourceGroupId(group))

function defaultWebsiteForm(): WebsiteForm {
  return {
    name: '',
    site_type: 'sub2api',
    base_url: '',
    api_prefix: '/api/v1/admin',
    auth_type: 'api_key',
    auth_config: { key: '', header: 'x-api-key' },
    groups_endpoint: '/groups',
    group_update_endpoint: '/groups/{id}',
    enabled: true,
    auto_sync_enabled: true,
    timeout_seconds: 30,
  }
}

const websiteDrawer = ref(false)
const savingWebsite = ref(false)
const editingWebsiteId = ref<number | null>(null)
const websiteFormRef = ref<FormInstance>()
const websiteForm = ref<WebsiteForm>(defaultWebsiteForm())
const websiteRules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  base_url: [{ required: true, message: '请输入 Base URL', trigger: 'blur' }],
}

function defaultBindingForm(): GroupBindingForm {
  return {
    website_id: websites.value[0]?.id ?? 0,
    target_group_id: '',
    target_group_name: '',
    source_groups: [],
    percent: 0,
    algorithm: 'max_plus_percent',
    enabled: true,
  }
}

const bindingDrawer = ref(false)
const savingBinding = ref(false)
const editingBindingId = ref<number | null>(null)
const bindingFormRef = ref<FormInstance>()
const bindingForm = ref<GroupBindingForm>(defaultBindingForm())
const sourceGroupKeys = ref<string[]>([])
const bindingRules = {
  target_group_id: [{ required: true, message: '请选择目标分组', trigger: 'change' }],
}

const importGroupsDialog = ref(false)
const importGroupsForm = ref({
  website_id: 0,
  upstream_id: 0,
  group_ids: [] as string[],
  name_prefix: '',
})
const importGroupResults = ref<ImportGroupItem[]>([])

const importAccountsDialog = ref(false)
const importAccountsForm = ref({
  website_id: 0,
  upstream_id: 0,
  upstream_key_ids: [] as number[],
  target_group_map: {} as Record<string, string>,
  account_name_prefix: 'SmartUp',
  default_platform: 'openai',
  platform_mode: 'auto',
  concurrency: 10,
  priority: 1,
})
const importAccountResults = ref<ImportAccountItem[]>([])

const upstreamGroupOptions = computed(() => {
  const rows: Array<{ key: string; label: string; source: BindingSourceGroup }> = []
  for (const upstream of upstreams.value) {
    const groups = snapshotsByUpstream.value[upstream.id] || []
    for (const group of groups) {
      const source = {
        upstream_id: upstream.id,
        upstream_name: upstream.name,
        group_id: group.group_id,
        group_name: group.group_name || group.group_id,
      }
      rows.push({
        key: `${upstream.id}::${group.group_id}`,
        label: `${upstream.name} / ${source.group_name} (${group.rate || '—'})`,
        source,
      })
    }
  }
  return rows
})

const importSourceGroups = computed(() => snapshotsByUpstream.value[importGroupsForm.value.upstream_id] || [])

function isImportableGeneratedKey(item: GeneratedUpstreamKey) {
  return item.id !== null
    && item.has_key_value
    && item.status !== 'failed'
    && !(item.imported_website_id === importAccountsForm.value.website_id && item.imported_account_id)
}

const importableGeneratedKeys = computed(() =>
  importGeneratedKeys.value.filter(isImportableGeneratedKey),
)

const importedGeneratedKeyCount = computed(() =>
  importGeneratedKeys.value.filter((item) =>
    item.imported_website_id === importAccountsForm.value.website_id && Boolean(item.imported_account_id),
  ).length,
)

const missingPlaintextKeyCount = computed(() =>
  importGeneratedKeys.value.filter((item) => !item.has_key_value).length,
)

const selectedWebsiteBindings = computed(() => {
  if (!selectedWebsite.value) return []
  return bindings.value.filter((binding) => binding.website_id === selectedWebsite.value?.id)
})

const selectedAccountGroups = computed(() => {
  const selected = new Set(importAccountsForm.value.upstream_key_ids)
  const rows = importableGeneratedKeys.value.filter((item) => item.id !== null && selected.has(item.id))
  const seen = new Set<string>()
  const groups: Array<{ group_id: string; group_name: string }> = []
  for (const row of rows) {
    if (seen.has(row.group_id)) continue
    seen.add(row.group_id)
    groups.push({ group_id: row.group_id, group_name: row.group_name })
  }
  return groups
})

async function loadWebsites() {
  websiteLoading.value = true
  try {
    const res = await websitesApi.list()
    websites.value = res.data
    if (!selectedWebsite.value && res.data.length > 0) selectedWebsite.value = res.data[0]
  } finally {
    websiteLoading.value = false
  }
}

async function onSelectedWebsiteChange(value: number | string) {
  const nextId = Number(value)
  const next = websites.value.find((site) => site.id === nextId)
  if (!next) return
  selectedWebsite.value = next
  await loadWebsiteGroups()
}

async function loadUpstreamGroups() {
  const upstreamRes = await upstreamsApi.list()
  upstreams.value = upstreamRes.data
  const entries: Record<number, any[]> = {}
  await Promise.all(upstreams.value.map(async (upstream) => {
    try {
      const res = await upstreamsApi.latestSnapshot(upstream.id)
      entries[upstream.id] = Object.values(res.data.snapshot?.groups || {})
    } catch {
      entries[upstream.id] = []
    }
  }))
  snapshotsByUpstream.value = entries
}

async function loadWebsiteGroups() {
  if (!selectedWebsite.value) return
  groupsLoading.value = true
  try {
    const res = await websitesApi.groups(selectedWebsite.value.id)
    websiteGroups.value = res.data
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '拉取分组失败')
  } finally {
    groupsLoading.value = false
  }
}

async function loadBindingWebsiteGroups(websiteId: number) {
  if (!websiteId) {
    bindingWebsiteGroups.value = []
    return
  }
  try {
    const res = await websitesApi.groups(websiteId)
    bindingWebsiteGroups.value = res.data
  } catch {
    bindingWebsiteGroups.value = []
  }
}

async function loadImportTargetGroups(websiteId: number) {
  if (!websiteId) {
    importTargetGroups.value = []
    return
  }
  try {
    const res = await websitesApi.groups(websiteId)
    importTargetGroups.value = res.data
  } catch {
    importTargetGroups.value = []
  }
}

async function loadBindings() {
  bindingLoading.value = true
  try {
    const res = await websitesApi.listBindings()
    bindings.value = res.data
  } finally {
    bindingLoading.value = false
  }
}

async function loadLogs() {
  logLoading.value = true
  try {
    const res = await websitesApi.logs({ limit: 50 })
    logs.value = res.data
  } finally {
    logLoading.value = false
  }
}

async function syncImportStatus() {
  const websiteId = importAccountsForm.value.website_id
  const upstreamId = importAccountsForm.value.upstream_id
  if (!websiteId || !upstreamId) return false
  syncingImportStatus.value = true
  let reloaded = false
  try {
    const res = await websitesApi.syncImportedUpstreamKeys(websiteId, { upstream_id: upstreamId })
    // 校验请求完成时表单未切换
    if (importAccountsForm.value.website_id !== websiteId || importAccountsForm.value.upstream_id !== upstreamId) return false
    const items = res.data.items
    importSyncStatus.value = {
      total: items.length,
      cleared: items.filter(i => i.status === 'stale_cleared').length,
      failed: items.filter(i => i.status === 'check_failed').length,
    }
    if (importSyncStatus.value.cleared > 0) {
      ElMessage.success(`已清除 ${importSyncStatus.value.cleared} 个失效导入标记`)
    }
    if (importAccountsForm.value.upstream_id === upstreamId) {
      await loadImportGeneratedKeys(upstreamId)
      reloaded = true
    }
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '同步导入状态失败')
  } finally {
    syncingImportStatus.value = false
  }
  return reloaded
}

async function loadImportGeneratedKeys(upstreamId: number) {
  importGeneratedKeys.value = []
  if (!upstreamId) return
  generatedKeyLoading.value = true
  const frozenId = upstreamId
  try {
    const res = await upstreamsApi.generatedKeys(frozenId)
    if (importAccountsForm.value.upstream_id !== frozenId) return  // 已切换到其他上游
    importGeneratedKeys.value = res.data
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '加载上游 Key 失败')
  } finally {
    generatedKeyLoading.value = false
  }
}

async function loadAll() {
  await Promise.all([loadWebsites(), loadUpstreamGroups(), loadBindings(), loadLogs()])
  if (selectedWebsite.value) await loadWebsiteGroups()
}

function selectWebsite(row: WebsiteData) {
  selectedWebsite.value = row
  loadWebsiteGroups()
}

function openWebsiteCreate() {
  editingWebsiteId.value = null
  websiteForm.value = defaultWebsiteForm()
  websiteDrawer.value = true
}

function openWebsiteEdit(row: WebsiteData) {
  editingWebsiteId.value = row.id
  websiteForm.value = {
    name: row.name,
    site_type: row.site_type,
    base_url: row.base_url,
    api_prefix: row.api_prefix,
    auth_type: row.auth_type,
    auth_config: { ...row.auth_config_masked },
    groups_endpoint: row.groups_endpoint,
    group_update_endpoint: row.group_update_endpoint,
    enabled: row.enabled,
    auto_sync_enabled: row.auto_sync_enabled,
    timeout_seconds: row.timeout_seconds,
  }
  websiteDrawer.value = true
}

async function saveWebsite() {
  const valid = await websiteFormRef.value?.validate().catch(() => false)
  if (!valid) return
  savingWebsite.value = true
  try {
    if (editingWebsiteId.value) {
      await websitesApi.update(editingWebsiteId.value, websiteForm.value)
      ElMessage.success('保存成功')
    } else {
      await websitesApi.create(websiteForm.value)
      ElMessage.success('创建成功')
    }
    websiteDrawer.value = false
    await loadWebsites()
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '保存失败')
  } finally {
    savingWebsite.value = false
  }
}

async function toggleWebsiteSync(row: WebsiteData) {
  try {
    await websitesApi.update(row.id, { auto_sync_enabled: row.auto_sync_enabled })
    ElMessage.success(row.auto_sync_enabled ? '已启用自动同步' : '已停用自动同步')
  } catch {
    row.auto_sync_enabled = !row.auto_sync_enabled
    ElMessage.error('操作失败')
  }
}

async function testWebsite(row: WebsiteData & { _testing?: boolean }) {
  row._testing = true
  try {
    const res = await websitesApi.test(row.id)
    ElMessage[res.data.success ? 'success' : 'error'](res.data.detail || res.data.message)
    await loadWebsites()
  } finally {
    row._testing = false
  }
}

/** 处理「更多」下拉菜单中的操作 */
function handleMoreAction(cmd: string, row: WebsiteData & { _testing?: boolean }) {
  switch (cmd) {
    case 'test': testWebsite(row); break
    case 'binding': openBindingCreate(row); break
    case 'importGroups': openImportGroups(row); break
    case 'importAccounts': openImportAccounts(row); break
    case 'delete': deleteWebsite(row); break
  }
}

async function deleteWebsite(row: WebsiteData) {
  try {
    await ElMessageBox.confirm(`确认删除网站 "${row.name}"？`, '删除确认', { type: 'warning' })
    await websitesApi.delete(row.id)
    ElMessage.success('已删除')
    selectedWebsite.value = null
    websiteGroups.value = []
    await loadAll()
  } catch {}
}

async function openBindingCreate(site?: WebsiteData | null, target?: WebsiteGroup) {
  editingBindingId.value = null
  bindingForm.value = defaultBindingForm()
  if (site) bindingForm.value.website_id = site.id
  await loadBindingWebsiteGroups(bindingForm.value.website_id)
  if (target) {
    bindingForm.value.target_group_id = target.id
    bindingForm.value.target_group_name = target.name
  }
  sourceGroupKeys.value = []
  bindingDrawer.value = true
}

async function openBindingEdit(row: GroupBindingData) {
  editingBindingId.value = row.id
  bindingForm.value = {
    website_id: row.website_id,
    target_group_id: row.target_group_id,
    target_group_name: row.target_group_name,
    source_groups: [...row.source_groups],
    percent: row.percent,
    algorithm: row.algorithm,
    enabled: row.enabled,
  }
  sourceGroupKeys.value = row.source_groups.map(item => `${item.upstream_id}::${item.group_id}`)
  await loadBindingWebsiteGroups(row.website_id)
  bindingDrawer.value = true
}

async function onBindingWebsiteChange(value: number) {
  bindingForm.value.target_group_id = ''
  bindingForm.value.target_group_name = ''
  await loadBindingWebsiteGroups(value)
}

function onTargetGroupChange(value: string) {
  const group = bindingWebsiteGroups.value.find(item => item.id === value)
  bindingForm.value.target_group_name = group?.name || value
}

function onSourceGroupsChange(values: string[]) {
  const options = new Map(upstreamGroupOptions.value.map(item => [item.key, item.source]))
  bindingForm.value.source_groups = values.map(value => options.get(value)).filter((item): item is BindingSourceGroup => Boolean(item))
}

async function saveBinding() {
  if (!bindingForm.value.source_groups.length) {
    ElMessage.error('请选择至少一个监听上游分组')
    return
  }
  const valid = await bindingFormRef.value?.validate().catch(() => false)
  if (!valid) return
  savingBinding.value = true
  try {
    if (editingBindingId.value) {
      await websitesApi.updateBinding(editingBindingId.value, bindingForm.value)
    } else {
      await websitesApi.createBinding(bindingForm.value)
    }
    ElMessage.success('保存成功，已尝试同步')
    bindingDrawer.value = false
    await Promise.all([loadBindings(), loadLogs()])
    if (selectedWebsite.value?.id === bindingForm.value.website_id) await loadWebsiteGroups()
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '保存失败')
  } finally {
    savingBinding.value = false
  }
}

async function toggleBinding(row: GroupBindingData) {
  try {
    await websitesApi.updateBinding(row.id, { enabled: row.enabled })
    ElMessage.success(row.enabled ? '已启用绑定' : '已停用绑定')
  } catch {
    row.enabled = !row.enabled
    ElMessage.error('操作失败')
  }
}

async function syncBinding(row: GroupBindingData & { _syncing?: boolean }) {
  row._syncing = true
  try {
    const res = await websitesApi.syncNow(row.id)
    ElMessage[res.data.status === 'success' ? 'success' : 'error'](res.data.message)
    await loadLogs()
    if (selectedWebsite.value?.id === row.website_id) await loadWebsiteGroups()
  } finally {
    row._syncing = false
  }
}

async function deleteBinding(row: GroupBindingData) {
  try {
    await ElMessageBox.confirm('确认删除该绑定？', '删除确认', { type: 'warning' })
    await websitesApi.deleteBinding(row.id)
    ElMessage.success('已删除')
    await loadBindings()
  } catch {}
}

async function openImportGroups(site?: WebsiteData | null) {
  if (upstreams.value.length === 0) await loadUpstreamGroups()
  const target = site || selectedWebsite.value || websites.value[0]
  importGroupsForm.value = {
    website_id: target?.id || 0,
    upstream_id: upstreams.value[0]?.id || 0,
    group_ids: [],
    name_prefix: '',
  }
  importGroupResults.value = []
  importGroupsDialog.value = true
}

async function submitImportGroups() {
  if (!importGroupsForm.value.website_id || !importGroupsForm.value.upstream_id) {
    ElMessage.error('请选择目标网站和来源上游')
    return
  }
  importingGroups.value = true
  try {
    const res = await websitesApi.importGroupsFromUpstream(
      importGroupsForm.value.website_id,
      importGroupsForm.value.upstream_id,
      {
        group_ids: importGroupsForm.value.group_ids,
        name_prefix: importGroupsForm.value.name_prefix,
      },
    )
    importGroupResults.value = res.data.items
    ElMessage[res.data.success ? 'success' : 'warning'](res.data.message)
    if (selectedWebsite.value?.id === importGroupsForm.value.website_id) await loadWebsiteGroups()
    await loadImportTargetGroups(importGroupsForm.value.website_id)
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '导入上游分组失败')
  } finally {
    importingGroups.value = false
  }
}

async function openImportAccounts(site?: WebsiteData | null) {
  if (upstreams.value.length === 0) await loadUpstreamGroups()
  const target = site || selectedWebsite.value || websites.value[0]
  importAccountsForm.value = {
    website_id: target?.id || 0,
    upstream_id: upstreams.value[0]?.id || 0,
    upstream_key_ids: [],
    target_group_map: {},
    account_name_prefix: 'SmartUp',
    default_platform: 'openai',
    platform_mode: 'auto',
    concurrency: 10,
    priority: 1,
  }
  importAccountResults.value = []
  importSyncStatus.value = null
  await loadImportTargetGroups(importAccountsForm.value.website_id)
  // 打开弹窗后自动同步导入状态（校验远端账号是否仍存在）
  const reloaded = await syncImportStatus()
  if (!reloaded) await loadImportGeneratedKeys(importAccountsForm.value.upstream_id)
  importAccountsDialog.value = true
}

async function onImportAccountWebsiteChange(value: number) {
  importAccountsForm.value.target_group_map = {}
  await loadImportTargetGroups(value)
  const reloaded = await syncImportStatus()
  if (!reloaded) await loadImportGeneratedKeys(importAccountsForm.value.upstream_id)
}

async function onImportAccountUpstreamChange(value: number) {
  importAccountsForm.value.upstream_key_ids = []
  importAccountsForm.value.target_group_map = {}
  importAccountResults.value = []
  const reloaded = await syncImportStatus()
  if (!reloaded) await loadImportGeneratedKeys(value)
}

function onPlatformModeChange(value: string) {
  if (value === 'auto') {
    importAccountsForm.value.default_platform = 'openai'
  }
}

function detectPlatform(item: { group_name?: string; group_id?: string; key_name?: string }) {
  const text = `${item.group_name || ''} ${item.group_id || ''} ${item.key_name || ''}`.toLowerCase()
  if (text.includes('claude') || text.includes('anthropic')) return 'Anthropic'
  if (text.includes('gemini')) return 'Gemini'
  if (text.includes('antigravity')) return 'Antigravity'
  return 'OpenAI 兼容'
}

function platformLabel(platform: string) {
  const map: Record<string, string> = {
    openai: 'OpenAI 兼容',
    anthropic: 'Anthropic',
    gemini: 'Gemini',
    antigravity: 'Antigravity',
  }
  return map[platform] || platform || '—'
}

function normalizeGroupName(name: string) {
  return String(name || '')
    .toLowerCase()
    .replace(/^smartup[-_\s]*/i, '')
    .replace(/^ai\d+pro/i, '')
    .replace(/[|｜]/g, ' ')
    .replace(/\s+/g, '')
    .trim()
}

function findTargetGroupForSource(sourceName: string, sourceId: string) {
  const sourceNorm = normalizeGroupName(sourceName || sourceId)
  if (!sourceNorm) return ''

  const exact = importTargetGroups.value.find(g =>
    normalizeGroupName(g.name) === sourceNorm
  )
  if (exact) return exact.id

  const fuzzy = importTargetGroups.value.find(g => {
    const targetNorm = normalizeGroupName(g.name)
    return targetNorm.includes(sourceNorm) || sourceNorm.includes(targetNorm)
  })
  return fuzzy?.id || ''
}

function autoFillAccountTargetGroups() {
  const selected = new Set(importAccountsForm.value.upstream_key_ids)
  const keys = importableGeneratedKeys.value.filter(item => item.id !== null && selected.has(item.id))
  const nextMap = { ...importAccountsForm.value.target_group_map }

  for (const item of keys) {
    if (!item.id || !selected.has(item.id)) continue
    if (nextMap[item.group_id]) continue

    const targetId = findTargetGroupForSource(item.group_name || item.group_id, item.group_id)
    if (targetId) nextMap[item.group_id] = targetId
  }

  importAccountsForm.value.target_group_map = nextMap
}

function selectAllImportableKeys() {
  const keys = importableGeneratedKeys.value
  importAccountsForm.value.upstream_key_ids = keys.map(item => item.id!)
  autoFillAccountTargetGroups()

  const matched = Object.keys(importAccountsForm.value.target_group_map).length
  ElMessage.success(`已选择 ${keys.length} 个 Key，自动匹配 ${matched} 个目标分组`)
}

function clearImportAccountSelection() {
  importAccountsForm.value.upstream_key_ids = []
  importAccountsForm.value.target_group_map = {}
}

async function submitImportAccounts() {
  if (!importAccountsForm.value.website_id || !importAccountsForm.value.upstream_id) {
    ElMessage.error('请选择目标网站和来源上游')
    return
  }
  if (importAccountsForm.value.upstream_key_ids.length === 0) {
    ElMessage.error('请选择要导入的上游 Key')
    return
  }
  importingAccounts.value = true
  try {
    const res = await websitesApi.importAccountsFromUpstreamKeys(importAccountsForm.value.website_id, {
      upstream_key_ids: importAccountsForm.value.upstream_key_ids,
      target_group_map: importAccountsForm.value.target_group_map,
      account_name_prefix: importAccountsForm.value.account_name_prefix,
      default_platform: importAccountsForm.value.default_platform,
      platform_mode: importAccountsForm.value.platform_mode,
      concurrency: importAccountsForm.value.concurrency,
      priority: importAccountsForm.value.priority,
    })
    importAccountResults.value = res.data.items
    ElMessage[res.data.success ? 'success' : 'warning'](res.data.message)
    await loadImportGeneratedKeys(importAccountsForm.value.upstream_id)
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '创建账号管理账号失败')
  } finally {
    importingAccounts.value = false
  }
}

onMounted(loadAll)
</script>

<style scoped>
.websites-page { display: flex; flex-direction: column; gap: 18px; padding-bottom: 1rem; }

.page-block {
  padding: 1rem;
}

.page-header {
  border-radius: var(--radius-shell);
}

.panel-head {
  min-height: 48px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-color);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.panel-title { font-size: 14px; font-weight: 600; color: var(--text-primary); }
.panel-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.panel-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px;
}
.content-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
}
.cell-name { font-weight: 500; font-size: 14px; }
.cell-url { font-size: 12px; color: var(--text-muted); margin-top: 2px; overflow-wrap: anywhere; }
.muted { color: var(--text-muted); font-size: 12px; }
.error-text { font-size: 12px; color: var(--color-danger); cursor: pointer; }
.rate-value { font-weight: 600; color: var(--color-primary-strong); font-family: monospace; }
.action-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: nowrap;
  gap: 6px;
  min-width: 0;
}
.action-row .el-button.is-circle {
  width: 26px;
  height: 26px;
  margin-left: 0;
}
.action-row .btn-edit {
  color: var(--text-primary);
  font-weight: 500;
  gap: 3px;
  padding: 0 6px;
  white-space: nowrap;
  flex-shrink: 0;
}
.action-row .btn-edit-icon {
  font-size: 13px;
}
.action-row .btn-edit:hover {
  color: var(--el-color-primary);
  background: var(--el-color-primary-light-9);
  border-radius: 4px;
}
.action-row .btn-more {
  color: var(--text-muted);
  font-size: 12px;
  padding: 0 4px;
}
.action-row .btn-more:hover {
  color: var(--el-color-primary);
}
.action-row .btn-more .el-icon--right {
  margin-left: 1px;
}
.btn-more-delete {
  color: var(--el-color-danger);
}

.site-switcher {
  width: 180px;
  flex-shrink: 0;
}

.binding-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
}
.binding-actions .el-button--danger,
.action-row .el-button--danger {
  --el-button-bg-color: transparent;
  --el-button-border-color: transparent;
}
.binding-actions .el-button--danger:hover,
.action-row .el-button--danger:hover {
  --el-button-bg-color: var(--el-color-danger-light-8, #fef0f0);
  --el-button-border-color: var(--el-color-danger-light-5, #fbc4c4);
}
.binding-list { min-height: 120px; }
.import-stats {
  margin: 0 0 8px;
  color: var(--text-muted);
  font-size: 12px;
}
.binding-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-color);
}
.binding-item:last-child { border-bottom: none; }
.binding-main { min-width: 0; }
.binding-title {
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.binding-meta { color: var(--text-muted); font-size: 12px; margin-top: 3px; }
.empty-hint {
  text-align: center;
  padding: 36px 16px;
  color: var(--text-muted);
  font-size: 13px;
}
.switch-line {
  min-height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: var(--text-secondary);
  font-size: 13px;
}
.dialog-note { margin-bottom: 12px; }
.result-panel {
  margin-top: 14px;
  border-top: 1px solid var(--border-color);
  padding-top: 12px;
}
.result-title {
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}
.mapping-panel {
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 12px;
}
.mapping-row {
  min-height: 38px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.mapping-row + .mapping-row {
  border-top: 1px solid var(--border-color);
}
.mapping-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-secondary);
  font-size: 13px;
}

@media (min-width: 1024px) {
  .content-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

@media (max-width: 768px) {
  .page-header {
    flex-direction: column;
    align-items: stretch;
  }
  .page-header .el-button { min-height: 44px; }
  .binding-item {
    align-items: flex-start;
    flex-direction: column;
  }
  .binding-actions { width: 100%; justify-content: flex-end; }
  .mapping-row {
    align-items: stretch;
    flex-direction: column;
    padding: 8px 0;
  }
  .mapping-row .el-select { width: 100% !important; }
}
</style>
