<script setup lang="ts">
import { NButton, NDataTable, NPopconfirm, NSwitch, useDialog, type DataTableColumns } from 'naive-ui'
import { h, ref } from 'vue'

import {
  activateIdp,
  createSignOnExemption,
  deleteIdp,
  deleteSignOnExemption,
  downloadSamlMetadata,
  listIdps,
  listSignOnRules,
} from '@/api/tenant'
import FootNote from '@/components/FootNote.vue'
import StatusBadge from '@/components/StatusBadge.vue'
import IdpFormModal from '@/components/tenant/IdpFormModal.vue'
import { useAsync } from '@/composables/useAsync'
import type { IdentityProvider, SignOnRule } from '@/types/api'
import { useToast } from '@/composables/useToast'

const props = defineProps<{ cfgId: number; domainId?: string }>()

const message = useToast()
const dialog = useDialog()
const idps = useAsync(() => listIdps(props.cfgId, props.domainId))
const rules = useAsync(() => listSignOnRules(props.cfgId, props.domainId))
const showCreate = ref(false)

async function act(fn: () => Promise<unknown>, ok: string) {
  try {
    await fn()
    message.success(ok)
    void idps.run()
    void rules.run()
  } catch (e) {
    message.error(e instanceof Error ? e.message : '操作失败')
  }
}

const idpColumns: DataTableColumns<IdentityProvider> = [
  {
    title: 'IdP',
    key: 'name',
    minWidth: 220,
    render: (row) =>
      h('div', [
        h('div', { class: 'font-medium' }, row.name),
        h('div', { class: 'mono text-xs text-ink-3 mt-px break-all' }, row.partnerProviderId),
      ]),
  },
  { title: '协议', key: 'type', width: 80 },
  {
    title: '状态',
    key: 'enabled',
    width: 100,
    render: (row) =>
      h(StatusBadge, {
        kind: row.enabled ? 'run' : 'stop',
        label: row.enabled ? '已启用' : '已停用',
      }),
  },
  {
    title: 'JIT',
    key: 'jitEnabled',
    width: 70,
    render: (row) => h('span', { class: 'text-[13px]' }, row.jitEnabled ? '开启' : '关闭'),
  },
  {
    title: '操作',
    key: 'actions',
    width: 160,
    render: (row) =>
      h('div', { class: 'flex items-center gap-3' }, [
        h(NSwitch, {
          size: 'small',
          value: row.enabled,
          onUpdateValue: (v: boolean) =>
            act(() => activateIdp(props.cfgId, row.id, v, props.domainId), v ? '已激活并显示到登录页' : '已停用'),
        }),
        h(
          NButton,
          { size: 'tiny', quaternary: true, type: 'error', onClick: () => confirmDeleteIdp(row) },
          { default: () => '删除' },
        ),
      ]),
  },
]

const ruleColumns: DataTableColumns<SignOnRule> = [
  { title: '#', key: 'sequence', width: 50 },
  {
    title: '规则',
    key: 'name',
    minWidth: 180,
    render: (row) =>
      h('div', [
        h('div', { class: 'mono text-[12.5px]' }, row.name),
        h(
          'div',
          { class: 'text-xs text-ink-3 mt-px' },
          row.conditionAttribute ? `${row.conditionAttribute} in ${row.conditionValue}` : '默认兜底规则',
        ),
      ]),
  },
  {
    title: '认证因子',
    key: 'authenticationFactor',
    width: 120,
    render: (row) =>
      h(StatusBadge, {
        kind: row.authenticationFactor === 'IDP' ? 'prov' : 'check',
        label: row.authenticationFactor === 'IDP' ? '仅 IdP' : 'IdP + 2FA',
        dot: false,
      }),
  },
  {
    title: '操作',
    key: 'actions',
    width: 110,
    render: (row) =>
      row.builtIn
        ? h('span', { class: 'text-xs text-ink-3' }, '内置')
        : h(
            NPopconfirm,
            {
              onPositiveClick: () =>
                act(() => deleteSignOnExemption(props.cfgId, row.id, props.domainId), '已删除免 MFA 规则并恢复优先级'),
            },
            {
              trigger: () =>
                h(NButton, { size: 'tiny', quaternary: true, type: 'error' }, { default: () => '删除' }),
              default: () => '删除该免 MFA 规则？删除后经此 IdP 登录将重新要求 MFA',
            },
          ),
  },
]

async function doDownloadMetadata() {
  try {
    await downloadSamlMetadata(props.cfgId, props.domainId)
    message.success('SAML 元数据已下载')
  } catch (e) {
    message.error(e instanceof Error ? e.message : '下载失败')
  }
}

function confirmDeleteIdp(row: IdentityProvider) {
  dialog.warning({
    title: '删除身份提供商',
    content: () =>
      h('div', { class: 'text-[13px]' }, [
        h('p', `确定删除 IdP「${row.name}」？此操作不可恢复。`),
        h('p', { class: 'mt-1.5 text-ink-3' }, '将自动清理关联的免 MFA 规则，并从登录页移除'),
      ]),
    positiveText: '确认删除',
    negativeText: '取消',
    onPositiveClick: () =>
      act(() => deleteIdp(props.cfgId, row.id, props.domainId), `已删除 IdP「${row.name}」及其关联规则`),
  })
}

function addExemption() {
  const enabled = idps.data.value?.find((i) => i.enabled)
  if (!enabled) {
    message.warning('没有已启用的 IdP')
    return
  }
  void act(
    () => createSignOnExemption(props.cfgId, enabled.id, props.domainId),
    `已为 ${enabled.name} 创建免 MFA 规则并置顶`,
  )
}
</script>

<template>
  <div class="flex flex-col gap-4">
    <div class="panel">
      <div class="flex items-center justify-between border-b border-line-soft px-4.5 py-3.5">
        <div class="text-sm font-semibold">SAML 身份提供商</div>
        <div class="flex items-center gap-2">
          <NButton size="small" @click="doDownloadMetadata">下载 SP 元数据</NButton>
          <NButton size="small" type="primary" @click="showCreate = true">创建 IdP</NButton>
        </div>
      </div>
      <NDataTable
        :columns="idpColumns"
        :data="idps.data.value ?? []"
        :loading="idps.loading.value"
        :scroll-x="620"
        :row-key="(r: IdentityProvider) => r.id"
      />
      <FootNote>
        推荐流程：下载 SP SAML 元数据导入 IdP 侧 → 创建 IdP → 激活（自动显示到登录页）→ 创建免 MFA
        规则；停用与删除会先将 IdP 移出登录页
      </FootNote>
    </div>

    <div class="panel">
      <div class="flex items-center justify-between border-b border-line-soft px-4.5 py-3.5">
        <div class="text-sm font-semibold">Sign-on 策略（免 MFA 规则）</div>
        <NButton size="small" @click="addExemption">为已启用 IdP 创建免 MFA 规则</NButton>
      </div>
      <NDataTable
        :columns="ruleColumns"
        :data="rules.data.value ?? []"
        :loading="rules.loading.value"
        :scroll-x="560"
        :row-key="(r: SignOnRule) => r.id"
      />
      <FootNote>
        sign-on 策略管控全租户控制台登录；Oracle 预置规则不可删除，请勿手工改动预置规则顺序
      </FootNote>
    </div>

    <IdpFormModal v-model:show="showCreate" :cfg-id="cfgId" :domain-id="domainId" @created="idps.run()" />
  </div>
</template>
