<script setup lang="ts">
import { computed, nextTick, onMounted, shallowRef, useTemplateRef, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Check, Refresh } from '@element-plus/icons-vue'
import { fetchPermissions, syncRolePermissions } from '@/api/admin'
import type { Permission } from '@/types/api'

interface PermissionNode extends Permission {
  label: string
  children?: PermissionNode[]
}

const loading = shallowRef(false)
const saving = shallowRef(false)
const role = shallowRef<'teacher' | 'user'>('teacher')
const permissions = shallowRef<Permission[]>([])
const rolePermissions = shallowRef<Record<string, number[]>>({})
const treeRef = useTemplateRef('treeRef')

const roleOptions = [
  { label: '老师', value: 'teacher' },
  { label: '普通用户', value: 'user' },
]

const treeProps = {
  children: 'children',
  label: 'label',
}

const permissionTree = computed<PermissionNode[]>(() => {
  const menus = permissions.value
    .filter((item) => item.type === 'menu')
    .map((item) => ({
      ...item,
      label: item.name,
      children: permissions.value
        .filter((child) => child.parent_code === item.code)
        .map((child) => ({ ...child, label: child.name })),
    }))

  const orphanButtons = permissions.value
    .filter((item) => item.type === 'button' && !item.parent_code)
    .map((item) => ({ ...item, label: item.name }))

  return [...menus, ...orphanButtons]
})

const selectedCount = computed(() => rolePermissions.value[role.value]?.length ?? 0)

async function loadPermissions() {
  loading.value = true
  try {
    const response = await fetchPermissions()
    permissions.value = response.data.permissions
    rolePermissions.value = response.data.role_permissions
    await applyCheckedKeys()
  } finally {
    loading.value = false
  }
}

async function applyCheckedKeys() {
  await nextTick()
  treeRef.value?.setCheckedKeys(rolePermissions.value[role.value] ?? [], false)
}

async function saveRolePermissions() {
  const checkedKeys = treeRef.value?.getCheckedKeys(false) ?? []
  const halfCheckedKeys = treeRef.value?.getHalfCheckedKeys() ?? []
  const permissionIds = [...checkedKeys, ...halfCheckedKeys].map((id) => Number(id))
  saving.value = true
  try {
    await syncRolePermissions(role.value, permissionIds)
    rolePermissions.value = {
      ...rolePermissions.value,
      [role.value]: permissionIds,
    }
    ElMessage.success('角色权限已保存')
  } finally {
    saving.value = false
  }
}

watch(role, applyCheckedKeys)

onMounted(loadPermissions)
</script>

<template>
  <section class="panel p-5">
    <div class="toolbar mb-4">
      <div class="flex-1">
        <h1 class="page-title">角色权限</h1>
        <p class="muted text-sm mt-1">配置老师和普通用户可访问的菜单与操作权限。</p>
      </div>
      <ElButton :icon="Refresh" @click="loadPermissions">刷新</ElButton>
      <ElButton :icon="Check" type="primary" :loading="saving" @click="saveRolePermissions">保存权限</ElButton>
    </div>

    <div class="permission-layout">
      <aside class="role-panel">
        <ElSegmented v-model="role" :options="roleOptions" block />
        <div class="role-summary">
          <strong>{{ selectedCount }}</strong>
          <span>已选权限</span>
        </div>
      </aside>

      <section v-loading="loading" class="tree-panel">
        <ElTree
          ref="treeRef"
          :data="permissionTree"
          :props="treeProps"
          node-key="id"
          show-checkbox
          default-expand-all
          check-on-click-node
        >
          <template #default="{ data }">
            <div class="permission-node">
              <span>{{ data.name }}</span>
              <ElTag v-if="data.type === 'menu'" size="small" effect="plain">菜单</ElTag>
              <ElTag v-else size="small" type="info" effect="plain">操作</ElTag>
              <code>{{ data.code }}</code>
            </div>
          </template>
        </ElTree>
      </section>
    </div>
  </section>
</template>

<style scoped>
.permission-layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 16px;
}

.role-panel,
.tree-panel {
  border: 1px solid var(--qq-line);
  border-radius: 8px;
  background: #fff;
}

.role-panel {
  padding: 14px;
}

.role-summary {
  margin-top: 14px;
  padding: 14px;
  border-radius: 8px;
  background: rgba(31, 111, 91, 0.08);
  text-align: center;
}

.role-summary strong {
  display: block;
  font-size: 28px;
  color: var(--qq-ink);
}

.role-summary span {
  color: var(--qq-muted);
  font-size: 13px;
}

.tree-panel {
  min-height: 420px;
  padding: 14px;
}

.permission-node {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.permission-node code {
  color: var(--qq-muted);
  font-size: 12px;
}

@media (max-width: 760px) {
  .permission-layout {
    grid-template-columns: 1fr;
  }
}
</style>
