<template>
  <el-card>
    <template #header>
      <div class='flex justify-between items-center'>
        <span class='font-700'>角色管理</span>
        <el-button v-if='hasPermission("platform.roles.manage")' type='primary' @click='openCreate'>新增角色</el-button>
      </div>
    </template>

    <el-table :data='rows' v-loading='loading'>
      <el-table-column prop='id' label='ID' width='80' sortable />
      <el-table-column prop='name' label='角色名' min-width='160' sortable />
      <el-table-column label='权限' min-width='420' sortable :sort-method='sortByPermissions'>
        <template #default='{ row }'>
          <div class='perm-wrap'>
            <el-tag v-for='item in row.permissions || []' :key='item.id' size='small' class='perm-tag'>{{ item.name }}</el-tag>
          </div>
        </template>
      </el-table-column>
      <el-table-column v-if='hasPermission("platform.roles.manage")' label='操作' width='180'>
        <template #default='{ row }'>
          <div class='btn-gap-8 btn-gap-8--nowrap'>
            <el-button size='small' @click='openEdit(row)'>编辑</el-button>
            <el-button size='small' type='danger' @click='removeRow(row)'>删除</el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      class='mt-4'
      layout='total, sizes, prev, pager, next'
      :total='total'
      :current-page='page'
      :page-size='perPage'
      :page-sizes='[10, 20, 50, 100]'
      @current-change='handlePageChange'
      @size-change='handleSizeChange'
    />

    <el-dialog v-model='dialogVisible' :title='editingId ? "编辑角色" : "新增角色"' width='92vw' top='4vh'>
      <el-form :model='form' label-width='95px'>
        <el-form-item label='角色名'><el-input v-model='form.name' /></el-form-item>
        <el-form-item label='权限选择'>
          <div class='permission-panel-wrap'>
            <el-cascader-panel v-model='selectedPermissionNodes' :options='permissionCascader' :props='cascaderProps' class='permission-panel' />
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click='dialogVisible = false'>取消</el-button>
        <el-button type='primary' :loading='saving' @click='submit'>提交</el-button>
      </template>
    </el-dialog>
  </el-card>
</template>

<script setup lang='ts'>
import { ElMessage, ElMessageBox } from 'element-plus'
import { computed, onMounted, reactive, ref } from 'vue'
import { permissionsApi } from '@/api/permissions'
import { rolesApi } from '@/api/roles'
import { buildPermissionCascader, extractPermissionIds } from '@/composables/permission-tree'
import { useAuthStore } from '@/stores/auth'

const authStore = useAuthStore()
const { hasPermission } = authStore

const loading = ref(false)
const saving = ref(false)
const dialogVisible = ref(false)
const editingId = ref<number | null>(null)
const rows = ref<any[]>([])
const total = ref(0)
const page = ref(1)
const perPage = ref(20)
const permissionOptions = ref<any[]>([])
const selectedPermissionNodes = ref<Array<number | string>>([])

const form = reactive<any>({ name: '' })
const cascaderProps = { multiple: true, emitPath: false, checkStrictly: false }
const permissionCascader = computed(() => buildPermissionCascader(permissionOptions.value))

async function fetchList(): Promise<void> {
  loading.value = true
  try {
    const response: any = await rolesApi.list({ page: page.value, per_page: perPage.value })
    rows.value = response.data.data || []
    total.value = Number(response.data.total || 0)
  } finally {
    loading.value = false
  }
}

function handlePageChange(nextPage: number): void {
  page.value = nextPage
  fetchList()
}

function handleSizeChange(nextSize: number): void {
  perPage.value = nextSize
  page.value = 1
  fetchList()
}

async function fetchPermissions(): Promise<void> {
  const response: any = await permissionsApi.list({ page: 1, per_page: 500 })
  permissionOptions.value = response.data.data || []
}

function openCreate(): void {
  editingId.value = null
  selectedPermissionNodes.value = []
  Object.assign(form, { name: '' })
  dialogVisible.value = true
}

function openEdit(row: any): void {
  editingId.value = row.id
  selectedPermissionNodes.value = (row.permissions || []).map((item: any) => item.id)
  Object.assign(form, { name: row.name })
  dialogVisible.value = true
}

async function submit(): Promise<void> {
  saving.value = true
  try {
    const payload = { name: form.name, permission_ids: extractPermissionIds(selectedPermissionNodes.value) }

    if (editingId.value) {
      await rolesApi.update(editingId.value, payload)
      ElMessage.success('更新成功')
    } else {
      await rolesApi.create(payload)
      ElMessage.success('创建成功')
    }

    dialogVisible.value = false
    await fetchList()
  } catch (error: any) {
    const first = error?.errors ? (Object.values(error.errors)[0] as string[])?.[0] : null
    ElMessage.error(first || error?.message || '提交失败')
  } finally {
    saving.value = false
  }
}

async function removeRow(row: any): Promise<void> {
  await ElMessageBox.confirm(`确认删除角色 ${row.name} 吗？`, '提示', { type: 'warning' })
  await rolesApi.remove(row.id)
  ElMessage.success('删除成功')
  await fetchList()
}

onMounted(async () => {
  await Promise.all([fetchPermissions(), fetchList()])
})

function sortByPermissions(a: any, b: any): number {
  return ((a.permissions || []).map((item: any) => item.name).join(',')).localeCompare((b.permissions || []).map((item: any) => item.name).join(','))
}
</script>

<style scoped>
.perm-wrap { display: flex; flex-wrap: wrap; gap: 6px; }
.perm-tag { margin: 0; }
:deep(.el-dialog) { max-width: 1000px; }
.permission-panel-wrap { width: 100%; overflow: hidden; }
.permission-panel { width: 100%; height: 40vh; min-height: 420px; }
:deep(.permission-panel .el-cascader-menu) { width: 260px; min-width: 260px; }
:deep(.permission-panel .el-cascader-menu__wrap) { height: 100%; overflow-y: auto; overflow-x: hidden; }
:deep(.permission-panel .el-cascader-node__label) {
  white-space: nowrap;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.35;
}
:deep(.permission-panel .el-cascader-menu__list) { width: 100%; }
:deep(.permission-panel .el-cascader-node) { width: 100%; }
:deep(.permission-panel .el-cascader-panel) { height: 100%; }
</style>
