<script setup lang="ts">
import { reactive, onMounted, ref, nextTick } from "vue";
import { http } from "@/utils/http";
import { deleteRole } from "@/api/role";
import { ElMessage, ElMessageBox } from "element-plus";
import { CircleCheckFilled } from "@element-plus/icons-vue";
import RoleDialog from "./dialog.vue";

defineOptions({ name: "AdminRole" });

const queryRef = ref();
const tableRef = ref();
const dialogRef = ref();

interface ColumnItem {
  label: string;
  prop: string;
  width?: number;
  fixed?: string;
}

const state = reactive({
  formQuery: {
    roleName: ""
  },
  tableData: {
    height: 500,
    data: [] as Array<any>,
    loading: false
  },
  columns: [{ label: "权限", prop: "permName", width: 200, fixed: "left" }] as ColumnItem[],
  expandAll: false,
  immutableRoleList: [] as string[],
  changed: false,
  roleDataMap: new Map() as Map<number, any>
});

onMounted(() => {
  loadData();
  nextTick(() => {
    const bodyHeight = document.body.clientHeight;
    const queryHeight = queryRef.value?.$el?.clientHeight || 0;
    state.tableData.height = bodyHeight - queryHeight - 230;
  });
});

const handleExpandSwitch = () => {
  state.expandAll = !state.expandAll;
  nextTick(() => {
    state.tableData.data.forEach((row: any) => {
      tableRef.value?.toggleRowExpansion(row, state.expandAll);
    });
  });
};

const loadPermissionList = (roleList: Array<any>) => {
  http.request<any>("get", "/permission/listPermission", { params: { pageSize: -1 } })
    .then((res: any) => {
      const data: any[] = [];
      const permMap = groupByKey(res || [], "pid");
      const roleMap = new Map();
      state.immutableRoleList = [];

      roleList.forEach((role: any) => {
        state.roleDataMap.set(role.id, role);
        state.columns.push({
          label: role.roleName,
          prop: "role_" + role.id,
          width: role.roleName.length * 60 + 45
        });
        roleMap.set(role.id, role);
      });

      const topPermissionList = permMap["0"] || [];
      if (topPermissionList.length === 0) {
        ElMessage.error("没有权限数据");
        state.tableData.loading = false;
        return;
      }

      topPermissionList.forEach((top: any) => {
        const { id, name, value } = top;
        const childrenPermissionList = permMap[id.toString()] || [];
        const record: any = {
          children: [] as any[],
          permName: name,
          id: id,
          perm: value
        };

        roleList.forEach((role: any) => {
          record["role_" + role.id] = !!(role.permissions && role.permissions.includes(value));
        });

        const children: any[] = [];
        if (childrenPermissionList.length > 0) {
          childrenPermissionList.forEach((child: any) => {
            const childRecord: any = {
              permName: child.name,
              id: child.id,
              perm: child.value
            };
            roleList.forEach((role: any) => {
              childRecord["role_" + role.id] = !!(role.permissions && role.permissions.includes(child.value));
            });
            children.push(childRecord);
          });
          record.children = children;
        }
        data.push(record);
      });

      state.tableData.data = data;
      state.tableData.loading = false;
    })
    .catch(() => {
      state.tableData.loading = false;
    });
};

const loadData = () => {
  state.columns = [{ label: "权限", prop: "permName", width: 200, fixed: "left" }];
  state.tableData.data = [];
  state.tableData.loading = true;

  http.request<any>("get", "/role/list", { params: { ...state.formQuery } })
    .then((res: any) => {
      loadPermissionList(res || []);
    })
    .catch(() => {
      state.tableData.loading = false;
    });
};

const handleToggleRoleCheck = (row: any, column: any) => {
  state.changed = true;

  if (column.rawColumnKey === "permName") {
    return;
  }

  const index = state.tableData.data.findIndex((k: any) => k.id === row.id);
  if (index >= 0) {
    const record = state.tableData.data[index];
    const bol = !record[column.rawColumnKey];
    state.tableData.data[index][column.rawColumnKey] = bol;
    if (record.children && record.children.length > 0) {
      record.children.forEach((r: any) => {
        r[column.rawColumnKey] = bol;
      });
    }
  } else {
    state.tableData.data.forEach((record: any) => {
      if (record.children && record.children.length > 0) {
        const r = record.children.find((k: any) => k.id === row.id);
        if (r) {
          r[column.rawColumnKey] = !r[column.rawColumnKey];
          return;
        }
      }
    });
  }
};

const handleSaveRolePermission = () => {
  const updateRoles: any[] = [];
  const map = new Map<string, string[]>();

  if (state.tableData.data.length === 0) return;

  const keys = Object.keys(state.tableData.data[0]);

  state.tableData.data.forEach((record: any) => {
    keys.forEach((k: string) => {
      if (k.startsWith("role_")) {
        if (record[k]) {
          const roleId = k.split("_")[1];
          const existing = map.get(roleId);
          if (!existing) {
            map.set(roleId, [record.perm]);
          } else {
            existing.push(record.perm);
            map.set(roleId, existing);
          }
        }
      }
      if (record.children && record.children.length > 0) {
        record.children.forEach((child: any) => {
          if (k.startsWith("role_")) {
            if (child[k]) {
              const roleId = k.split("_")[1];
              const existing = map.get(roleId);
              if (!existing) {
                map.set(roleId, [child.perm]);
              } else {
                existing.push(child.perm);
                map.set(roleId, existing);
              }
            }
          }
        });
      }
    });
  });

  map.forEach((value: string[], key: string) => {
    updateRoles.push({
      id: Number(key),
      permissions: value.join("|")
    });
  });

  http.request<any>("post", "/role/saveList", { data: updateRoles })
    .then(() => {
      ElMessage.success("更新成功");
      state.changed = false;
      nextTick(() => {
        loadData();
      });
    });
};

const handleSearch = () => {
  loadData();
};

const handleReset = () => {
  state.formQuery = {
    roleName: ""
  };
  loadData();
};

const handleAddRole = () => dialogRef.value?.open("add");

const handleEditRole = (colProp: string) => {
  const roleId = Number(colProp.split("_")[1]);
  const role = state.roleDataMap.get(roleId);
  if (role) {
    dialogRef.value?.open("edit", role);
  }
};

const handleDeleteRole = (colProp: string) => {
  const roleId = Number(colProp.split("_")[1]);
  const role = state.roleDataMap.get(roleId);
  if (!role) return;
  ElMessageBox.confirm(`确定要删除角色"${role.roleName}"吗？`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    deleteRole(role.id).then(() => {
      ElMessage.success("删除成功");
      loadData();
    });
  }).catch(() => {});
};

// 工具函数
const groupByKey = (arr: any[], key: string) => {
  const result: Record<string, any[]> = {};
  arr.forEach((item: any) => {
    const k = item[key]?.toString() || "0";
    if (!result[k]) {
      result[k] = [];
    }
    result[k].push(item);
  });
  return result;
};
</script>

<template>
  <div class="page-container">
    <el-card shadow="hover">
      <template #header>
        <span class="card-header">角色权限</span>
      </template>
      <el-form ref="queryRef" :model="state.formQuery" inline class="search-form">
        <el-form-item>
          <el-input
            v-model="state.formQuery.roleName"
            placeholder="请输入角色名称"
            clearable
            style="max-width: 180px"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">查询</el-button>
          <el-button @click="handleReset">重置</el-button>
          <el-button type="success" @click="handleAddRole">新增角色</el-button>
          <el-button v-if="state.changed" type="success" @click="handleSaveRolePermission">
            保存设置
          </el-button>
        </el-form-item>
      </el-form>

      <el-table
        ref="tableRef"
        v-loading="state.tableData.loading"
        :data="state.tableData.data"
        :height="state.tableData.height"
        border
        row-key="id"
        :tree-props="{ children: 'children' }"
        @cell-click="handleToggleRoleCheck"
      >
        <template #empty>
          <el-empty description="暂无数据" />
        </template>
        <el-table-column
          v-for="(col, idx) in state.columns"
          :key="col.prop"
          :label="col.label"
          :prop="col.prop"
          :width="col.width"
          :fixed="col.fixed"
          :align="col.prop === 'permName' ? 'left' : 'center'"
          show-overflow-tooltip
        >
          <template #header>
            <template v-if="idx > 0">
              <div class="role-header-item">
                <span>{{ col.label }}</span>
                <span class="role-header-actions">
                  <el-button
                    link
                    type="primary"
                    size="small"
                    title="编辑"
                    @click.stop="handleEditRole(col.prop)"
                  >
                    <el-icon><i class="ri-edit-line" /></el-icon>
                  </el-button>
                  <el-button
                    link
                    type="danger"
                    size="small"
                    title="删除"
                    @click.stop="handleDeleteRole(col.prop)"
                  >
                    <el-icon><i class="ri-delete-bin-line" /></el-icon>
                  </el-button>
                </span>
              </div>
            </template>
            <template v-if="idx === 0">
              权限
              <span
                style="cursor: pointer; font-size: 12px; margin-left: 8px; color: var(--el-text-color-secondary)"
                @click="handleExpandSwitch"
              >
                {{ state.expandAll ? "收起" : "展开" }}
              </span>
            </template>
          </template>
          <template #default="scope">
            <template v-if="scope.column.label !== '权限'">
              <el-icon v-if="scope.row[scope.column.rawColumnKey]" color="var(--el-color-success)">
                <CircleCheckFilled />
              </el-icon>
              <span v-else>-</span>
            </template>
            <template v-else>
              <span :title="scope.row.perm">{{ scope.row[scope.column.property] }}</span>
            </template>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <RoleDialog ref="dialogRef" @refresh="loadData" />
  </div>
</template>

<style scoped lang="scss">
.page-container {
  padding: 15px;
}

.card-header { font-size: 16px; font-weight: 600; }

.search-form {
  margin-bottom: 15px;
}

.role-header-item {
  display: inline-flex;
  justify-content: space-around;
  align-items: center;
}

:deep(.el-table thead th.el-table__cell) {
  background: var(--el-fill-color-light);
}
</style>
