// 引入Express框架的核心模块，用于创建Web应用、定义路由以及处理HTTP请求等相关操作。
// Express是Node.js中非常流行的Web应用框架，它提供了便捷的方式来搭建服务器、配置路由以及处理不同类型的HTTP请求，是整个后端服务开发的基础。
var express = require('express');

// 创建一个Express路由器实例，方便以模块化的方式来定义一组相关的路由，便于在整个应用中进行有条理的路由管理。
// 通过使用路由器实例，可以将不同功能模块（比如这里的角色管理相关路由）的路由集中定义在一起，使得代码结构更加清晰，易于维护和扩展，避免路由逻辑过于混乱。
var router = express.Router();

// 引入Node.js的path模块，主要用于处理文件路径相关的操作，比如拼接模块的路径，以便准确地引入其他模块。
// 在Node.js项目中，模块的位置需要精确指定才能正确加载，path模块提供了诸如拼接、解析路径等功能，帮助我们根据项目目录结构找到所需模块。
var path = require("path");

// 获取自定义的验证模块，通过path.join方法将当前工作目录（process.cwd()）与相对路径（"/modules/authorization"）拼接起来，准确地引入该验证模块。
// 这种方式确保了无论项目在何种环境下运行，都能正确定位到验证模块所在位置。该验证模块通常在整个应用架构中起着关键作用，用于验证用户的权限等情况，
// 以此确保后续的各种操作都符合相应的安全和业务规则，防止未经授权的访问或不符合业务逻辑的操作发生。
var authorization = require(path.join(process.cwd(), "/modules/authorization"));

// 通过验证模块获取名为"RoleService"的角色管理模块，该模块应该封装了与角色相关的各种业务操作方法，例如角色的增删改查以及权限管理等功能。
// 将角色管理相关的业务逻辑封装在这个服务模块内，使得代码职责更加清晰，在路由处理中只需调用该模块提供的相应方法即可实现具体的角色管理操作，
// 而不用在路由代码中分散地编写复杂的数据库操作、权限判断等具体业务实现细节。
var roleServ = authorization.getService("RoleService");

// 定义处理获取角色列表的GET请求的路由，路径为根路径 "/"。
// 当客户端向服务器发送GET请求到根路径时，会进入这个路由对应的处理逻辑，以获取所有角色的相关信息，通常会从数据库等数据存储中查询并返回这些信息给客户端。
router.get("/",
    // 参数验证中间件，当前这里直接调用next()，意味着暂时没有进行额外的参数验证逻辑，不过一般情况下可根据实际需求添加相关验证，比如分页参数等验证。
    // 在实际应用中，获取角色列表可能需要分页展示等功能，那时就需要对请求中的分页相关参数（如页码、每页数量等）进行合法性检查，确保后续查询操作能正确执行。
    function (req, res, next) {
        next();
    },
    // 处理业务逻辑的中间件，用于获取所有角色的信息。在参数验证中间件（当前为空验证）通过后，会进入这个中间件来执行具体的获取角色列表操作。
    function (req, res, next) {
        // 调用roleServ角色管理模块的getAllRoles方法，该方法用于获取所有角色的相关数据，是一个异步操作。
        // 它内部可能涉及到数据库连接、查询语句执行等操作，从数据库中获取所有角色记录，并整理成合适的数据格式返回。
        // 如果在获取角色列表的过程中出现错误（err不为null），比如数据库查询失败、权限不足无法获取等情况，则通过res.sendResult返回包含错误信息的响应，状态码为400，表示请求出现错误，
        // 同时将具体的错误信息（err）传递给客户端，让客户端知晓请求失败的原因。
        // 如果获取成功，则返回包含角色列表数据（result）的响应，状态码为200，并附带提示信息"获取成功"，告知客户端操作已顺利完成，客户端可以根据接收到的数据进行展示等后续处理。
        roleServ.getAllRoles(function (err, result) {
            if (err) return res.sendResult(null, 400, err);
            res.sendResult(result, 200, "获取成功");
        })(req, res, next);
    }
);

// 定义处理创建角色的POST请求的路由，路径为 "/"。
// 当客户端向服务器的根路径发送POST请求时，会进入此路由对应的处理逻辑，用于创建新的角色，一般需要在请求体中携带创建角色所需的相关信息，如角色名称、描述等。
router.post("/",
    // 参数验证中间件，用于验证创建角色时请求体中必要参数是否存在。在创建角色的业务逻辑中，角色名称通常是必不可少的关键信息，所以要先对其进行验证。
    function (req, res, next) {
        // 检查请求体中是否包含roleName字段，如果不存在则返回错误响应，状态码400表示请求参数有误，同时附带提示信息"角色名称不能为空"。
        // 因为没有角色名称就无法创建一个有意义的角色，所以必须确保该字段存在于请求体中。
        if (!req.body.roleName) return res.sendResult(null, 400, "角色名称不能为空");
        // 参数验证通过后，将控制权传递给下一个中间件，继续后续的业务逻辑处理。通过调用next()函数，按照Express中间件的执行机制，让请求可以继续流转到下一个环节进行处理。
        next();
    },
    // 处理业务逻辑的中间件，用于创建新的角色。在前面的参数验证中间件通过后，会进入这个中间件来执行实际的创建角色操作，比如将角色数据插入到数据库等数据存储中。
    function (req, res, next) {
        // 构建一个包含角色名称（roleName）和角色描述（roleDesc）的对象，从请求体中获取相应的值。
        // 这里假设创建角色时，除了必填的角色名称外，还可以选择性地传入角色描述信息，将这些信息整理成一个对象传递给创建角色的服务方法。
        roleServ.createRole({
            "roleName": req.body.roleName,
            "roleDesc": req.body.roleDesc
        }, function (err, role) {
            // 如果创建角色的操作出现错误（err不为null），比如数据库插入失败、参数不符合数据库表结构要求等情况，则通过res.sendResult返回包含错误信息的响应，状态码为400，表示请求出现错误，
            // 同时将具体的错误信息（err）传递给客户端，告知客户端创建角色失败的原因。
            if (err) return res.sendResult(null, 400, err);
            // 如果创建成功，则返回包含新创建角色信息（role）的响应，状态码为201，表示资源创建成功，并附带提示信息"创建成功"，告知客户端新角色已成功创建，
            // 客户端可以根据接收到的角色信息进行后续操作，比如进一步为该角色配置权限等。
            res.sendResult(role, 201, "创建成功");
        })(req, res, next);
    }
);

// 定义处理获取角色详情的GET请求的路由，路径中包含角色ID参数，格式为 "/:id"。
// 当客户端向服务器发送GET请求并在路径中携带具体的角色ID时，会进入这个路由对应的处理逻辑，用于获取对应角色的详细信息，例如角色的具体权限、关联的用户等信息。
router.get("/:id",
    // 参数验证中间件，用于验证角色ID参数的合法性。因为要获取特定角色的详细信息，必须先确保传入的角色ID是合法有效的，才能准确从数据库等数据源中查找对应的角色记录。
    function (req, res, next) {
        // 检查请求参数中的角色ID（req.params.id）是否存在，如果不存在则返回错误响应，状态码400表示请求参数有误，同时附带提示信息"角色ID不能为空"。
        // 若没有角色ID，服务器就无法确定要获取哪个角色的详细信息，所以该参数不能为空。
        if (!req.params.id) return res.sendResult(null, 400, "角色ID不能为空");
        // 进一步验证角色ID是否可以转换为数字类型，如果不能转换成功（即不是有效的数字），则返回错误响应，状态码同样为400，并附带提示信息"角色ID必须为数字"。
        // 通常在数据库中角色ID是以数字形式存储和标识的，所以要求传入的参数能正确转换为数字，以保证后续查询操作的准确性。
        if (isNaN(parseInt(req.params.id))) res.sendResult(null, 400, "角色ID必须为数字");
        // 参数验证通过后，将控制权传递给下一个中间件，继续后续的业务逻辑处理。通过调用next()，使请求能继续进入下一个中间件执行获取角色详情的业务逻辑。
        next();
    },
    // 处理业务逻辑的中间件，用于获取指定角色的详细信息。在前面参数验证中间件通过后，会进入此中间件来执行具体的获取角色详情操作，比如从数据库中查询对应角色的详细记录信息。
    function (req, res, next) {
        // 调用roleServ角色管理模块的getRoleById方法，传入经过验证的角色ID（req.params.id），用于获取该角色的详细信息，这是一个异步操作。
        // 该方法内部会根据传入的角色ID去数据库等数据存储中查找对应的角色记录，并提取相关详细信息进行返回，这个过程可能涉及数据库查询、数据关联查询等操作。
        // 如果在获取角色详情的过程中出现错误（err不为null），例如数据库查询失败、角色ID对应的记录不存在等情况，则通过res.sendResult返回包含错误信息的响应，状态码为400，表示请求出现错误，
        // 同时将具体的错误信息（err）传递给客户端，让客户端知晓获取角色详情失败的原因。
        // 如果获取成功，则返回包含角色详细信息（result）的响应，状态码为200，并附带提示信息"获取成功"，告知客户端操作已顺利完成，客户端可以根据接收到的详细信息进行展示或其他相关操作。
        roleServ.getRoleById(
            req.params.id,
            function (err, result) {
                if (err) return res.sendResult(null, 400, err);
                res.sendResult(result, 200, "获取成功");
            }
        )(req, res, next);
    }
);

// 定义处理更新角色信息的PUT请求的路由，路径中包含角色ID参数，格式为 "/:id"。
// 当客户端向服务器发送PUT请求并在路径中携带角色ID时，会进入这个路由对应的处理逻辑，用于更新指定角色的相关信息，比如修改角色名称、描述等内容。
router.put("/:id",
    // 参数验证中间件，用于验证更新角色信息时必要参数的合法性。在更新角色信息时，既要确保角色ID是合法有效的，又要保证请求体中包含必要的更新内容（如角色名称等）。
    function (req, res, next) {
        // 检查请求参数中的角色ID（req.params.id）是否存在，如果不存在则返回错误响应，状态码400表示请求参数有误，同时附带提示信息"角色ID不能为空"。
        // 因为没有角色ID就无法确定要更新哪个角色的信息，所以该参数必须存在。
        if (!req.params.id) return res.sendResult(null, 400, "角色ID不能为空");
        // 验证角色ID是否可以转换为数字类型，如果不能转换成功（即不是有效的数字），则返回错误响应，状态码为400，并附带提示信息"角色ID必须为数字"。
        // 与获取角色详情类似，数据库中角色ID通常以数字形式存储，所以要保证传入的ID能正确转换为数字，便于准确更新对应角色的记录。
        if (isNaN(parseInt(req.params.id))) return res.sendResult(null, 400, "角色ID必须为数字");
        // 检查请求体中是否包含roleName字段，如果不存在则返回错误响应，状态码400表示请求参数有误，同时附带提示信息"角色名称不能为空"。
        // 角色名称是角色的重要标识信息，更新角色时一般需要修改这个字段，所以必须确保请求体中包含该字段，否则无法进行有效的更新操作。
        if (!req.body.roleName) return res.sendResult(null, 400, "角色名称不能为空");
        // 参数验证通过后，将控制权传递给下一个中间件，继续后续的业务逻辑处理。通过调用next()函数，使请求能继续流转到下一个中间件执行更新角色信息的业务逻辑。
        next();
    },
    // 处理业务逻辑的中间件，用于更新指定角色的信息。在前面参数验证中间件通过后，会进入这个中间件来执行实际的更新角色信息操作，比如修改数据库中对应角色记录的相关字段值。
    function (req, res, next) {
        // 构建一个包含角色ID（id）、角色名称（roleName）和角色描述（roleDesc）的对象，用于传递给更新角色信息的方法。
        // 这里将角色ID以及从请求体中获取的角色名称和可能存在的角色描述信息整理成一个对象，以便准确地将更新内容传递给服务模块的更新方法进行处理。
        roleServ.updateRole(
            {
                "id": req.params.id,
                "roleName": req.body.roleName,
                "roleDesc": req.body.roleDesc
            },
            function (err, result) {
                // 如果更新角色信息的操作出现错误（err不为null），比如数据库更新失败、传入的更新参数不符合要求等情况，则通过res.sendResult返回包含错误信息的响应，状态码为400，表示请求出现错误，
                // 同时将具体的错误信息（err）传递给客户端，告知客户端更新角色信息失败的原因。
                if (err) return res.sendResult(null, 400, err);
                // 如果更新成功，则返回包含更新后角色信息（result）的响应，状态码为200，并附带提示信息"获取成功"（此处提示信息可能更改为"更新成功"更合适，可根据实际情况调整）。
                // 告知客户端角色信息已成功更新，客户端可以根据更新后的信息进行相应的后续操作，比如查看更新后的角色详情等。
                res.sendResult(result, 200, "获取成功");
            }
        )(req, res, next);
    }
);

// 定义处理删除角色的DELETE请求的路由，路径中包含角色ID参数，格式为 "/:id"。
// 当客户端向服务器发送DELETE请求并在路径中携带角色ID时，会进入这个路由对应的处理逻辑，用于删除指定的角色，从数据库等数据存储中移除对应的角色记录。
router.delete("/:id",
    // 参数验证中间件，用于验证角色ID参数的合法性。在执行删除角色操作前，必须确保传入的角色ID是合法有效的，避免误删或因无效ID导致操作失败。
    function (req, res, next) {
        // 检查请求参数中的角色ID（req.params.id）是否存在，如果不存在则返回错误响应，状态码400表示请求参数有误，同时附带提示信息"角色ID不能为空"。
        // 若没有角色ID，服务器无法确定要删除哪个角色，所以该参数不能为空。
        if (!req.params.id) return res.sendResult(null, 400, "角色ID不能为空");
        // 验证角色ID是否可以转换为数字类型，如果不能转换成功（即不是有效的数字），则返回错误响应，状态码为400，并附带提示信息"角色ID必须为数字"。
        // 同样，由于数据库中角色ID通常以数字形式存储，需要保证传入的ID能正确转换为数字，以准确执行删除操作。
        if (isNaN(parseInt(req.params.id))) return res.sendResult(null, 400, "角色ID必须为数字");
        // 参数验证通过后，将控制权传递给下一个中间件，继续后续的业务逻辑处理。通过调用next()函数，使请求能继续进入下一个中间件执行删除角色的业务逻辑。
        next();
    },
    // 处理业务逻辑的中间件，用于执行删除指定角色的操作。在前面参数验证中间件通过后，会进入这个中间件来执行实际的删除角色操作，比如从数据库中删除对应的角色记录。
    function (req, res, next) {
        // 调用roleServ角色管理模块的deleteRole方法，传入经过验证的角色ID（req.params.id），用于删除该角色，这是一个异步操作。
        // 该方法内部会与数据库进行交互，执行删除对应的角色记录的操作，这个过程可能涉及到数据库事务处理等相关操作，以确保数据的一致性和完整性。
        // 如果在删除角色的过程中出现错误（err不为null），比如数据库删除失败、存在关联数据导致无法删除等情况，则通过res.sendResult返回包含错误信息的响应，状态码为400，表示请求出现错误，
        // 同时将具体的错误信息（err）传递给客户端，让客户端知晓删除角色失败的原因。
        // 如果删除成功，则返回一个空数据的响应（因为角色已被删除），状态码为200，并附带提示信息"删除成功"，告知客户端指定角色已成功删除。
        roleServ.deleteRole(
            req.params.id,
            function (err, success) {
                if (err) return res.sendResult(null, 400, err);
                res.sendResult(null, 200, "删除成功");
            }
        )(req, res, next);
    }
);

// 定义处理为角色授权的POST请求的路由，路径中包含角色ID参数，格式为 "/:id/rights"。
// 意味着当客户端向服务器发送POST请求到这个特定路径（其中包含具体的角色ID）时，会进入此路由对应的处理逻辑，
// 目的是为指定的角色更新其权限信息，比如给某个角色添加新的权限或者修改已有的权限配置等操作。
router.post("/:id/rights",
    // 参数校验中间件，用于验证角色ID参数的合法性。
    // 在进行角色授权操作前，必须确保传入的角色ID是准确且符合要求的，否则无法确定要为哪个角色进行权限更新，
    // 这是保障后续业务逻辑能正确执行的前置必要步骤。
    function (req, res, next) {
        // 检查请求参数中的角色ID（req.params.id）是否存在，如果不存在则返回错误响应，状态码400表示请求参数有误，
        // 同时附带提示信息"角色ID不能为空"。因为角色ID是定位具体角色的关键标识，缺少它就无法明确操作对象，所以该参数必须存在。
        if (!req.params.id) return res.sendResult(null, 400, "角色ID不能为空");
        // 验证角色ID是否可以转换为数字类型，如果不能转换成功（即不是有效的数字），则返回错误响应，状态码为400，
        // 并附带提示信息"角色ID必须为数字"。通常在系统设计中，角色ID在数据库等存储中是以数字形式存储和管理的，
        // 所以传入的角色ID参数需要能正确转换为数字才能准确匹配到对应的角色记录进行权限更新操作。
        if (isNaN(parseInt(req.params.id))) res.sendResult(null, 400, "角色ID必须为数字");
        // 参数验证通过后，将控制权传递给下一个中间件，继续后续的业务逻辑处理。
        // 通过调用next()函数，遵循Express中间件的执行流程，让请求可以顺利流转到下一个中间件去执行具体的为角色授权的业务逻辑。
        next();
    },
    // 业务逻辑中间件，用于为指定角色更新权限。
    // 在前面参数验证中间件通过后，进入此中间件执行实际的更新角色权限的操作，例如在数据库中修改角色与权限关联表的相关记录等操作。
    function (req, res, next) {
        // 调用roleServ角色管理模块的updateRoleRight方法，传入角色ID（req.params.id）和权限ID列表（req.body.rids），
        // 用于更新角色的权限信息，这是一个异步操作。updateRoleRight方法应该是在RoleService中定义的，
        // 其内部实现了根据传入的角色ID以及要赋予或修改的权限ID列表，去更新对应角色的权限配置的具体逻辑，
        // 这个过程可能涉及到数据库的插入、更新等操作，以确保角色的权限数据能准确变更。
        // 如果在更新角色权限的过程中出现错误（err不为null），比如数据库连接失败、权限数据更新出现冲突等情况，
        // 则通过res.sendResult返回包含错误信息的响应，状态码为400，表示请求出现错误，同时将具体的错误信息（err）传递给客户端，
        // 让客户端知晓更新权限操作失败的原因。
        // 如果更新成功，则返回一个空数据的响应（重点在于权限更新成功的提示），状态码为200，并附带提示信息"更新成功"，
        // 告知客户端指定角色的权限已按照要求成功更新，客户端可以基于这个提示信息知晓操作结果，进行后续的相关操作，
        // 比如重新获取角色详情查看更新后的权限情况等。
        roleServ.updateRoleRight(req.params.id, req.body.rids, function (err, newRole) {
            if (err) return res.sendResult(null, 400, err);
            res.sendResult(null, 200, "更新成功");
        })(req, res, next);
    }
);

// 定义处理删除角色权限的DELETE请求的路由，路径中包含角色ID和权限ID两个参数，格式为 "/:id/rights/:rightId"。
// 当客户端向服务器发送DELETE请求到这个特定路径（包含具体的角色ID和权限ID）时，会进入此路由对应的处理逻辑，
// 用于执行删除指定角色的指定权限的操作，例如撤销某个角色已有的某项特定权限等情况。
router.delete("/:id/rights/:rightId",
    // 参数验证中间件，用于验证角色ID和权限ID参数的合法性。
    // 在执行删除角色权限操作前，必须确保传入的角色ID和权限ID都是合法有效的，否则可能导致误删或者因无法准确定位要删除的权限记录而操作失败，
    // 所以要对这两个关键参数进行严格的合法性验证。
    function (req, res, next) {
        // 检查请求参数中的角色ID（req.params.id）是否存在，如果不存在则返回错误响应，状态码400表示请求参数有误，
        // 同时附带提示信息"角色ID不能为空"。与前面类似，角色ID是确定操作对象（具体角色）的关键，缺少它无法明确要对哪个角色的权限进行删除操作，所以必须存在。
        if (!req.params.id) return res.sendResult(null, 400, "角色ID不能为空");
        // 验证角色ID是否可以转换为数字类型，如果不能转换成功（即不是有效的数字），则返回错误响应，状态码为400，
        // 并附带提示信息"角色ID必须为数字"。这是基于数据库中角色ID存储形式的要求，确保能准确匹配到对应的角色记录来进行权限删除操作。
        if (isNaN(parseInt(req.params.id))) res.sendResult(null, 400, "角色ID必须为数字");
        // 检查请求参数中的权限ID（req.params.rightId）是否存在，如果不存在则返回错误响应，状态码400表示请求参数有误，
        // 同时附带提示信息"权限ID必须为数字"。权限ID同样是定位要删除的具体权限的关键标识，若不存在则无法准确知道要删除哪个权限，所以该参数也必须存在。
        if (isNaN(parseInt(req.params.rightId))) res.sendResult(null, 400, "权限ID必须为数字");
        // 参数验证通过后，将控制权传递给下一个中间件，继续后续的业务逻辑处理。
        // 通过调用next()函数，按照Express中间件机制，让请求继续流转到下一个中间件去执行实际的删除角色权限的业务逻辑。
        next();
    },
    // 业务逻辑中间件，用于执行删除指定角色的指定权限的操作。
    // 在前面参数验证中间件通过后，进入此中间件执行具体的从数据库等存储中删除对应角色权限记录的操作，
    // 例如在角色与权限关联表中删除相应的关联记录，以实现取消指定权限的功能。
    function (req, res, next) {
        // 调用roleServ角色管理模块的deleteRoleRight方法，传入角色ID（req.params.id）和权限ID（req.params.rightId），
        // 用于删除该角色的指定权限，这是一个异步操作。deleteRoleRight方法内部实现了根据传入的角色ID和权限ID，
        // 在数据存储中准确找到并删除相应权限关联记录的具体逻辑，这个过程需要考虑数据的一致性、完整性以及可能存在的关联约束等情况。
        // 如果在删除角色权限的过程中出现错误（err不为null），比如数据库删除操作失败、存在外键约束导致无法删除等情况，
        // 则通过res.sendResult返回包含错误信息的响应，状态码为400，表示请求出现错误，同时将具体的错误信息（err）传递给客户端，
        // 让客户端知晓删除权限操作失败的原因。
        // 如果删除成功，则返回一个空数据的响应（重点在于提示取消权限成功），状态码为200，并附带提示信息"取消权限成功"，
        // 告知客户端指定角色的指定权限已成功取消，客户端可以据此进行后续操作，比如再次查看角色权限列表确认权限已被删除等情况。
        roleServ.deleteRoleRight(req.params.id, req.params.rightId, function (err, result) {
            if (err) return res.sendResult(null, 400, err);
            res.sendResult(result, 200, "取消权限成功");
        })(req, res, next);
    }
);

// 将配置好的路由器对象导出，以便在主应用中引入并挂载到对应的路径上，使这些路由能够正确响应客户端发送的相应HTTP请求，
// 实现角色管理相关的各种功能。在主应用中，通过引入这个路由器模块，并将其挂载到对应的路径上，
// 服务器就能根据客户端发送的不同请求（如获取角色列表、创建角色、更新角色权限等），按照这里定义的路由逻辑进行相应的处理，
// 从而完整地实现角色管理的各项功能，为整个应用提供角色相关的服务支持。
module.exports = router;
//这段代码整体围绕角色管理中的权限相关操作（为角色授权和删除角色权限）定义了相应的路由及处理逻
//辑，通过严格的参数验证和具体的业务逻辑处理，确保操作的合法性和数据的准确性，最终实现角色管理
//在权限方面的功能需求。