<template>
  <div>
    <ContentPage>
    <!-- <template #header>角色管理</template> -->

    <template #search>
      <div style="display: flex; gap: 8px">
        <el-input v-model="query.keyword" placeholder="角色名称/标识" style="max-width: 260px" clearable />
        <el-button type="primary" @click="() => ((query.page = 1), load())">查询</el-button>
        <el-button @click="openCreate" style="border: 1px solid var(--ios-primary); color: var(--ios-primary);">新增角色</el-button>
      </div>
    </template>

    <el-table :data="roles" v-loading="loading" style="width: 100%; height: 100%">
      <el-table-column prop="id" label="ID" width="80" />
      <el-table-column prop="roleKey" label="角色标识" />
      <el-table-column prop="roleName" label="角色名称" />
      <el-table-column prop="status" label="状态" width="90">
        <template #default="{ row }">
          <el-tag :type="row.status === 1 ? 'success' : 'danger'">{{ row.status === 1 ? '正常' : '禁用' }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="160">
        <template #default="{ row }">
          <div style="display: flex; align-items: center">
            <el-tooltip content="编辑" placement="top">
              <el-button type="primary" text bg :icon="EditPen" style="font-size: 15px; padding: 6px 8px" @click="openEdit(row)" />
            </el-tooltip>
            <el-tooltip content="分配权限" placement="top">
              <el-button type="primary" text bg :icon="Setting" style="font-size: 15px; padding: 6px 8px" @click="openPermissions(row)" />
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button type="danger" text bg :icon="Delete" style="font-size: 15px; padding: 6px 8px" @click="handleDelete(row)" />
            </el-tooltip>
          </div>
        </template>
      </el-table-column>
    </el-table>

    <template #pagination>
      <el-pagination
        background
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        v-model:page-size="query.size"
        v-model:current-page="query.page"
        :page-sizes="[10, 20, 50, 100]"
        @size-change="load"
        @current-change="load"
      />
    </template>
  </ContentPage>

  <!-- 编辑角色弹窗 -->
  <el-dialog v-model="roleDialogOpen" :title="roleData.id ? '编辑角色' : '新增角色'" width="500px">
    <el-form ref="roleFormRef" :model="roleData" :rules="roleRules" label-width="80px" v-loading="roleLoading">
      <el-form-item label="角色标识" prop="roleKey">
        <el-input v-model="roleData.roleKey" :disabled="!!roleData.id" />
      </el-form-item>
      <el-form-item label="角色名称" prop="roleName">
        <el-input v-model="roleData.roleName" />
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="roleData.status">
          <el-radio :value="1">启用</el-radio>
          <el-radio :value="0">禁用</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="roleDialogOpen = false">取消</el-button>
      <el-button type="primary" :loading="roleLoading" @click="saveRole">保存</el-button>
    </template>
  </el-dialog>

  <!-- 分配权限弹窗 -->
  <el-dialog v-model="permDialogOpen" title="分配权限" width="500px">
    <div style="margin-bottom: 12px; display: flex; align-items: center; gap: 16px;">
      <el-checkbox v-model="expandAll" @change="handleExpandAll">展开/折叠</el-checkbox>
      <el-checkbox v-model="selectAll" @change="handleSelectAll">全选/全不选</el-checkbox>
      <el-checkbox v-model="checkStrictly">父子联动</el-checkbox>
    </div>
    <div v-loading="permLoading" style="height: 400px; overflow-y: auto; border: 1px solid var(--el-border-color-lighter); border-radius: 4px; padding: 8px;">
      <el-tree
        ref="treeRef"
        :data="menuTree"
        show-checkbox
        node-key="id"
        :default-expand-all="true"
        :check-strictly="!checkStrictly"
        :props="{ label: 'name', children: 'children' }"
      />
    </div>
    <template #footer>
      <el-button @click="permDialogOpen = false">取消</el-button>
      <el-button type="primary" :loading="permLoading" @click="savePermissions">保存</el-button>
    </template>
  </el-dialog>
  </div>
</template>


<script setup>
import ContentPage from '@/components/ContentPage.vue'
import { onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Delete, EditPen, Setting } from '@element-plus/icons-vue'
import {
  createRole,
  deleteRole,
  fetchMenuTree,
  fetchRoleMenuIds,
  pageRoles,
  updateRole,
  updateRoleMenus,
} from '../../../api/system'

const query = reactive({
  page: 1,
  size: 10,
  keyword: '',
})

const roles = ref([])
const total = ref(0)
const loading = ref(false)

async function load() {
  loading.value = true
  try {
    const page = await pageRoles(query)
    roles.value = page.records
    total.value = page.total
  } finally {
    loading.value = false
  }
}


// Role Form
const roleDialogOpen = ref(false)
const roleLoading = ref(false)
const roleFormRef = ref(null)
const roleData = reactive({
  id: undefined,
  roleKey: '',
  roleName: '',
  status: 1,
})
const roleRules = {
  roleKey: [{ required: true, message: '请输入角色标识', trigger: 'blur' }],
  roleName: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
}

function openCreate() {
  roleData.id = undefined
  roleData.roleKey = ''
  roleData.roleName = ''
  roleData.status = 1
  roleDialogOpen.value = true
}

function openEdit(row) {
  Object.assign(roleData, row)
  roleDialogOpen.value = true
}

async function saveRole() {
  if (!roleFormRef.value) return
  await roleFormRef.value.validate()
  roleLoading.value = true
  try {
    if (roleData.id) {
      await updateRole(roleData)
      ElMessage.success('更新成功')
    } else {
      await createRole(roleData)
      ElMessage.success('创建成功')
    }
    roleDialogOpen.value = false
    load()
  } catch (e) {
    ElMessage.error(e?.response?.data?.message || '保存失败')
  } finally {
    roleLoading.value = false
  }
}

function handleDelete(row) {
  ElMessageBox.confirm(`确认删除角色 "${row.roleName}" 吗？`, '提示', {
    type: 'warning',
  }).then(async () => {
    try {
      await deleteRole(row.id)
      ElMessage.success('删除成功')
      load()
    } catch (e) {
      ElMessage.error(e?.response?.data?.message || '删除失败')
    }
  })
}

// Permissions
const permDialogOpen = ref(false)
const permLoading = ref(false)
const menuTree = ref([])
const currentRole = ref(null)
const treeRef = ref(null)

// Permission Tree Controls
const expandAll = ref(true)
const selectAll = ref(false)
const checkStrictly = ref(true)

function handleExpandAll(val) {
  const nodes = treeRef.value.store.nodesMap
  for (let i in nodes) {
    nodes[i].expanded = val
  }
}

function handleSelectAll(val) {
  if (val) {
    treeRef.value.setCheckedNodes(menuTree.value)
  } else {
    treeRef.value.setCheckedKeys([])
  }
}

async function openPermissions(row) {
  currentRole.value = row
  permDialogOpen.value = true
  permLoading.value = true
  // Reset controls
  expandAll.value = true
  selectAll.value = false
  checkStrictly.value = true

  try {
    const [menus, checkedKeys] = await Promise.all([fetchMenuTree(), fetchRoleMenuIds(row.id)])
    // fetchMenuTree returns a tree.
    // However, if we're not admin, it might return partial tree.
    // The requirement says "admin has all menus".
    menuTree.value = menus
    
    // Helper to find all leaf node IDs in the tree
    const leafIds = new Set()
    const traverse = (nodes) => {
      for (const node of nodes) {
        if (node.children && node.children.length > 0) {
          traverse(node.children)
        } else {
          leafIds.add(node.id)
        }
      }
    }
    traverse(menus)

    // Only set checked keys for leaf nodes. 
    // Element Plus tree will automatically check parent nodes if all children are checked,
    // or indeterminate if some are checked.
    const leafCheckedKeys = checkedKeys.filter(id => leafIds.has(id))

    // We need to wait for next tick or manually set checked keys
    // But tree might render async.
    // Element Plus tree setCheckedKeys works better after data is set.
    setTimeout(() => {
      treeRef.value?.setCheckedKeys(leafCheckedKeys, false)
    }, 0)
  } finally {
    permLoading.value = false
  }
}

async function savePermissions() {
  if (!currentRole.value) return
  permLoading.value = true
  try {
    // We need both checked nodes and half-checked nodes if the backend logic requires it.
    // Typically backend expects all menu IDs needed to reconstruct the permission set.
    // Element Plus: getCheckedKeys() returns only checked leaf nodes by default if we don't include half-checked.
    // But usually for menu permissions we want all checked + half-checked (parent nodes).
    const checked = treeRef.value.getCheckedKeys()
    const halfChecked = treeRef.value.getHalfCheckedKeys()
    const allIds = [...checked, ...halfChecked]
    await updateRoleMenus(currentRole.value.id, allIds)
    ElMessage.success('权限保存成功')
    permDialogOpen.value = false
  } catch (e) {
    ElMessage.error(e?.response?.data?.message || '保存失败')
  } finally {
    permLoading.value = false
  }
}

onMounted(load)
</script>
