<script setup lang="ts">
import { NButton, NModal } from 'naive-ui'
import { computed, ref, watch } from 'vue'

import { activateApiKey, addUserApiKey, deleteUserApiKey, listUserApiKeys } from '@/api/tenant'
import ConfirmPop from '@/components/ConfirmPop.vue'
import { fmtTime } from '@/composables/useFormat'
import { useMobileModal } from '@/composables/useMobileModal'
import { useToast } from '@/composables/useToast'
import type { CreatedApiKey, IamUser, UserApiKey } from '@/types/api'

const props = defineProps<{ show: boolean; cfgId: number; user: IamUser | null }>()
const emit = defineEmits<{ 'update:show': [boolean] }>()

const toast = useToast()
const { modalStyle, modalClass } = useMobileModal(760)

const keys = ref<UserApiKey[]>([])
const loading = ref(false)
const busy = ref(false)
const activating = ref(false)
const activated = ref(false)
const selectedFp = ref('')
/** 本次弹窗内刚创建的 key;选中它时右栏进入结果态(私钥仅此一次可下载) */
const created = ref<CreatedApiKey | null>(null)

const selected = computed(() => keys.value.find((k) => k.fingerprint === selectedFp.value) ?? null)
const isCreatedView = computed(
  () => !!created.value && selectedFp.value === created.value.fingerprint,
)

watch(
  () => props.show,
  (show) => {
    if (show) {
      created.value = null
      activated.value = false
      selectedFp.value = ''
      void reload()
    }
  },
)

async function reload() {
  if (!props.user) return
  loading.value = true
  try {
    keys.value = (await listUserApiKeys(props.cfgId, props.user.id)).items
    if (!keys.value.some((k) => k.fingerprint === selectedFp.value))
      selectedFp.value = keys.value[0]?.fingerprint ?? ''
  } catch (e) {
    toast.error(e instanceof Error ? e.message : '加载失败')
  } finally {
    loading.value = false
  }
}

async function doAdd() {
  if (!props.user || busy.value || keys.value.length >= 3) return
  busy.value = true
  try {
    const res = await addUserApiKey(props.cfgId, props.user.id)
    created.value = res
    activated.value = false
    await reload()
    selectedFp.value = res.fingerprint
  } catch (e) {
    toast.error(e instanceof Error ? e.message : '创建失败')
  } finally {
    busy.value = false
  }
}

async function doDelete(fp: string) {
  if (!props.user) return
  try {
    await deleteUserApiKey(props.cfgId, props.user.id, fp)
    toast.success('已删除')
    if (created.value?.fingerprint === fp) created.value = null
    await reload()
  } catch (e) {
    toast.error(e instanceof Error ? e.message : '删除失败')
  }
}

/** 把刚创建的 key 设为面板签名凭据;私钥仅存在于本次弹窗内存中 */
async function doActivate() {
  if (!created.value || activating.value) return
  activating.value = true
  try {
    await activateApiKey(props.cfgId, created.value.fingerprint, created.value.privateKey)
    activated.value = true
    toast.success('面板签名凭据已切换到该 key')
    await reload()
  } catch (e) {
    toast.error(e instanceof Error ? e.message : '设置失败')
  } finally {
    activating.value = false
  }
}

function download() {
  if (!created.value) return
  const blob = new Blob([created.value.privateKey], { type: 'application/x-pem-file' })
  const a = document.createElement('a')
  a.href = URL.createObjectURL(blob)
  a.download = 'oci_api_key.pem'
  a.click()
  URL.revokeObjectURL(a.href)
}

async function copyIni(text: string) {
  await navigator.clipboard.writeText(text)
  toast.success('已复制配置')
}
</script>

<template>
  <NModal
    :show="show"
    preset="card"
    :style="modalStyle"
    :class="modalClass"
    @update:show="emit('update:show', $event)"
  >
    <template #header>
      <div>
        <div class="text-[15px] leading-tight font-semibold">API Keys</div>
        <div class="mt-1 text-xs font-normal text-ink-3">
          {{ user?.name }}{{ user?.isCurrentUser ? ' · 当前签名用户' : '' }}
        </div>
      </div>
    </template>

    <div class="flex max-md:flex-col md:min-h-[300px]">
      <!-- 左栏:key 列表 -->
      <div
        class="flex w-[218px] flex-none flex-col gap-0.5 border-r border-line-soft pr-2.5 max-md:w-full max-md:border-r-0 max-md:border-b max-md:pr-0 max-md:pb-2.5"
      >
        <div class="px-2.5 pb-1.5 text-[11px] text-ink-3">{{ keys.length }} / 3 把</div>
        <div v-if="loading && !keys.length" class="px-2.5 py-6 text-center text-xs text-ink-3">加载中…</div>
        <button
          v-for="k in keys"
          :key="k.fingerprint"
          type="button"
          class="cursor-pointer rounded-[7px] px-2.5 py-[7px] text-left hover:bg-row-hover"
          :class="selectedFp === k.fingerprint ? 'bg-row-hover' : ''"
          @click="selectedFp = k.fingerprint"
        >
          <div class="mono truncate text-xs">{{ k.fingerprint }}</div>
          <div class="mt-0.5 text-[11px] text-ink-3">
            {{ created?.fingerprint === k.fingerprint ? '刚刚创建' : fmtTime(k.timeCreated) }}
          </div>
        </button>
        <button
          type="button"
          class="mt-auto cursor-pointer rounded-[7px] border border-dashed border-line px-2.5 py-[7px] text-xs text-ink-3 enabled:hover:border-accent enabled:hover:text-accent disabled:opacity-60 max-md:mt-2"
          :disabled="busy || keys.length >= 3"
          @click="doAdd"
        >
          {{ busy ? '创建中…' : '+ 添加 Key' }}
        </button>
      </div>

      <!-- 右栏:详情 / 创建结果 -->
      <div class="min-w-0 flex-1 pt-0.5 pl-4 max-md:pt-3 max-md:pl-0">
        <template v-if="isCreatedView && created">
          <div class="rounded-lg bg-warn/14 px-3 py-2 text-xs leading-relaxed text-warn">
            私钥仅可下载这一次,离开本页后无法再次获取
          </div>
          <div class="mt-3 flex items-center gap-2 rounded-lg border border-line-soft bg-white px-3 py-2.5">
            <span class="mono text-xs">oci_api_key.pem</span>
            <span class="text-[11px] text-ink-3">RSA-2048</span>
            <span class="min-w-0 flex-1"></span>
            <NButton size="tiny" type="primary" @click="download">下载私钥</NButton>
          </div>
          <div class="mt-3 overflow-hidden rounded-lg border border-line-soft bg-white">
            <div class="flex items-center px-3 pt-2">
              <span class="text-[11px] text-ink-3">~/.oci/config</span>
              <span class="min-w-0 flex-1"></span>
              <NButton size="tiny" quaternary @click="copyIni(created.configIni)">复制</NButton>
            </div>
            <pre class="mono overflow-x-auto px-3 pt-1 pb-2.5 text-xs leading-relaxed">{{ created.configIni }}</pre>
          </div>
          <div v-if="user?.isCurrentUser" class="mt-3 flex">
            <NButton size="tiny" secondary :loading="activating" :disabled="activated" @click="doActivate">
              {{ activated ? '已设为面板签名 key' : '设为面板签名 key' }}
            </NButton>
          </div>
        </template>

        <template v-else-if="selected">
          <div class="mono text-[13px] leading-relaxed break-all">{{ selected.fingerprint }}</div>
          <div class="mt-1 text-[11.5px] text-ink-3">
            创建于 {{ fmtTime(selected.timeCreated) }} · RSA-2048{{ selected.isCurrent ? ' · 面板签名使用中' : '' }}
          </div>
          <div class="mt-3 overflow-hidden rounded-lg border border-line-soft bg-white">
            <div class="flex items-center px-3 pt-2">
              <span class="text-[11px] text-ink-3">~/.oci/config · key_file 指向本机保存的私钥</span>
              <span class="min-w-0 flex-1"></span>
              <NButton size="tiny" quaternary @click="copyIni(selected.configIni)">复制</NButton>
            </div>
            <pre class="mono overflow-x-auto px-3 pt-1 pb-2.5 text-xs leading-relaxed">{{ selected.configIni }}</pre>
          </div>
          <div class="mt-3 flex">
            <span class="min-w-0 flex-1"></span>
            <ConfirmPop
              v-if="!selected.isCurrent"
              title="删除该 API Key?"
              content="删除后使用它签名的调用立即失效。"
              confirm-text="删除"
              :on-confirm="() => doDelete(selectedFp)"
            >
              <template #trigger>
                <NButton size="tiny" secondary type="error">删除此 Key</NButton>
              </template>
            </ConfirmPop>
          </div>
        </template>

        <div v-else-if="!loading" class="py-12 text-center text-xs text-ink-3">
          该用户暂无 API Key,点左侧「添加 Key」创建
        </div>
      </div>
    </div>
  </NModal>
</template>
