// 引入lodash库，它是一个功能强大的JavaScript工具库，提供了许多便捷的函数来处理各种数据类型，比如数组、对象的操作等，在后续代码中用于数据的转换、整理等操作。
var _ = require('lodash');
// 引入Node.js的path模块，主要用于处理文件路径相关的操作，像拼接、解析文件路径等，这里用于准确地引入自定义的 `dao/PermissionAPIDAO` 模块所在的文件位置。
var path = require("path");
// 引入自定义的 `PermissionAPIDAO` 模块，通过拼接当前工作目录（`process.cwd()`）和相对路径的方式找到并引入该模块，推测这个模块封装了与权限数据访问相关的操作，比如查询权限数据等功能。
var dao = require(path.join(process.cwd(), "dao/PermissionAPIDAO"));

// 获取所有权限
// 此函数用于获取系统中的所有权限信息，并根据传入的参数类型，以不同的格式返回权限数据，通过回调函数将结果或错误信息传递给调用者。
module.exports.getAllRights = function (type, cb) {
    // 首先对传入的参数 `type` 进行验证，如果 `type` 不存在（即 `!type`），或者 `type` 的值既不是 `"list"` 也不是 `"tree"`，说明参数不符合要求，
    // 则直接通过回调函数 `cb` 返回错误信息，表示参数类型错误，告知调用者传入的参数不符合函数预期的格式要求。
    if (!type || (type!= "list" && type!= "tree")) {
        cb("参数类型错误");
    }

    // 调用 `dao` 模块的 `list` 方法来获取权限数据，这个方法内部大概率会执行数据库查询等操作来获取所有的权限记录信息，它是一个异步操作，通过回调函数来处理获取数据后的结果情况。
    dao.list(function (err, permissions) {
        // 如果在获取权限数据的过程中出现错误（`err` 不为 `null`），比如数据库查询失败（可能是连接问题、权限不足、表不存在等原因），则直接通过回调函数 `cb` 返回错误信息，表示获取权限数据失败，让调用者知晓操作出现问题及原因。
        if (err) return cb("获取权限数据失败");

        // 根据传入的参数 `type` 的值来决定如何处理和返回权限数据。如果 `type` 的值为 `"list"`，表示要以列表形式返回权限数据。
        if (type == "list") {
            // 创建一个空数组 `result`，用于存储整理后的权限数据，后续会将每个权限的相关信息按照特定格式添加到这个数组中。
            var result = [];
            // 遍历获取到的权限数据数组 `permissions`，通过索引 `idx` 来访问每个权限信息对象，进行后续的处理，将每个权限的关键信息提取出来并整理成指定格式后添加到 `result` 数组中。
            for (idx in permissions) {
                permission = permissions[idx];
                result.push({
                    "id": permission.ps_id,
                    "authName": permission.ps_name,
                    "level": permission.ps_level,
                    "pid": permission.ps_pid,
                    "path": permission.ps_api_path
                });
            }
            // 将整理好的权限数据数组 `result` 通过回调函数 `cb` 返回给调用者，表示获取权限数据成功且以列表形式返回了相应的数据，调用者可以根据这个格式的数据进行后续的业务处理，比如展示权限列表等操作。
            cb(null, result);
        } else {
            // 如果 `type` 的值为 `"tree"`，表示要以树形结构返回权限数据，更直观地展示权限之间的层级关系，以下是构建树形结构权限数据的相关逻辑。

            // 使用 `lodash` 的 `keyBy` 函数，将获取到的权限数据（`permissions`）按照权限ID（`ps_id`）进行转换，生成一个以权限ID为键，对应权限详细信息为值的对象结构，
            // 方便后续通过权限ID快速查找对应的权限详情，在构建树形结构以及关联不同层级权限时能更高效地获取所需信息。
            var keyCategories = _.keyBy(permissions, 'ps_id');

            // 显示一级
            // 创建一个空对象 `permissionsResult`，用于存储最终整理好的树形结构权限数据，它将以一级权限的权限ID为键，对应权限的详细信息（包含子权限信息等）为值进行存储，作为树形结构的顶层节点。
            var permissionsResult = {};

            // 处理一级菜单
            // 遍历权限数据数组 `permissions`，通过索引 `idx` 来访问每个权限信息对象，针对每个权限进行相关处理，构建一级菜单对应的权限信息结构并添加到 `permissionsResult` 对象中。
            for (idx in permissions) {
                permission = permissions[idx];
                // 如果当前权限存在（即 `permission` 不为 `null`），并且该权限的层级（`ps_level`）为0，表示它是一级菜单权限，那么就将其相关信息按照特定结构添加到 `permissionsResult` 对象中。
                if (permission && permission.ps_level == 0) {
                    permissionsResult[permission.ps_id] = {
                        "id": permission.ps_id,
                        "authName": permission.ps_name,
                        "path": permission.ps_api_path,
                        "pid": permission.ps_pid,
                        "children": []
                    };
                }
            }

            // 临时存储二级返回结果
            // 创建一个临时对象 `tmpResult`，用于在处理二级菜单权限时，暂时存储二级菜单权限的相关信息，后续会将这些信息整理到对应的一级菜单权限的 `children` 数组中，以构建完整的树形结构。
            tmpResult = {};
            // 处理二级菜单
            // 再次遍历权限数据数组 `permissions`，同样对每个权限进行检查和相关处理，这次是构建二级菜单对应的权限信息结构，并关联到对应的一级菜单权限下。
            for (idx in permissions) {
                permission = permissions[idx];
                if (permission && permission.ps_level == 1) {
                    // 根据当前二级菜单权限的父级权限ID（`ps_pid`），从 `permissionsResult` 中获取对应的一级菜单权限结果对象，后续将把当前二级菜单权限添加到这个一级菜单权限的子权限列表中。
                    parentPermissionResult = permissionsResult[permission.ps_pid];
                    if (parentPermissionResult) {
                        tmpResult[permission.ps_id] = {
                            "id": permission.ps_id,
                            "authName": permission.ps_name,
                            "path": permission.ps_api_path,
                            "pid": permission.ps_pid,
                            "children": []
                        }
                        // 将当前二级菜单权限对象添加到对应的一级菜单权限结果对象的 `children` 数组中，建立起层级关系，表示二级菜单权限隶属于对应的一级菜单权限。
                        parentPermissionResult.children.push(tmpResult[permission.ps_id]);
                    }
                }
            }

            // 处理三级菜单
            // 又一次遍历权限数据数组 `permissions`，针对每个权限进行处理，构建三级菜单对应的权限信息结构，并关联到对应的二级菜单权限下，完善整个权限树形结构。
            for (idx in permissions) {
                permission = permissions[idx];
                if (permission && permission.ps_level == 2) {
                    // 根据当前三级菜单权限的父级权限ID（`ps_pid`），从 `tmpResult` 中获取对应的二级菜单权限结果对象，后续将把当前三级菜单权限添加到这个二级菜单权限的子权限列表中。
                    parentPermissionResult = tmpResult[permission.ps_pid];
                    if (parentPermissionResult) {
                        // 将当前三级菜单权限的相关信息按照特定结构，添加到对应的二级菜单权限结果对象的 `children` 数组中，建立起三级菜单权限与二级菜单权限的隶属关系。
                        // 这里对于 `pid` 属性的赋值，除了当前权限的父级权限ID，还添加了父级权限的父级权限ID（通过 `keyCategories[permission.ps_pid].ps_pid` 获取），
                        // 可能是为了更详细地记录权限的层级关联信息，具体含义要根据业务需求来确定，这样构建出更完整的权限层级结构信息。
                        parentPermissionResult.children.push({
                            "id": permission.ps_id,
                            "authName": permission.ps_name,
                            "path": permission.ps_api_path,
                            "pid": permission.ps_pid + "," + keyCategories[permission.ps_pid].ps_pid
                        });
                    }
                }
            }
            // 使用 `_.values` 获取 `permissionsResult` 对象中的值（即整理好的树形结构权限数据），然后通过回调函数 `cb` 返回这些数据给调用者，
            // 表示获取权限数据成功且以树形结构返回了相应的数据，调用者可以根据这个格式的数据进行后续的业务处理，比如在权限管理页面以树形菜单形式展示权限等操作。
            cb(null, _.values(permissionsResult));
        }
    });
}
//这段代码整体围绕获取系统所有权限信息展开，根据传入的不同参数类型，能够以列表形式或者树形结构
//形式返回权限数据，通过一系列的数据处理和层级构建操作，满足了不同业务场景下对权限数据展示和
//使用的需求，在权限管理相关的应用开发中具有重要作用。
