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

import {
  createUser,
  getIdentitySetting,
  getUserDetail,
  updateUser,
  type UpdateUserBody,
} from '@/api/tenant'
import FormField from '@/components/FormField.vue'
import FormModal from '@/components/FormModal.vue'
import type { IamUser, IamUserDetail } from '@/types/api'
import { useToast } from '@/composables/useToast'

// user 非空即编辑模式：打开时拉取域档案预填充，提交只发送与原值不同的字段
const props = defineProps<{ show: boolean; cfgId: number; domainId?: string; user?: IamUser | null }>()
const emit = defineEmits<{ 'update:show': [boolean]; created: [] }>()

const message = useToast()
const submitting = ref(false)
// 域开启「用户需要提供主电子邮件地址」时邮箱必填
const emailRequired = ref(false)
// 编辑模式的域档案；加载失败保持 null，降级为「留空不修改、勾选仅添加」
const detail = ref<IamUserDetail | null>(null)
const detailLoading = ref(false)

const blank = {
  name: '',
  givenName: '',
  familyName: '',
  email: '',
  description: '',
  grantDomainAdmin: false,
  addToAdminGroup: false,
}
const form = reactive({ ...blank })
const editing = computed(() => !!props.user)
// 经典 IAM 用户不在身份域中，姓名与管理员状态均不可操作
const classicUser = computed(() => editing.value && !!detail.value && !detail.value.inDomain)

watch(
  () => props.show,
  (v) => {
    if (!v) return
    Object.assign(form, blank)
    detail.value = null
    if (props.user) {
      form.name = props.user.name
      form.email = props.user.email
      form.description = props.user.description
      void loadDetail(props.user.id)
    }
    void loadIdentitySetting()
  },
)

async function loadIdentitySetting() {
  try {
    emailRequired.value = (await getIdentitySetting(props.cfgId, props.domainId)).primaryEmailRequired
  } catch {
    emailRequired.value = false
  }
}

// 拉取域档案并回填表单；返回时弹窗已切到别的用户则丢弃结果
async function loadDetail(userId: string) {
  detailLoading.value = true
  try {
    const d = await getUserDetail(props.cfgId, userId, props.domainId)
    if (props.user?.id !== userId) return
    detail.value = d
    if (!d.inDomain) return
    form.givenName = d.givenName
    form.familyName = d.familyName
    form.grantDomainAdmin = d.isDomainAdmin
    form.addToAdminGroup = d.inAdminGroup
  } catch {
    if (props.user?.id === userId)
      message.warning('用户详情加载失败：姓名留空表示不修改，管理员选项仅执行添加')
  } finally {
    if (props.user?.id === userId) detailLoading.value = false
  }
}

const nameRequired = computed(() => !editing.value || !!detail.value?.inDomain)

const nameHint = computed(() => {
  if (!editing.value || detailLoading.value) return undefined
  if (classicUser.value) return '经典 IAM 用户不支持修改姓名'
  if (!detail.value) return '详情加载失败：留空表示不修改，仅身份域用户可改姓名'
  return undefined
})

const adminHint = computed(() => {
  if (!editing.value)
    return form.grantDomainAdmin && form.addToAdminGroup
      ? '同时勾选时先授予身份域管理员，再加入管理员组'
      : undefined
  if (detailLoading.value) return '正在加载当前管理员状态…'
  if (classicUser.value) return '经典 IAM 用户不在身份域中，无法调整管理员角色与组'
  if (!detail.value) return '详情加载失败：仅执行添加操作，不会撤销已有的管理员角色或组成员'
  return '已按当前状态勾选；取消勾选保存后将撤销对应的管理员角色 / 组成员'
})

const canSubmit = computed(() => {
  const emailOk = !emailRequired.value || !!form.email.trim()
  if (!editing.value)
    return !!form.name.trim() && !!form.givenName.trim() && !!form.familyName.trim() && emailOk
  if (detailLoading.value) return false
  if (detail.value?.inDomain && (!form.givenName.trim() || !form.familyName.trim())) return false
  return emailOk
})

// 编辑只提交与原值不同的字段；域档案在手时管理员勾选与当前状态比对，取消勾选即撤销
function buildUpdateBody(u: IamUser): UpdateUserBody {
  const body: UpdateUserBody = {}
  if (form.email.trim() !== u.email) body.email = form.email.trim()
  if (form.description.trim() !== u.description) body.description = form.description.trim()
  if (classicUser.value) return body
  const d = detail.value
  if (d?.inDomain) {
    if (form.givenName.trim() !== d.givenName) body.givenName = form.givenName.trim()
    if (form.familyName.trim() !== d.familyName) body.familyName = form.familyName.trim()
    if (form.grantDomainAdmin !== d.isDomainAdmin) body.grantDomainAdmin = form.grantDomainAdmin
    if (form.addToAdminGroup !== d.inAdminGroup) body.addToAdminGroup = form.addToAdminGroup
    return body
  }
  if (form.givenName.trim()) body.givenName = form.givenName.trim()
  if (form.familyName.trim()) body.familyName = form.familyName.trim()
  if (form.grantDomainAdmin) body.grantDomainAdmin = true
  if (form.addToAdminGroup) body.addToAdminGroup = true
  return body
}

async function submitEdit(u: IamUser) {
  const body = buildUpdateBody(u)
  if (!Object.keys(body).length) {
    emit('update:show', false)
    return
  }
  await updateUser(props.cfgId, u.id, body, props.domainId)
  message.success(`用户「${u.name}」已更新`)
}

async function submitCreate() {
  const created = await createUser(
    props.cfgId,
    {
      name: form.name.trim(),
      givenName: form.givenName.trim(),
      familyName: form.familyName.trim(),
      email: form.email.trim() || undefined,
      description: form.description.trim() || undefined,
      grantDomainAdmin: form.grantDomainAdmin,
      addToAdminGroup: form.addToAdminGroup,
    },
    props.domainId,
  )
  message.success(`用户「${created.name}」已创建，可再执行「重置密码」下发初始密码`)
}

async function submit() {
  if (!canSubmit.value) return
  submitting.value = true
  try {
    if (props.user) await submitEdit(props.user)
    else await submitCreate()
    emit('update:show', false)
    emit('created')
  } catch (e) {
    message.error(e instanceof Error ? e.message : editing.value ? '更新失败' : '创建失败')
  } finally {
    submitting.value = false
  }
}
</script>

<template>
  <FormModal
    :show="show"
    :title="editing ? `修改用户 · ${user?.name ?? ''}` : '添加用户'"
    :submitting="submitting"
    :submit-disabled="!canSubmit"
    :submit-text="editing ? '保存' : '创建'"
    @update:show="emit('update:show', $event)"
    @submit="submit"
  >
    <FormField v-if="!editing" label="用户名" required>
      <NInput v-model:value="form.name" placeholder="new-user" @keyup.enter="submit" />
    </FormField>
    <div class="grid grid-cols-2 gap-3 max-md:grid-cols-1">
      <FormField label="名字" :required="nameRequired" :hint="nameHint">
        <NInput
          v-model:value="form.givenName"
          placeholder="First name"
          :disabled="classicUser"
          :loading="detailLoading"
        />
      </FormField>
      <FormField label="姓氏" :required="nameRequired">
        <NInput
          v-model:value="form.familyName"
          placeholder="Last name"
          :disabled="classicUser"
          :loading="detailLoading"
        />
      </FormField>
    </div>
    <FormField
      label="邮箱"
      :required="emailRequired"
      :hint="
        emailRequired
          ? '域已开启「用户需要提供主电子邮件地址」，必须填写'
          : '用于接收欢迎邮件与找回密码'
      "
    >
      <NInput v-model:value="form.email" placeholder="user@example.com" />
    </FormField>
    <FormField label="备注" :hint="editing ? undefined : '留空默认取「名字 姓氏」'">
      <NInput v-model:value="form.description" placeholder="可选" />
    </FormField>
    <div class="mb-2 flex flex-col gap-1.5">
      <NCheckbox
        v-model:checked="form.grantDomainAdmin"
        :disabled="classicUser || detailLoading"
      >
        {{ editing ? '身份域管理员' : '添加到身份域管理员' }}
      </NCheckbox>
      <NCheckbox v-model:checked="form.addToAdminGroup" :disabled="classicUser || detailLoading">
        {{ editing ? '租户管理员组成员' : '添加到租户管理员组' }}
      </NCheckbox>
      <div v-if="adminHint" class="text-xs text-ink-3">{{ adminHint }}</div>
    </div>
  </FormModal>
</template>
