<template>
  <div class="page-content">
    <div class="mb-5 flex items-center justify-between gap-4">
      <div>
        <h2 class="text-xl font-semibold">账号与权限</h2>
        <p class="text-g-500 mt-1 text-sm">管理员和门户账号统一管理，权限变更即时生效</p>
      </div>
      <ElButton type="primary" @click="openCreate">
        {{ activeTab === 'department' ? '新增部门' : activeTab === 'oidc' || activeTab === 'saml' ? '新增身份源' : '新增账号' }}
      </ElButton>
    </div>

    <ElAlert
      class="mb-4"
      type="info"
      :closable="false"
      title="内置角色提供默认权限；直接权限使用 resource:action 格式并与角色权限合并。"
    />

    <ElTabs v-model="activeTab" @tab-change="load">
      <ElTabPane label="管理员" name="admin" />
      <ElTabPane label="门户用户" name="portal" />
      <ElTabPane label="部门" name="department" />
      <ElTabPane label="OIDC 身份源" name="oidc" />
      <ElTabPane label="SAML 身份源" name="saml" />
    </ElTabs>

    <ElTable v-if="activeTab === 'admin' || activeTab === 'portal'" v-loading="loading" :data="records" row-key="id">
      <ElTableColumn prop="login" label="账号" min-width="170" />
      <ElTableColumn prop="display_name" label="显示名称" min-width="150">
        <template #default="{ row }">{{ row.display_name || '-' }}</template>
      </ElTableColumn>
      <ElTableColumn prop="role" label="角色" width="130" />
      <ElTableColumn v-if="activeTab === 'portal'" prop="department_name" label="部门" min-width="150">
        <template #default="{ row }">{{ row.department_name || '未分配' }}</template>
      </ElTableColumn>
      <ElTableColumn label="有效权限" min-width="280">
        <template #default="{ row }">
          <div class="flex flex-wrap gap-1">
            <ElTag v-for="permission in row.effective_permissions" :key="permission" size="small">
              {{ permission }}
            </ElTag>
            <span v-if="row.effective_permissions.length === 0">-</span>
          </div>
        </template>
      </ElTableColumn>
      <ElTableColumn label="TOTP" width="90">
        <template #default="{ row }">
          <ElTag :type="row.totp_enabled ? 'success' : 'info'">
            {{ row.totp_enabled ? '已启用' : '未启用' }}
          </ElTag>
        </template>
      </ElTableColumn>
      <ElTableColumn label="状态" width="90">
        <template #default="{ row }">
          <ElTag :type="row.active ? 'success' : 'danger'">
            {{ row.active ? '启用' : '停用' }}
          </ElTag>
        </template>
      </ElTableColumn>
      <ElTableColumn label="操作" width="90" fixed="right">
        <template #default="{ row }">
          <ElButton link type="primary" @click="openEdit(row)">编辑</ElButton>
        </template>
      </ElTableColumn>
    </ElTable>

    <ElTable v-else-if="activeTab === 'department'" v-loading="loading" :data="departments" row-key="id">
      <ElTableColumn prop="code" label="代码" min-width="150" />
      <ElTableColumn prop="name" label="名称" min-width="170" />
      <ElTableColumn prop="parent_name" label="上级部门" min-width="160">
        <template #default="{ row }">{{ row.parent_name || '根部门' }}</template>
      </ElTableColumn>
      <ElTableColumn prop="description" label="描述" min-width="220" show-overflow-tooltip />
      <ElTableColumn prop="user_count" label="启用用户" width="100" />
      <ElTableColumn label="状态" width="90">
        <template #default="{ row }">
          <ElTag :type="row.active ? 'success' : 'info'">{{ row.active ? '启用' : '停用' }}</ElTag>
        </template>
      </ElTableColumn>
      <ElTableColumn label="操作" width="90" fixed="right">
        <template #default="{ row }">
          <ElButton link type="primary" @click="openDepartmentEdit(row)">编辑</ElButton>
        </template>
      </ElTableColumn>
    </ElTable>

    <ElTable v-else-if="activeTab === 'oidc'" v-loading="loading" :data="identityProviders" row-key="id">
      <ElTableColumn prop="code" label="代码" min-width="130" />
      <ElTableColumn prop="display_name" label="名称" min-width="150" />
      <ElTableColumn prop="issuer_url" label="Issuer" min-width="260" show-overflow-tooltip />
      <ElTableColumn prop="client_id" label="Client ID" min-width="170" show-overflow-tooltip />
      <ElTableColumn label="自动开户" width="100">
        <template #default="{ row }">{{ row.auto_provision ? '启用' : '关闭' }}</template>
      </ElTableColumn>
      <ElTableColumn label="状态" width="90">
        <template #default="{ row }"><ElTag :type="row.enabled ? 'success' : 'info'">{{ row.enabled ? '启用' : '停用' }}</ElTag></template>
      </ElTableColumn>
      <ElTableColumn label="操作" width="90" fixed="right">
        <template #default="{ row }"><ElButton link type="primary" @click="openIdentityProviderEdit(row)">编辑</ElButton></template>
      </ElTableColumn>
    </ElTable>

    <ElTable v-else v-loading="loading" :data="samlProviders" row-key="id">
      <ElTableColumn prop="code" label="代码" min-width="130" />
      <ElTableColumn prop="display_name" label="名称" min-width="150" />
      <ElTableColumn prop="metadata_url" label="IdP Metadata" min-width="280" show-overflow-tooltip />
      <ElTableColumn prop="sp_entity_id" label="SP Entity ID" min-width="220" show-overflow-tooltip />
      <ElTableColumn label="自动开户" width="100">
        <template #default="{ row }">{{ row.auto_provision ? '启用' : '关闭' }}</template>
      </ElTableColumn>
      <ElTableColumn label="状态" width="90">
        <template #default="{ row }"><ElTag :type="row.enabled ? 'success' : 'info'">{{ row.enabled ? '启用' : '停用' }}</ElTag></template>
      </ElTableColumn>
      <ElTableColumn label="操作" width="90" fixed="right">
        <template #default="{ row }"><ElButton link type="primary" @click="openSAMLProviderEdit(row)">编辑</ElButton></template>
      </ElTableColumn>
    </ElTable>

    <ElDialog v-model="dialogVisible" :title="editingId ? '编辑账号' : '新增账号'" width="640px">
      <ElForm ref="formRef" :model="form" :rules="rules" label-width="100px">
        <ElFormItem label="账号" prop="login">
          <ElInput v-model="form.login" placeholder="登录账号" />
        </ElFormItem>
        <ElFormItem label="显示名称">
          <ElInput v-model="form.display_name" maxlength="64" />
        </ElFormItem>
        <ElFormItem label="角色" prop="role">
          <ElSelect v-model="form.role" class="w-full">
            <ElOption
              v-for="role in roleOptions"
              :key="role.value"
              :label="role.label"
              :value="role.value"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem :label="editingId ? '新口令' : '初始口令'" prop="password">
          <ElInput
            v-model="form.password"
            type="password"
            show-password
            :placeholder="editingId ? '留空表示不修改' : '至少 12 个字符'"
          />
        </ElFormItem>
        <ElFormItem label="直接权限">
          <ElSelect
            v-model="form.permissions"
            multiple
            filterable
            allow-create
            default-first-option
            class="w-full"
            placeholder="选择或输入 resource:action"
          >
            <ElOption v-for="item in permissionOptions" :key="item" :label="item" :value="item" />
          </ElSelect>
        </ElFormItem>
        <ElFormItem v-if="activeTab === 'portal'" label="所属部门">
          <ElSelect v-model="form.department_id" clearable class="w-full" placeholder="可不分配">
            <ElOption
              v-for="department in activeDepartments"
              :key="department.id"
              :label="department.name"
              :value="department.id"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="启用">
          <ElSwitch v-model="form.active" />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <ElButton @click="dialogVisible = false">取消</ElButton>
        <ElButton type="primary" :loading="saving" @click="submit">保存</ElButton>
      </template>
    </ElDialog>

    <ElDialog v-model="departmentDialogVisible" :title="departmentEditingId ? '编辑部门' : '新增部门'" width="600px">
      <ElForm ref="departmentFormRef" :model="departmentForm" label-width="100px">
        <ElFormItem label="代码" required>
          <ElInput v-model="departmentForm.code" placeholder="例如 platform" />
        </ElFormItem>
        <ElFormItem label="名称" required>
          <ElInput v-model="departmentForm.name" maxlength="128" />
        </ElFormItem>
        <ElFormItem label="上级部门">
          <ElSelect v-model="departmentForm.parent_id" clearable class="w-full">
            <ElOption
              v-for="department in availableParents"
              :key="department.id"
              :label="department.name"
              :value="department.id"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="描述">
          <ElInput v-model="departmentForm.description" type="textarea" maxlength="1024" show-word-limit />
        </ElFormItem>
        <ElFormItem label="启用">
          <ElSwitch v-model="departmentForm.active" />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <ElButton @click="departmentDialogVisible = false">取消</ElButton>
        <ElButton type="primary" :loading="saving" @click="submitDepartment">保存</ElButton>
      </template>
    </ElDialog>

    <ElDialog v-model="idpDialogVisible" :title="idpEditingId ? '编辑 OIDC 身份源' : '新增 OIDC 身份源'" width="720px">
      <ElForm :model="idpForm" label-width="130px">
        <ElFormItem label="代码" required><ElInput v-model="idpForm.code" placeholder="例如 corp_oidc" /></ElFormItem>
        <ElFormItem label="显示名称" required><ElInput v-model="idpForm.display_name" /></ElFormItem>
        <ElFormItem label="Issuer URL" required><ElInput v-model="idpForm.issuer_url" placeholder="https://id.example.com" /></ElFormItem>
        <ElFormItem label="Client ID" required><ElInput v-model="idpForm.client_id" /></ElFormItem>
        <ElFormItem label="Client Secret" :required="!idpEditingId">
          <ElInput v-model="idpForm.client_secret" type="password" show-password :placeholder="idpEditingId ? '留空表示不更换' : ''" />
        </ElFormItem>
        <ElFormItem label="网关回调 URL" required><ElInput v-model="idpForm.redirect_uri" /></ElFormItem>
        <ElFormItem label="门户返回 URL" required><ElInput v-model="idpForm.portal_return_url" /></ElFormItem>
        <ElFormItem label="Scopes"><ElSelect v-model="idpForm.scopes" multiple allow-create filterable class="w-full" /></ElFormItem>
        <ElFormItem label="默认部门">
          <ElSelect v-model="idpForm.default_department_id" clearable class="w-full">
            <ElOption v-for="department in activeDepartments" :key="department.id" :label="department.name" :value="department.id" />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="自动开户"><ElSwitch v-model="idpForm.auto_provision" /></ElFormItem>
        <ElFormItem label="启用"><ElSwitch v-model="idpForm.enabled" /></ElFormItem>
      </ElForm>
      <template #footer>
        <ElButton @click="idpDialogVisible = false">取消</ElButton>
        <ElButton type="primary" :loading="saving" @click="submitIdentityProvider">保存</ElButton>
      </template>
    </ElDialog>

    <ElDialog v-model="samlDialogVisible" :title="samlEditingId ? '编辑 SAML 身份源' : '新增 SAML 身份源'" width="760px">
      <ElAlert class="mb-4" type="info" :closable="false" title="启用时服务端会拉取 IdP metadata，并验证 Redirect SSO 端点和当前有效的签名证书。" />
      <ElForm :model="samlForm" label-width="150px">
        <ElFormItem label="代码" required><ElInput v-model="samlForm.code" placeholder="例如 corp_saml" /></ElFormItem>
        <ElFormItem label="显示名称" required><ElInput v-model="samlForm.display_name" /></ElFormItem>
        <ElFormItem label="IdP Metadata URL" required><ElInput v-model="samlForm.metadata_url" placeholder="https://idp.example.com/metadata" /></ElFormItem>
        <ElFormItem label="SP Entity ID" required><ElInput v-model="samlForm.sp_entity_id" placeholder="urn:example:ai-gateway" /></ElFormItem>
        <ElFormItem label="ACS URL" required><ElInput v-model="samlForm.acs_url" placeholder="https://gateway.example.com/api/v1/portal/sso/corp_saml/callback" /></ElFormItem>
        <ElFormItem label="门户返回 URL" required><ElInput v-model="samlForm.portal_return_url" /></ElFormItem>
        <ElFormItem label="邮箱属性"><ElInput v-model="samlForm.email_attribute" placeholder="mail 或属性 URI" /></ElFormItem>
        <ElFormItem label="姓名属性"><ElInput v-model="samlForm.name_attribute" placeholder="cn 或属性 URI" /></ElFormItem>
        <ElFormItem label="默认部门">
          <ElSelect v-model="samlForm.default_department_id" clearable class="w-full">
            <ElOption v-for="department in activeDepartments" :key="department.id" :label="department.name" :value="department.id" />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="自动开户"><ElSwitch v-model="samlForm.auto_provision" /></ElFormItem>
        <ElFormItem label="启用"><ElSwitch v-model="samlForm.enabled" /></ElFormItem>
      </ElForm>
      <template #footer>
        <ElButton @click="samlDialogVisible = false">取消</ElButton>
        <ElButton type="primary" :loading="saving" @click="submitSAMLProvider">保存</ElButton>
      </template>
    </ElDialog>
  </div>
</template>

<script setup lang="ts">
  import { ElMessage, FormInstance, FormRules, TabsPaneContext } from 'element-plus'
  import {
    createDepartment,
    createIdentityProvider,
    createSAMLProvider,
    createIdentity,
    DepartmentInput,
    DepartmentRecord,
    fetchDepartments,
    fetchIdentityProviders,
    fetchSAMLProviders,
    fetchIdentities,
    IdentityInput,
    IdentityKind,
    IdentityRecord,
    IdentityProviderInput,
    IdentityProviderRecord,
    SAMLProviderInput,
    SAMLProviderRecord,
    updateDepartment,
    updateIdentityProvider,
    updateSAMLProvider,
    updateIdentity
  } from '@/api/identities'

  defineOptions({ name: 'User' })

  const permissionOptions = [
    'identity:manage',
    'provider:read',
    'provider:manage',
    'api_key:read',
    'api_key:manage'
  ]
  type ManagementTab = IdentityKind | 'department' | 'oidc' | 'saml'
  const activeTab = ref<ManagementTab>('admin')
  const records = ref<IdentityRecord[]>([])
  const loading = ref(false)
  const saving = ref(false)
  const dialogVisible = ref(false)
  const editingId = ref('')
  const departments = ref<DepartmentRecord[]>([])
  const identityProviders = ref<IdentityProviderRecord[]>([])
  const samlProviders = ref<SAMLProviderRecord[]>([])
  const departmentDialogVisible = ref(false)
  const departmentEditingId = ref('')
  const idpDialogVisible = ref(false)
  const idpEditingId = ref('')
  const samlDialogVisible = ref(false)
  const samlEditingId = ref('')
  const formRef = ref<FormInstance>()
  const departmentFormRef = ref<FormInstance>()
  const form = reactive<IdentityInput>({
    login: '',
    display_name: '',
    role: 'operator',
    password: '',
    permissions: [],
    active: true,
    department_id: undefined
  })
  const departmentForm = reactive<DepartmentInput>({
    code: '', name: '', description: '', parent_id: undefined, active: true
  })
  const idpForm = reactive<IdentityProviderInput>({
    code: '', display_name: '', issuer_url: '', client_id: '', client_secret: '',
    redirect_uri: '', portal_return_url: '', scopes: ['openid', 'profile', 'email'],
    auto_provision: false, default_department_id: undefined, enabled: false
  })
  const samlForm = reactive<SAMLProviderInput>({
    code: '', display_name: '', metadata_url: '', sp_entity_id: '', acs_url: '',
    portal_return_url: '', email_attribute: 'mail', name_attribute: 'cn',
    auto_provision: false, default_department_id: undefined, enabled: false
  })
  const activeDepartments = computed(() => departments.value.filter((item) => item.active))
  const availableParents = computed(() =>
    activeDepartments.value.filter((item) => item.id !== departmentEditingId.value)
  )
  const roleOptions = computed(() =>
    activeTab.value === 'admin'
      ? [
          { label: '超级管理员', value: 'superadmin' },
          { label: '运维管理员', value: 'operator' },
          { label: '审计员', value: 'auditor' }
        ]
      : [{ label: '普通成员', value: 'member' }]
  )
  const rules: FormRules = {
    login: [
      { required: true, message: '请输入账号', trigger: 'blur' },
      { min: 2, max: 128, message: '长度必须为 2 至 128 个字符', trigger: 'blur' }
    ],
    role: [{ required: true, message: '请选择角色', trigger: 'change' }]
  }

  async function load(_pane?: TabsPaneContext | string | number) {
    loading.value = true
    try {
      departments.value = await fetchDepartments()
      if (activeTab.value === 'admin' || activeTab.value === 'portal') records.value = await fetchIdentities(activeTab.value)
      if (activeTab.value === 'oidc') identityProviders.value = await fetchIdentityProviders()
      if (activeTab.value === 'saml') samlProviders.value = await fetchSAMLProviders()
    } finally {
      loading.value = false
    }
  }

  function resetForm() {
    Object.assign(form, {
      login: '',
      display_name: '',
      role: activeTab.value === 'admin' ? 'operator' : 'member',
      password: '',
      permissions: [],
      active: true,
      department_id: undefined
    })
  }

  function openCreate() {
    if (activeTab.value === 'department') {
      departmentEditingId.value = ''
      Object.assign(departmentForm, { code: '', name: '', description: '', parent_id: undefined, active: true })
      departmentDialogVisible.value = true
      return
    }
    if (activeTab.value === 'oidc') {
      idpEditingId.value = ''
      Object.assign(idpForm, { code: '', display_name: '', issuer_url: '', client_id: '', client_secret: '', redirect_uri: '', portal_return_url: '', scopes: ['openid', 'profile', 'email'], auto_provision: false, default_department_id: undefined, enabled: false })
      idpDialogVisible.value = true
      return
    }
    if (activeTab.value === 'saml') {
      samlEditingId.value = ''
      Object.assign(samlForm, { code: '', display_name: '', metadata_url: '', sp_entity_id: '', acs_url: '', portal_return_url: '', email_attribute: 'mail', name_attribute: 'cn', auto_provision: false, default_department_id: undefined, enabled: false })
      samlDialogVisible.value = true
      return
    }
    editingId.value = ''
    resetForm()
    dialogVisible.value = true
  }

  function openEdit(record: IdentityRecord) {
    editingId.value = record.id
    Object.assign(form, {
      login: record.login,
      display_name: record.display_name,
      role: record.role,
      password: '',
      permissions: [...record.permissions],
      active: record.active,
      department_id: record.department_id
    })
    dialogVisible.value = true
  }

  function openDepartmentEdit(record: DepartmentRecord) {
    departmentEditingId.value = record.id
    Object.assign(departmentForm, {
      code: record.code, name: record.name, description: record.description,
      parent_id: record.parent_id, active: record.active
    })
    departmentDialogVisible.value = true
  }

  async function submitDepartment() {
    if (!departmentForm.code || !departmentForm.name) {
      ElMessage.warning('部门代码和名称不能为空')
      return
    }
    saving.value = true
    try {
      const payload: DepartmentInput = { ...departmentForm }
      if (!payload.parent_id) delete payload.parent_id
      if (departmentEditingId.value) await updateDepartment(departmentEditingId.value, payload)
      else await createDepartment(payload)
      ElMessage.success('部门保存成功')
      departmentDialogVisible.value = false
      await load()
    } finally {
      saving.value = false
    }
  }

  function openIdentityProviderEdit(record: IdentityProviderRecord) {
    idpEditingId.value = record.id
    Object.assign(idpForm, { code: record.code, display_name: record.display_name, issuer_url: record.issuer_url, client_id: record.client_id, client_secret: '', redirect_uri: record.redirect_uri, portal_return_url: record.portal_return_url, scopes: [...record.scopes], auto_provision: record.auto_provision, default_department_id: record.default_department_id, enabled: record.enabled })
    idpDialogVisible.value = true
  }

  async function submitIdentityProvider() {
    if (!idpForm.code || !idpForm.display_name || !idpForm.issuer_url || !idpForm.client_id || !idpForm.redirect_uri || !idpForm.portal_return_url || (!idpEditingId.value && !idpForm.client_secret)) {
      ElMessage.warning('请填写所有必填 OIDC 配置')
      return
    }
    saving.value = true
    try {
      const payload: IdentityProviderInput = { ...idpForm, scopes: [...idpForm.scopes] }
      if (!payload.client_secret) delete payload.client_secret
      if (!payload.default_department_id) delete payload.default_department_id
      if (idpEditingId.value) await updateIdentityProvider(idpEditingId.value, payload)
      else await createIdentityProvider(payload)
      ElMessage.success('OIDC 身份源保存成功')
      idpDialogVisible.value = false
      await load()
    } finally { saving.value = false }
  }

  function openSAMLProviderEdit(record: SAMLProviderRecord) {
    samlEditingId.value = record.id
    Object.assign(samlForm, {
      code: record.code, display_name: record.display_name, metadata_url: record.metadata_url,
      sp_entity_id: record.sp_entity_id, acs_url: record.acs_url,
      portal_return_url: record.portal_return_url, email_attribute: record.email_attribute,
      name_attribute: record.name_attribute, auto_provision: record.auto_provision,
      default_department_id: record.default_department_id, enabled: record.enabled
    })
    samlDialogVisible.value = true
  }

  async function submitSAMLProvider() {
    if (!samlForm.code || !samlForm.display_name || !samlForm.metadata_url || !samlForm.sp_entity_id || !samlForm.acs_url || !samlForm.portal_return_url) {
      ElMessage.warning('请填写所有必填 SAML 配置')
      return
    }
    saving.value = true
    try {
      const payload: SAMLProviderInput = { ...samlForm }
      if (!payload.default_department_id) delete payload.default_department_id
      if (samlEditingId.value) await updateSAMLProvider(samlEditingId.value, payload)
      else await createSAMLProvider(payload)
      ElMessage.success('SAML 身份源保存成功')
      samlDialogVisible.value = false
      await load()
    } finally { saving.value = false }
  }

  async function submit() {
    if (!(await formRef.value?.validate())) return
    if (!editingId.value && (!form.password || form.password.length < 12)) {
      ElMessage.warning('初始口令至少需要 12 个字符')
      return
    }
    if (form.password && form.password.length < 12) {
      ElMessage.warning('新口令至少需要 12 个字符')
      return
    }
    saving.value = true
    try {
      const payload: IdentityInput = { ...form, permissions: [...form.permissions] }
      if (editingId.value && !payload.password) delete payload.password
      if (!payload.department_id) delete payload.department_id
      const kind = activeTab.value as IdentityKind
      if (editingId.value) await updateIdentity(kind, editingId.value, payload)
      else await createIdentity(kind, payload)
      ElMessage.success('保存成功，权限状态已即时生效')
      dialogVisible.value = false
      await load()
    } finally {
      saving.value = false
    }
  }

  onMounted(load)
</script>
