<template>
  <div class="shell-page shell-page-fluid page-section upstreams-page">
    <section class="page-header upstreams-hero surface-card">
      <div class="page-heading">
        <p class="page-kicker">Monitoring Matrix</p>
        <h2 class="page-title">上游管理</h2>
        <p class="page-desc">
          管理 API 上游服务、认证方式与轮询策略。这里优先展示健康度、检测节奏和错误信号，减少你在异常发生时的定位成本。
        </p>
      </div>

      <div class="toolbar-cluster hero-actions">
        <el-button @click="loadList" :loading="tableLoading">
          <el-icon><Refresh /></el-icon>
          刷新列表
        </el-button>
        <el-button type="primary" @click="openCreate">
          <el-icon><Plus /></el-icon>
          新增上游
        </el-button>
      </div>
    </section>

    <section class="metric-grid">
      <article class="surface-card metric-card">
        <div class="metric-label">Total Sources</div>
        <div class="metric-value">{{ metrics.total }}</div>
        <p class="metric-note">当前纳管的上游节点总数</p>
      </article>
      <article class="surface-card metric-card">
        <div class="metric-label">Healthy</div>
        <div class="metric-value">{{ metrics.healthy }}</div>
        <p class="metric-note">最近一次检测返回健康状态</p>
      </article>
      <article class="surface-card metric-card">
        <div class="metric-label">Enabled</div>
        <div class="metric-value">{{ metrics.enabled }}</div>
        <p class="metric-note">已启用定时检测的上游节点</p>
      </article>
      <article class="surface-card metric-card">
        <div class="metric-label">Attention</div>
        <div class="metric-value">{{ metrics.unhealthy }}</div>
        <p class="metric-note">需要处理错误或网络异常的节点</p>
      </article>
      <article class="surface-card metric-card">
        <div class="metric-label">Balance</div>
        <div class="metric-value">{{ metrics.balanceCount }}</div>
        <p class="metric-note">已配置余额接口的上游节点数</p>
      </article>
    </section>

    <section class="upstreams-content">
      <section class="surface-card data-stage">
        <div class="section-header data-stage-head">
          <div>
            <div class="section-caption">Upstream Registry</div>
            <h3 class="data-stage-title brand-type">检测与变更控制台</h3>
          </div>
          <p class="data-stage-note">点击详情可查看快照历史、分组倍率与最近错误。</p>
        </div>

        <el-table :data="list" v-loading="tableLoading" row-key="id" style="width: 100%">
          <el-table-column label="来源" min-width="220">
            <template #default="{ row }">
              <div class="cell-name">{{ row.name }}</div>
              <div class="cell-url mono">{{ row.base_url }}</div>
            </template>
          </el-table-column>

          <el-table-column label="状态" width="118">
            <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="140" align="right">
            <template #default="{ row }">
              <span v-if="row.balance !== null && row.balance !== undefined" class="balance-value mono">
                {{ formatBalance(row.balance) }}
              </span>
              <span v-else class="muted">—</span>
            </template>
          </el-table-column>

          <el-table-column label="启用" width="88" align="center">
            <template #default="{ row }">
              <el-switch v-model="row.enabled" @change="toggleEnabled(row)" />
            </template>
          </el-table-column>

          <el-table-column label="认证" width="132">
            <template #default="{ row }">
              <span class="status-badge auth-badge">{{ authLabel(row.auth_type) }}</span>
            </template>
          </el-table-column>

          <el-table-column label="检测间隔" width="112">
            <template #default="{ row }">
              <span class="mono time-inline">{{ row.check_interval_seconds }}s</span>
            </template>
          </el-table-column>

          <el-table-column label="最近检测" min-width="168">
            <template #default="{ row }">
              <span v-if="row.last_checked_at" class="time-text mono">{{ fmtTime(row.last_checked_at) }}</span>
              <span v-else class="muted">未检测</span>
            </template>
          </el-table-column>

          <el-table-column label="最近错误" min-width="220">
            <template #default="{ row }">
              <el-tooltip v-if="row.last_error" :content="row.last_error" placement="top" :show-after="300">
                <span class="error-text">{{ shrinkError(row.last_error) }}</span>
              </el-tooltip>
              <span v-else class="muted">无异常</span>
            </template>
          </el-table-column>

          <el-table-column label="操作" width="258" fixed="right">
            <template #default="{ row }">
              <div class="action-row">
                <el-button size="small" text @click="openEdit(row)" title="编辑">
                  <el-icon><Edit /></el-icon>
                </el-button>
                <el-button size="small" text @click="testUpstream(row)" :loading="row._testing">测试</el-button>
                <el-button size="small" text @click="checkNow(row)" :loading="row._checking">检测</el-button>
                <el-button size="small" text @click="openDetail(row)">
                  <el-icon><List /></el-icon>
                  详情
                </el-button>
                <el-button size="small" text type="danger" @click="confirmDelete(row)" title="删除">
                  <el-icon><Delete /></el-icon>
                </el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </section>

      <aside class="upstreams-side surface-card">
        <section class="side-section overview-section">
          <div class="section-header insight-head">
            <div>
              <div class="section-caption">Runtime Snapshot</div>
              <h3 class="insight-title">运行概览</h3>
            </div>
            <span class="insight-pill">健康率 {{ healthyRate }}%</span>
          </div>
          <div class="insight-grid">
            <div class="insight-metric">
              <span>异常节点</span>
              <strong>{{ metrics.unhealthy }}</strong>
            </div>
            <div class="insight-metric">
              <span>已启用</span>
              <strong>{{ metrics.enabled }}</strong>
            </div>
            <div class="insight-metric">
              <span>待检测</span>
              <strong>{{ pendingChecks }}</strong>
            </div>
            <div class="insight-metric">
              <span>最近检测</span>
              <strong>{{ latestCheckedAt ? fmtTime(latestCheckedAt) : '—' }}</strong>
            </div>
          </div>
        </section>

        <section class="side-section">
          <div class="section-header insight-head compact">
            <div>
              <div class="section-caption">Need Attention</div>
              <h3 class="insight-title">待关注节点</h3>
            </div>
          </div>
          <div v-if="attentionList.length > 0" class="feed-list">
            <button
              v-for="row in attentionList"
              :key="row.id"
              type="button"
              class="feed-item"
              @click="openDetail(row)"
            >
              <div class="feed-main">
                <div class="feed-top">
                  <span class="feed-name">{{ row.name }}</span>
                  <span :class="['status-badge', row.last_status]">
                    <span class="dot" />{{ statusLabel(row.last_status) }}
                  </span>
                </div>
                <div class="feed-meta">{{ row.last_error ? shrinkError(row.last_error) : '最近状态异常，建议查看快照详情' }}</div>
              </div>
              <span class="feed-link">详情</span>
            </button>
          </div>
          <div v-else class="empty-hint side-empty">当前没有需要关注的异常节点</div>
        </section>

        <section class="side-section">
          <div class="section-header insight-head compact">
            <div>
              <div class="section-caption">Recent Activity</div>
              <h3 class="insight-title">最近检测</h3>
            </div>
          </div>
          <div v-if="recentChecks.length > 0" class="timeline-list">
            <div v-for="row in recentChecks" :key="row.id" class="timeline-item">
              <div class="timeline-main">
                <div class="timeline-name">{{ row.name }}</div>
                <div class="timeline-meta mono">{{ fmtTime(row.last_checked_at!) }}</div>
              </div>
              <el-button size="small" text @click="openDetail(row)">查看</el-button>
            </div>
          </div>
          <div v-else class="empty-hint side-empty">还没有检测记录</div>
        </section>
      </aside>
    </section>

    <el-drawer
      v-model="drawerVisible"
      :title="editingId ? '编辑上游' : '新增上游'"
      size="480px"
      destroy-on-close
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-position="top">
        <el-form-item label="名称" prop="name">
          <el-input v-model="form.name" placeholder="例：ai98pro" />
        </el-form-item>
        <el-form-item v-if="!editingId" label="系统类型（快捷配置）">
          <el-select v-model="quickPlatform" @change="handlePlatformChange" style="width: 100%">
            <el-option label="Sub2API" value="sub2api" />
            <el-option label="New-API (管理员Key)" value="new-api" />
            <el-option label="New-API (普通账号)" value="new-api-user" />
            <el-option label="自定义" value="custom" />
          </el-select>
        </el-form-item>
        <el-form-item label="Base URL" prop="base_url">
          <el-input v-model="form.base_url" placeholder="https://example.com" />
        </el-form-item>
        <el-form-item label="API Prefix">
          <el-input v-model="form.api_prefix" placeholder="/api/v1" />
        </el-form-item>
        <el-form-item label="认证方式">
          <el-select v-model="form.auth_type" style="width: 100%">
            <el-option label="无认证" value="none" />
            <el-option label="Bearer Token" value="bearer" />
            <el-option label="Cookie" value="cookie" />
            <el-option label="API Key" value="api_key" />
            <el-option label="邮箱密码登录" value="login_password" />
          </el-select>
        </el-form-item>
        <template v-if="form.auth_type === 'bearer'">
          <el-form-item label="Bearer Token">
            <div class="auth-field-row">
              <el-input v-model="form.auth_config.token" type="password" show-password placeholder="***" />
              <el-button size="small" @click="openAuthCapture">
                <el-icon><Pointer /></el-icon>
                提取
              </el-button>
            </div>
          </el-form-item>
        </template>
        <template v-else-if="form.auth_type === 'cookie'">
          <el-form-item label="Cookie">
            <div class="auth-field-row">
              <el-input v-model="form.auth_config.cookie_string" type="password" show-password placeholder="name=value; name2=value2" />
              <el-button size="small" @click="openAuthCapture">
                <el-icon><Pointer /></el-icon>
                提取
              </el-button>
            </div>
          </el-form-item>
        </template>
        <template v-else-if="form.auth_type === 'api_key'">
          <el-form-item label="API Key">
            <el-input v-model="form.auth_config.key" type="password" show-password placeholder="***" />
          </el-form-item>
          <el-form-item label="Header 名称">
            <el-input v-model="form.auth_config.header" placeholder="Authorization" />
          </el-form-item>
        </template>
        <template v-else-if="form.auth_type === 'login_password'">
          <el-form-item :label="form.auth_config.username_field === 'username' ? '登录账号' : '登录邮箱'">
            <el-input v-model="form.auth_config.email" :placeholder="form.auth_config.username_field === 'username' ? 'admin' : 'admin@example.com'" />
          </el-form-item>
          <el-form-item label="登录密码">
            <el-input v-model="form.auth_config.password" type="password" show-password placeholder="***" />
          </el-form-item>
          <el-form-item label="登录接口路径">
            <el-input v-model="form.auth_config.login_path" placeholder="/auth/login" />
          </el-form-item>
        </template>
        <el-form-item label="分组接口">
          <el-input v-model="form.groups_endpoint" placeholder="/groups/available" />
        </el-form-item>
        <el-form-item label="倍率接口">
          <el-input v-model="form.rate_endpoint" placeholder="/groups/rates" />
        </el-form-item>
        <el-form-item label="余额接口">
          <el-input v-model="form.balance_endpoint" placeholder="留空则不获取余额，如 /auth/me" />
        </el-form-item>
        <el-form-item label="余额字段路径">
          <el-input v-model="form.balance_response_path" placeholder="如 balance、data.quota" />
          <div class="form-hint">JSON 点分路径，例如 <code>balance</code> 或 <code>data.quota</code></div>
        </el-form-item>
        <el-form-item label="余额除数">
          <el-input-number v-model="form.balance_divisor" :min="1" :max="999999999" style="width: 100%" />
          <div class="form-hint">原始值除以该数得到实际余额。New-API 填 <code>500000</code>，Sub2API 填 <code>1</code></div>
        </el-form-item>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="检测间隔（秒）">
              <el-input-number v-model="form.check_interval_seconds" :min="60" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="超时（秒）">
              <el-input-number v-model="form.timeout_seconds" :min="5" :max="120" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="启用">
          <el-switch v-model="form.enabled" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="drawerVisible = false">取消</el-button>
        <el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
      </template>
    </el-drawer>

    <el-drawer
      v-model="detailVisible"
      :title="`检测详情 — ${detailUpstream?.name || ''}`"
      size="700px"
      destroy-on-close
      @open="loadSnapshots"
    >
      <div v-if="detailUpstream" class="info-cards">
        <div class="surface-card info-card">
          <div class="info-label">状态</div>
          <span :class="['status-badge', detailUpstream.last_status]">
            <span class="dot" />{{ statusLabel(detailUpstream.last_status) }}
          </span>
        </div>
        <div class="surface-card info-card" v-if="detailUpstream.balance !== null">
          <div class="info-label">余额</div>
          <div class="info-value mono">{{ formatBalance(detailUpstream.balance) }}</div>
        </div>
        <div class="surface-card info-card" v-if="detailUpstream.balance_updated_at">
          <div class="info-label">余额更新于</div>
          <div class="info-value mono">{{ fmtTimeFull(detailUpstream.balance_updated_at) }}</div>
        </div>
        <div class="surface-card info-card">
          <div class="info-label">最近检测</div>
          <div class="info-value mono">{{ detailUpstream.last_checked_at ? fmtTimeFull(detailUpstream.last_checked_at) : '未检测' }}</div>
        </div>
        <div class="surface-card info-card">
          <div class="info-label">检测间隔</div>
          <div class="info-value mono">{{ detailUpstream.check_interval_seconds }}s</div>
        </div>
        <div class="surface-card info-card">
          <div class="info-label">超时</div>
          <div class="info-value mono">{{ detailUpstream.timeout_seconds }}s</div>
        </div>
      </div>

      <div v-if="detailUpstream?.last_error" class="error-box">
        <el-icon><Warning /></el-icon>
        <span>{{ detailUpstream.last_error }}</span>
      </div>

      <div class="section-title">
        <el-icon><Clock /></el-icon>
        检测历史
        <span class="section-sub">最近 {{ snapshots.length }} 条</span>
      </div>

      <div v-loading="snapshotLoading" class="snapshot-list">
        <div
          v-for="snap in snapshots"
          :key="snap.id"
          class="snap-item"
          :class="{ expanded: expandedId === snap.id }"
        >
          <div class="snap-header" @click="toggleExpand(snap)">
            <div class="snap-left">
              <el-icon class="expand-icon"><ArrowRight /></el-icon>
              <span class="snap-time mono">{{ fmtTimeFull(snap.captured_at) }}</span>
            </div>
            <div class="snap-right">
              <el-tag size="small" type="info">{{ snap.snapshot._groups_count }} 个分组</el-tag>
              <template v-if="snap.snapshot._changes_count !== null && snap.snapshot._changes_count !== undefined">
                <el-tag size="small" :type="snap.snapshot._changes_count > 0 ? 'warning' : 'success'">
                  {{ snap.snapshot._changes_count > 0 ? `${snap.snapshot._changes_count} 处变化` : '无变化' }}
                </el-tag>
              </template>
              <el-tag v-else size="small" type="primary">初始快照</el-tag>
            </div>
          </div>

          <div v-if="expandedId === snap.id" class="snap-body">
            <el-table
              :data="groupRows(snap.snapshot)"
              size="small"
              :header-cell-style="{ background: 'rgba(255, 244, 232, 0.02)', color: 'var(--text-soft)' }"
              :cell-style="{ background: 'transparent', color: 'var(--text-primary)' }"
            >
              <el-table-column prop="group_name" label="分组名称" min-width="140" />
              <el-table-column prop="platform" label="平台" width="110" />
              <el-table-column label="当前倍率" width="110">
                <template #default="{ row }">
                  <span class="rate-value mono">{{ row.rate || '—' }}</span>
                </template>
              </el-table-column>
              <el-table-column prop="default_rate" label="默认倍率" width="110" />
              <el-table-column prop="override_rate" label="覆盖倍率" width="110">
                <template #default="{ row }">
                  <span v-if="row.override_rate" class="override-value mono">{{ row.override_rate }}</span>
                  <span v-else class="muted">—</span>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>

        <div v-if="!snapshotLoading && snapshots.length === 0" class="empty-hint">
          暂无检测历史，请先触发「立即检测」
        </div>
      </div>

      <div v-if="snapshots.length > 0 || snapshotOffset > 0" class="snap-pagination">
        <el-button size="small" :disabled="snapshotOffset === 0" @click="prevSnapPage">上一页</el-button>
        <span class="page-info">第 {{ snapshotOffset / snapshotLimit + 1 }} 页</span>
        <el-button size="small" :disabled="snapshots.length < snapshotLimit" @click="nextSnapPage">下一页</el-button>
      </div>
    </el-drawer>

    <AuthCaptureDialog
      v-model="authCaptureVisible"
      :initial-url="authCaptureInitialUrl"
      @select="handleAuthCaptureSelect"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
import dayjs from 'dayjs'
import { Refresh, Plus, Edit, List, Delete, Warning, Clock, ArrowRight, Pointer } from '@element-plus/icons-vue'
import { upstreamsApi, type UpstreamData } from '@/api'
import AuthCaptureDialog from '@/components/AuthCaptureDialog.vue'

const list = ref<(UpstreamData & { _testing?: boolean; _checking?: boolean })[]>([])
const tableLoading = ref(false)

const drawerVisible = ref(false)
const saving = ref(false)
const editingId = ref<number | null>(null)
const formRef = ref<FormInstance>()

const defaultForm = () => ({
  name: '',
  base_url: '',
  api_prefix: '/api/v1',
  auth_type: 'login_password',
  auth_config: { email: '', password: '', login_path: '/auth/login' } as Record<string, any>,
  rate_endpoint: '/groups/rates',
  groups_endpoint: '/groups/available',
  enabled: true,
  check_interval_seconds: 600,
  timeout_seconds: 30,
  balance_endpoint: '',
  balance_response_path: '',
  balance_divisor: 1.0,
})
const form = ref(defaultForm())
const rules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  base_url: [{ required: true, message: '请输入 Base URL', trigger: 'blur' }],
}

const authCaptureVisible = ref(false)

const authCaptureInitialUrl = computed(() => {
  const base = (form.value.base_url || '').replace(/\/+$/, '')
  if (!base) return ''
  return base + '/login'
})

function openAuthCapture() {
  authCaptureVisible.value = true
}

function handleAuthCaptureSelect(candidate: { type: string; value: string; cookie_name?: string; cookie_value?: string; new_api_user?: string }) {
  if (candidate.type === 'bearer_token') {
    form.value.auth_type = 'bearer'
    form.value.auth_config.token = candidate.value
    ElMessage.success('已填入 Bearer Token')
  } else if (candidate.type === 'cookie') {
    form.value.auth_type = 'cookie'
    form.value.auth_config.cookie_string = candidate.cookie_name && candidate.cookie_value
      ? `${candidate.cookie_name}=${candidate.cookie_value}`
      : candidate.value
    if (candidate.new_api_user) {
      form.value.auth_config.new_api_user = candidate.new_api_user
      form.value.api_prefix = ''
      form.value.groups_endpoint = '/api/user/self/groups'
      form.value.rate_endpoint = '/api/user/self/groups'
    } else if (quickPlatform.value === 'new-api-user') {
      form.value.api_prefix = ''
      form.value.groups_endpoint = '/api/user/self/groups'
      form.value.rate_endpoint = '/api/user/self/groups'
      ElMessage.warning('已填入 Cookie，但未提取到 New-Api-User，请重新登录后再提取')
    }
    ElMessage.success('已填入 Cookie')
  } else if (candidate.type === 'api_key') {
    form.value.auth_type = 'api_key'
    form.value.auth_config.key = candidate.value
    form.value.auth_config.header = 'X-API-Key'
    ElMessage.success('已填入 API Key')
  } else if (candidate.type === 'credential') {
    // Try to guess — if value starts with 'sk-', treat as bearer
    if (candidate.value.startsWith('sk-')) {
      form.value.auth_type = 'bearer'
      form.value.auth_config.token = candidate.value
      ElMessage.success('已填入 Bearer Token (sk-key)')
    } else {
      form.value.auth_type = 'bearer'
      form.value.auth_config.token = candidate.value
      ElMessage.success('已填入认证信息')
    }
  }
}

const quickPlatform = ref('sub2api')

function handlePlatformChange(val: string) {
  if (val === 'sub2api') {
    form.value.api_prefix = '/api/v1'
    form.value.groups_endpoint = '/groups/available'
    form.value.rate_endpoint = '/groups/rates'
    form.value.auth_type = 'login_password'
    form.value.auth_config.login_path = '/auth/login'
    form.value.auth_config.username_field = 'email'
    form.value.balance_endpoint = '/auth/me'
    form.value.balance_response_path = 'data.balance'
  } else if (val === 'new-api') {
    form.value.api_prefix = ''
    form.value.groups_endpoint = '/api/group/'
    form.value.rate_endpoint = '/api/option/?key=GroupRatio'
    form.value.auth_type = 'bearer'
    form.value.balance_endpoint = '/api/user/self'
    form.value.balance_response_path = 'data.quota'
    form.value.balance_divisor = 500000
  } else if (val === 'new-api-user') {
    form.value.api_prefix = ''
    form.value.groups_endpoint = '/api/user/self/groups'
    form.value.rate_endpoint = '/api/user/self/groups'
    form.value.auth_type = 'login_password'
    form.value.auth_config.login_path = '/api/user/login'
    form.value.auth_config.username_field = 'username'
    form.value.balance_endpoint = '/api/user/self'
    form.value.balance_response_path = 'data.quota'
    form.value.balance_divisor = 500000
  } else {
    form.value.balance_endpoint = ''
    form.value.balance_response_path = ''
  }
}

const detailVisible = ref(false)
const detailUpstream = ref<UpstreamData | null>(null)
const snapshots = ref<any[]>([])
const snapshotLoading = ref(false)
const expandedId = ref<number | null>(null)
const snapshotOffset = ref(0)
const snapshotLimit = 20

const metrics = computed(() => ({
  total: list.value.length,
  healthy: list.value.filter((item) => item.last_status === 'healthy').length,
  enabled: list.value.filter((item) => item.enabled).length,
  unhealthy: list.value.filter((item) => item.last_status === 'unhealthy').length,
  balanceCount: list.value.filter((item) => item.balance_endpoint).length,
}))

const healthyRate = computed(() => {
  if (metrics.value.total === 0) return 0
  return Math.round((metrics.value.healthy / metrics.value.total) * 100)
})

const pendingChecks = computed(() => list.value.filter((item) => !item.last_checked_at).length)

const latestCheckedAt = computed(() => {
  const times = list.value
    .map((item) => item.last_checked_at)
    .filter((value): value is string => Boolean(value))
    .sort((a, b) => new Date(toUTC(b)).getTime() - new Date(toUTC(a)).getTime())
  return times[0] || ''
})

const attentionList = computed(() =>
  list.value
    .filter((item) => item.last_status === 'unhealthy' || item.last_error)
    .slice(0, 4),
)

const recentChecks = computed(() =>
  [...list.value]
    .filter((item) => Boolean(item.last_checked_at))
    .sort((a, b) => new Date(toUTC(b.last_checked_at as string)).getTime() - new Date(toUTC(a.last_checked_at as string)).getTime())
    .slice(0, 5),
)

const statusLabel = (s: string) => ({ healthy: '健康', unhealthy: '异常', unknown: '未知' }[s] || s)
const authLabel = (s: string) => ({ none: '无认证', bearer: 'Bearer', cookie: 'Cookie', api_key: 'API Key', login_password: '邮箱密码' }[s] || s)

function formatBalance(value: number | null | undefined): string {
  if (value === null || value === undefined) return '—'
  return value.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}
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 fmtTimeFull = (t: string) => dayjs(toUTC(t)).format('YYYY-MM-DD HH:mm:ss')

function groupRows(snapshot: any) {
  if (!snapshot?.groups) return []
  return Object.values(snapshot.groups) as any[]
}

function shrinkError(value: string) {
  return value.length > 40 ? `${value.slice(0, 40)}…` : value
}

async function loadList() {
  tableLoading.value = true
  try {
    const res = await upstreamsApi.list()
    list.value = res.data
  } finally {
    tableLoading.value = false
  }
}

function openCreate() {
  editingId.value = null
  quickPlatform.value = 'sub2api'
  form.value = defaultForm()
  drawerVisible.value = true
}

function openEdit(row: UpstreamData) {
  editingId.value = row.id
  form.value = {
    name: row.name,
    base_url: row.base_url,
    api_prefix: row.api_prefix,
    auth_type: row.auth_type,
    auth_config: { ...(row.auth_config_masked as Record<string, any>) },
    rate_endpoint: row.rate_endpoint,
    groups_endpoint: row.groups_endpoint,
    enabled: row.enabled,
    check_interval_seconds: row.check_interval_seconds,
    timeout_seconds: row.timeout_seconds,
    balance_endpoint: row.balance_endpoint || '',
    balance_response_path: row.balance_response_path || '',
    balance_divisor: row.balance_divisor ?? 1.0,
  }
  drawerVisible.value = true
}

async function handleSave() {
  const valid = await formRef.value?.validate().catch(() => false)
  if (!valid) return
  saving.value = true
  try {
    if (editingId.value) {
      await upstreamsApi.update(editingId.value, form.value)
      ElMessage.success('保存成功')
    } else {
      await upstreamsApi.create(form.value as any)
      ElMessage.success('创建成功')
    }
    drawerVisible.value = false
    loadList()
  } catch (e: any) {
    ElMessage.error(e.response?.data?.detail || '保存失败')
  } finally {
    saving.value = false
  }
}

async function toggleEnabled(row: UpstreamData) {
  try {
    await upstreamsApi.update(row.id, { enabled: row.enabled })
    ElMessage.success(row.enabled ? '已启用' : '已停用')
  } catch {
    row.enabled = !row.enabled
    ElMessage.error('操作失败')
  }
}

async function testUpstream(row: any) {
  row._testing = true
  try {
    const res = await upstreamsApi.test(row.id)
    if (res.data.success) ElMessage.success(res.data.message)
    else ElMessage.error(res.data.detail || res.data.message)
    await loadList()
  } finally {
    row._testing = false
  }
}

async function checkNow(row: any) {
  row._checking = true
  try {
    const res = await upstreamsApi.checkNow(row.id)
    ElMessage[res.data.success ? 'success' : 'error'](res.data.message)
    loadList()
  } finally {
    row._checking = false
  }
}

function openDetail(row: UpstreamData) {
  detailUpstream.value = row
  snapshots.value = []
  snapshotOffset.value = 0
  expandedId.value = null
  detailVisible.value = true
}

async function loadSnapshots() {
  if (!detailUpstream.value) return
  snapshotLoading.value = true
  try {
    const res = await upstreamsApi.listSnapshots(detailUpstream.value.id, snapshotLimit, snapshotOffset.value)
    snapshots.value = res.data
    if (res.data.length > 0 && expandedId.value === null) {
      expandedId.value = res.data[0].id
    }
  } catch {
    ElMessage.error('加载历史失败')
  } finally {
    snapshotLoading.value = false
  }
}

function toggleExpand(snap: any) {
  expandedId.value = expandedId.value === snap.id ? null : snap.id
}

function prevSnapPage() {
  snapshotOffset.value = Math.max(0, snapshotOffset.value - snapshotLimit)
  expandedId.value = null
  loadSnapshots()
}

function nextSnapPage() {
  snapshotOffset.value += snapshotLimit
  expandedId.value = null
  loadSnapshots()
}

async function confirmDelete(row: UpstreamData) {
  try {
    await ElMessageBox.confirm(`确认删除上游 "${row.name}" ？`, '删除确认', { type: 'warning' })
    await upstreamsApi.delete(row.id)
    ElMessage.success('已删除')
    loadList()
  } catch {
    // noop
  }
}

onMounted(loadList)
</script>

<style scoped>
.auth-field-row {
  display: flex;
  gap: 8px;
  align-items: center;
}
.auth-field-row .el-input {
  flex: 1;
}
.auth-field-row .el-button {
  flex-shrink: 0;
}

.upstreams-page {
  padding-bottom: 1rem;
}

.upstreams-hero {
  align-items: center;
  padding: 1.2rem 1.25rem;
  min-height: 8.7rem;
  border-radius: var(--radius-shell);
  background:
    radial-gradient(circle at top right, rgba(217, 139, 66, 0.14), transparent 24%),
    linear-gradient(180deg, rgba(255, 244, 232, 0.03), transparent 28%),
    var(--bg-panel);
}

.upstreams-hero .page-heading {
  gap: 0.32rem;
}

.upstreams-hero .page-title {
  font-size: clamp(1.95rem, 1.45rem + 1.2vw, 2.65rem);
}

.upstreams-hero .page-desc {
  max-width: 50rem;
  font-size: 0.9rem;
  line-height: 1.55;
}

.hero-actions {
  align-self: flex-end;
}

.upstreams-content {
  display: grid;
  grid-template-columns: minmax(0, 1.9fr) minmax(360px, 0.82fr);
  gap: 1rem;
  align-items: stretch;
}

.data-stage {
  padding: 1rem;
  min-width: 0;
}

.data-stage,
.upstreams-side {
  min-height: 33rem;
}

.data-stage-head {
  min-height: 4.65rem;
  margin-bottom: 0.85rem;
}

.data-stage-title {
  margin-top: 0.28rem;
  font-size: clamp(1.4rem, 1.05rem + 0.8vw, 2rem);
  font-weight: 800;
}

.data-stage-note {
  color: var(--text-muted);
  font-size: 0.86rem;
  line-height: 1.6;
}

.upstreams-side {
  display: grid;
  align-content: start;
  padding: 1rem;
  min-width: 0;
}

.side-section {
  padding-block: 1rem;
  border-top: 1px solid var(--border-color);
}

.side-section:first-child {
  padding-top: 0;
  border-top: 0;
}

.side-section:last-child {
  padding-bottom: 0;
}

.overview-section {
  min-height: 12.4rem;
}

.insight-head {
  min-height: 3.75rem;
  margin-bottom: 0.9rem;
}

.insight-head.compact {
  margin-bottom: 0.75rem;
}

.insight-title {
  margin: 0.24rem 0 0;
  font-size: 1.05rem;
  font-weight: 700;
}

.insight-pill {
  display: inline-flex;
  align-items: center;
  padding: 0.38rem 0.7rem;
  border-radius: 999px;
  background: rgba(239, 175, 99, 0.12);
  border: 1px solid rgba(239, 175, 99, 0.18);
  color: var(--color-primary-strong);
  font-size: 0.76rem;
  font-weight: 700;
}

.insight-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.8rem;
}

.insight-metric {
  display: grid;
  gap: 0.28rem;
  padding: 0.85rem 0.9rem;
  border-radius: var(--radius-control);
  background: rgba(255, 244, 232, 0.03);
  border: 1px solid rgba(255, 244, 232, 0.06);
}

.insight-metric span {
  color: var(--text-muted);
  font-size: 0.75rem;
}

.insight-metric strong {
  color: var(--text-primary);
  font-size: 1rem;
  line-height: 1.35;
}

.feed-list,
.timeline-list {
  display: grid;
  gap: 0.7rem;
}

.feed-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  width: 100%;
  padding: 0.85rem 0.9rem;
  border: 1px solid rgba(255, 244, 232, 0.06);
  border-radius: var(--radius-control);
  background: rgba(255, 244, 232, 0.02);
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.feed-item:hover {
  border-color: rgba(239, 175, 99, 0.2);
  background: rgba(255, 244, 232, 0.04);
}

.feed-main,
.timeline-main {
  min-width: 0;
  display: grid;
  gap: 0.32rem;
}

.feed-top,
.timeline-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.7rem;
}

.feed-name,
.timeline-name {
  color: var(--text-primary);
  font-weight: 700;
}

.feed-meta,
.timeline-meta {
  color: var(--text-muted);
  font-size: 0.82rem;
  line-height: 1.45;
}

.feed-link {
  color: var(--color-primary-strong);
  font-size: 0.8rem;
  white-space: nowrap;
}

.side-empty {
  min-height: auto;
  padding: 0.6rem 0;
}

.auth-badge {
  background: rgba(134, 183, 199, 0.12);
  color: var(--color-info);
  border-color: rgba(134, 183, 199, 0.18);
}

.time-inline {
  color: var(--text-secondary);
  font-size: 0.84rem;
}

.info-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.85rem;
  margin-bottom: 1rem;
}

.info-card {
  padding: 1rem;
}

.info-label {
  margin-bottom: 0.45rem;
  color: var(--text-soft);
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.info-value {
  font-size: 0.96rem;
  color: var(--text-primary);
}

.error-box {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin-bottom: 1rem;
  padding: 0.9rem 1rem;
  border-radius: var(--radius-control);
  color: var(--color-danger);
  background: rgba(221, 126, 114, 0.08);
  border: 1px solid rgba(221, 126, 114, 0.16);
}

.section-title {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin-bottom: 0.8rem;
  font-size: 1rem;
  font-weight: 700;
}

.section-sub {
  color: var(--text-muted);
  font-size: 0.78rem;
  font-weight: 500;
}

.snapshot-list {
  display: grid;
  gap: 0.7rem;
  min-height: 4rem;
}

.snap-item {
  border-radius: var(--radius-control);
  border: 1px solid var(--border-color);
  background: rgba(255, 244, 232, 0.02);
  overflow: hidden;
}

.snap-item.expanded {
  border-color: rgba(239, 175, 99, 0.24);
}

.snap-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 0.95rem 1rem;
  cursor: pointer;
}

.snap-left,
.snap-right,
.snap-pagination {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.expand-icon {
  color: var(--text-soft);
  transition: transform var(--motion-fast) var(--ease-standard);
}

.snap-item.expanded .expand-icon {
  transform: rotate(90deg);
}

.snap-time {
  color: var(--text-secondary);
  font-size: 0.85rem;
}

.snap-body {
  padding: 0 0.35rem 0.35rem;
  border-top: 1px solid var(--border-color);
}

.rate-value {
  color: var(--color-primary-strong);
  font-weight: 700;
}

.override-value {
  color: var(--color-warning);
}

.balance-value {
  color: var(--color-success);
  font-weight: 600;
}

.form-hint {
  font-size: 0.75rem;
  color: var(--text-soft);
  margin-top: 0.25rem;
  line-height: 1.4;
}

.form-hint code {
  background: var(--bg-soft);
  padding: 0 0.3em;
  border-radius: 3px;
  font-size: 0.85em;
}

.snap-pagination {
  justify-content: center;
  margin-top: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border-color);
}

@media (min-width: 768px) {
  .info-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 1199px) {
  .upstreams-content {
    grid-template-columns: 1fr;
  }
}

@media (min-width: 1200px) {
  .info-cards {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (max-width: 767px) {
  .upstreams-hero,
  .data-stage,
  .upstreams-side {
    padding: 1rem;
  }

  .data-stage,
  .upstreams-side {
    min-height: 0;
  }

  .hero-actions {
    width: 100%;
  }

  .hero-actions :deep(.el-button) {
    flex: 1 1 100%;
  }

  .insight-grid {
    grid-template-columns: 1fr;
  }

  .feed-item,
  .timeline-item {
    align-items: flex-start;
  }
}

.action-row .el-button--danger {
  --el-button-bg-color: transparent;
  --el-button-border-color: transparent;
}
.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);
}
</style>
