<template>
  <div class="page-content">
    <div class="mb-5">
      <h2 class="text-xl font-semibold">账号安全</h2>
      <p class="text-g-500 mt-1 text-sm">管理登录设备、新设备登录提醒与扫码登录绑定</p>
    </div>

    <ElCard shadow="never" class="mb-5">
      <template #header><div class="font-medium">登录设备</div></template>
      <ElTable v-loading="loading" :data="sessions">
        <ElTableColumn label="当前" width="80">
          <template #default="{ row }"><ElTag v-if="row.current" type="success">当前</ElTag></template>
        </ElTableColumn>
        <ElTableColumn prop="ip" label="IP 地址" width="160" />
        <ElTableColumn prop="user_agent" label="设备 / 浏览器" min-width="240">
          <template #default="{ row }">{{ row.user_agent || '未知设备' }}</template>
        </ElTableColumn>
        <ElTableColumn label="登录时间" width="180">
          <template #default="{ row }">{{ formatTime(row.issued_at) }}</template>
        </ElTableColumn>
        <ElTableColumn label="操作" width="100" fixed="right">
          <template #default="{ row }">
            <ElButton link type="danger" :disabled="row.current" @click="revoke(row)">下线</ElButton>
          </template>
        </ElTableColumn>
      </ElTable>
      <ElEmpty v-if="!sessions.length && !loading" description="暂无其他登录设备" />
    </ElCard>

    <ElCard shadow="never" class="mb-5">
      <template #header><div class="font-medium">登录提醒</div></template>
      <div class="flex items-center justify-between">
        <div>
          <div class="text-sm">新设备登录通知</div>
          <p class="text-g-500 mt-1 text-sm">账号在新设备登录时通过站内消息提醒，可及时发现异常登录</p>
        </div>
        <ElSwitch v-model="loginNotify" :loading="savingPrefs" @change="savePrefs" />
      </div>
    </ElCard>

    <ElCard shadow="never" class="mb-5">
      <template #header><div class="font-medium">智能体安全策略</div></template>
      <div class="flex flex-col gap-4">
        <div class="flex items-center justify-between">
          <div>
            <div class="text-sm">个人工具自动审批</div>
            <p class="text-g-500 mt-1 text-sm">开启后你通过个人凭据调用需审批的工具时不再要求管理员审批（平台级审批标记仍适用于其他调用）</p>
          </div>
          <ElSwitch v-model="policy.auto_approve_tools" :loading="savingPolicy" @change="savePolicy" />
        </div>
        <div class="flex items-center justify-between">
          <div>
            <div class="text-sm">个人限流倍数</div>
            <p class="text-g-500 mt-1 text-sm">你的个人调用按此倍数放宽工具限流（例如工具限流 10 rpm、倍数 2 时个人可调用 20 rpm）</p>
          </div>
          <ElInputNumber v-model="policy.rate_limit_multiplier" :min="1" :max="10" class="w-32" :disabled="savingPolicy" @change="savePolicy" />
        </div>
      </div>
    </ElCard>

    <ElCard shadow="never">
      <template #header>
        <div class="flex items-center justify-between">
          <div class="font-medium">扫码登录绑定</div>
          <span class="text-g-400 text-xs">绑定后可用企业微信 / 钉钉 / 飞书扫码直接登录</span>
        </div>
      </template>
      <ElTable v-loading="loading" :data="bindingRows">
        <ElTableColumn label="平台" width="140">
          <template #default="{ row }">{{ providerName(row.kind) }}</template>
        </ElTableColumn>
        <ElTableColumn prop="provider_uid" label="企业账号" min-width="200" />
        <ElTableColumn label="绑定时间" width="180">
          <template #default="{ row }">{{ row.created_at }}</template>
        </ElTableColumn>
        <ElTableColumn label="操作" width="160" fixed="right">
          <template #default="{ row }">
            <template v-if="row.bound">
              <ElButton link type="primary" @click="reBind(row.kind)">重新绑定</ElButton>
              <ElButton link type="danger" @click="unbind(row.kind)">解绑</ElButton>
            </template>
            <ElButton v-else link type="primary" @click="bind(row.kind)">绑定</ElButton>
          </template>
        </ElTableColumn>
      </ElTable>
      <p class="text-g-400 mt-3 text-xs">绑定需使用平台 App 扫码授权；同一平台账号只能绑定到一个本系统账号。未配置的身份源请在管理端「系统管理 → 身份源」中启用。</p>
    </ElCard>
  </div>
</template>
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  AgentPolicy, ProviderBinding, SessionView, fetchAgentPolicy, fetchMySessions, fetchProviderBindings,
  fetchSecurityPrefs, revokeSession, setAgentPolicy, setSecurityPrefs, startSocialBind, unbindSocial
} from '@/api/portal'

const loading = ref(false)
const savingPrefs = ref(false)
const savingPolicy = ref(false)
const policy = reactive<AgentPolicy>({ auto_approve_tools: false, rate_limit_multiplier: 1 })
const sessions = ref<SessionView[]>([])
const loginNotify = ref(true)
const bindings = ref<ProviderBinding[]>([])

const providerKinds = ['wecom', 'dingtalk', 'feishu']
const providerNames: Record<string, string> = { wecom: '企业微信', dingtalk: '钉钉', feishu: '飞书' }

const bindingRows = computed(() =>
  providerKinds.map((kind) => {
    const item = bindings.value.find((b) => b.kind === kind)
    return { kind, bound: !!item, provider_uid: item?.provider_uid || '—', created_at: item?.created_at || '—' }
  })
)

function providerName(kind: string) {
  return providerNames[kind] || kind
}

function formatTime(epochSeconds: number) {
  if (!epochSeconds) return '—'
  return new Date(epochSeconds * 1000).toLocaleString()
}

async function loadAll() {
  loading.value = true
  try {
    const [sessionList, pref, bindingList, agentPolicy] = await Promise.all([fetchMySessions(), fetchSecurityPrefs(), fetchProviderBindings(), fetchAgentPolicy()])
    sessions.value = sessionList
    loginNotify.value = pref.login_notify
    bindings.value = bindingList
    policy.auto_approve_tools = agentPolicy.auto_approve_tools
    policy.rate_limit_multiplier = agentPolicy.rate_limit_multiplier || 1
  } finally {
    loading.value = false
  }
}

async function revoke(row: SessionView) {
  await ElMessageBox.confirm('下线该设备后，其登录状态将立即失效。确定下线？', '下线设备', { type: 'warning' })
  await revokeSession(row.id)
  sessions.value = sessions.value.filter((item) => item.id !== row.id)
  ElMessage.success('已下线')
}

async function savePrefs(value: string | number | boolean) {
  const enabled = value === true || value === 'true' || value === 1
  savingPrefs.value = true
  try {
    await setSecurityPrefs(enabled)
    ElMessage.success(enabled ? '已开启登录提醒' : '已关闭登录提醒')
  } catch {
    loginNotify.value = !enabled
    ElMessage.error('保存失败')
  } finally {
    savingPrefs.value = false
  }
}

async function savePolicy() {
  savingPolicy.value = true
  try {
    await setAgentPolicy({ auto_approve_tools: policy.auto_approve_tools, rate_limit_multiplier: policy.rate_limit_multiplier })
    ElMessage.success('安全策略已保存')
  } catch {
    ElMessage.error('保存失败')
    await loadAll()
  } finally {
    savingPolicy.value = false
  }
}

async function bind(kind: string) {
  const { redirect_url } = await startSocialBind(kind)
  const win = window.open(redirect_url, '_blank', 'width=720,height=600')
  if (win) {
    // 扫码完成后回调窗口会带 bind_result 跳回门户;本窗口聚焦时刷新绑定状态。
    const timer = window.setInterval(async () => {
      if (win.closed) {
        window.clearInterval(timer)
        await loadAll()
      }
    }, 1000)
    window.addEventListener('focus', () => {
      window.clearInterval(timer)
      loadAll()
    }, { once: true })
  }
}

async function reBind(kind: string) {
  await bind(kind)
}

async function unbind(kind: string) {
  await ElMessageBox.confirm(`解绑后该平台将无法扫码登录此账号，确定解绑？`, '解除绑定', { type: 'warning' })
  await unbindSocial(kind)
  await loadAll()
  ElMessage.success('已解绑')
}

onMounted(() => {
  loadAll()
  // 扫码绑定回调 302 回门户时携带 bind_result(位于 # 之前的 query)。
  const pathQuery = new URLSearchParams(window.location.search)
  const result = pathQuery.get('bind_result')
  if (result) {
    history.replaceState(null, '', window.location.pathname + window.location.hash)
    if (result === 'ok') ElMessage.success('扫码登录绑定成功')
    else if (result === 'conflict') ElMessage.error('该企业账号已被其他账号绑定')
    else ElMessage.error('扫码绑定失败或已取消')
  }
})
</script>
