package com.jiayue.ssi.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.util.NumberUtil;
import com.jiayue.ssi.annotation.OperateLog;
import com.jiayue.ssi.annotation.PreventReplay;
import com.jiayue.ssi.backenum.AuditType;
import com.jiayue.ssi.backenum.BusinessType;
import com.jiayue.ssi.constant.CustomException;
import com.jiayue.ssi.constant.UserConstants;
import com.jiayue.ssi.entity.SysMenu;
import com.jiayue.ssi.entity.SysRole;
import com.jiayue.ssi.service.SysMenuService;
import com.jiayue.ssi.service.SysRoleService;
import com.jiayue.ssi.util.RyStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.jiayue.ssi.util.ResponseVO;
import com.jiayue.ssi.util.SecurityContextUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 菜单接口
 *
 * @author xsl
 * @since 2023/03/21
 */
@RestController
@RequestMapping("/sysMenuController")
@Slf4j
public class SysMenuController {

    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysRoleService sysRoleService;

    /**
     * 获取菜单列表
     */
    @GetMapping("/list")
    @PreAuthorize("@ss.hasPermi('system:menu:list')")
    @OperateLog(title = "菜单管理", businessType = BusinessType.QUERY, auditType = AuditType.SYS,operdesc = "查询菜单")
    @PreventReplay
    public ResponseVO list(SysMenu menu) throws CustomException {
        try {
            if (StringUtils.isNotEmpty(menu.getMenuName())) {
                if (menu.getMenuName().length() > 50) {
                    return ResponseVO.fail("菜单名长度不能超过50个字符！");
                }
            }
            List<SysMenu> menus = sysMenuService.selectMenuList(menu, SecurityContextUtil.getSysUser().getId());
            return ResponseVO.success(menus);
        } catch (Exception e) {
            throw new CustomException("获取菜单列表异常", e);
        }
    }

    /**
     * 新增菜单
     */
    @PostMapping(value = "/addMenu")
    @OperateLog(title = "菜单管理", businessType = BusinessType.INSERT, auditType = AuditType.SYS,operdesc = "新增菜单")
    @PreAuthorize("@ss.hasPermi('system:menu:add')")
    @PreventReplay
    public ResponseVO addMenu(@RequestBody SysMenu menu) throws CustomException {
        try {
            if (RyStringUtils.isEmpty(menu.getMenuName()) || RyStringUtils.isEmpty(menu.getMenuName().trim())) {
                return ResponseVO.fail("菜单名称不能为空！");
            } else {
                String menuName = menu.getMenuName().trim();
                if (menuName.length() > 50) {
                    return ResponseVO.fail("菜单名长度不能超过50个字符！");
                }
            }

            if (!"F".equals(menu.getMenuType())) {
                if (RyStringUtils.isEmpty(menu.getPath()) || RyStringUtils.isEmpty(menu.getPath().trim())) {
                    return ResponseVO.fail("路由地址不能为空！");
                } else {
                    String routerPath = menu.getPath().trim();
                    if (routerPath.length() > 200) {
                        return ResponseVO.fail("路由地址长度不能超过200个字符！");
                    }
                }
            }
            if (menu.getOrderNum() == null) {
                return ResponseVO.fail("排序不能为空！");
            } else if (!NumberUtil.isInteger(menu.getOrderNum() + "")) {
                return ResponseVO.fail("排序不是整型数值！");
            }

            if (RyStringUtils.isNotEmpty(menu.getComponent())) {
                if (menu.getComponent().length() > 200) {
                    return ResponseVO.fail("组件路径长度不能超过200个字符！");
                }
            }

            if (RyStringUtils.isNotEmpty(menu.getQuery())) {
                if (menu.getQuery().length() > 200) {
                    return ResponseVO.fail("路由参数长度不能超过200个字符！");
                }
            }

            if (RyStringUtils.isNotEmpty(menu.getPerms())) {
                if (menu.getPerms().length() > 100) {
                    return ResponseVO.fail("权限字符长度不能超过100个字符！");
                }
            }
            if (UserConstants.NOT_UNIQUE.equals(sysMenuService.checkMenuNameUnique(menu))) {
                return ResponseVO.fail(menu.getMenuName() + "'失败，菜单名称已存在！");
            }
            if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !RyStringUtils.ishttp(menu.getPath())) {
                return ResponseVO.fail(menu.getMenuName() + "'失败，地址必须以http(s)://开头！");
            }
            menu.setCreateBy(SecurityContextUtil.getSysUser().getUsername());
            int bo = sysMenuService.insertMenu(menu);
            if (bo == 1) {
                return ResponseVO.success("添加菜单成功");
            } else {
                log.error("添加菜单失败");
                return ResponseVO.fail("添加菜单失败");
            }
        } catch (Exception e) {
            throw new CustomException("添加菜单异常", e);
        }
    }

    /**
     * 更新系统参数
     *
     * @param menu 参数
     * @return 执行结果
     */
    @PostMapping(value = "/updateMenu")
    @OperateLog(title = "菜单管理", businessType = BusinessType.UPDATE, auditType = AuditType.SYS,operdesc = "修改菜单")
    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
    @PreventReplay
    public ResponseVO updateMenu(@RequestBody SysMenu menu) throws CustomException {
        try {
            if (menu.getMenuId() == null) {
                return ResponseVO.fail("主键为空不能修改!");
            }

            String menuName = menu.getMenuName().trim();
            if (RyStringUtils.isEmpty(menuName)) {
                return ResponseVO.fail("菜单名称不能为空！");
            } else if (menuName.length() > 50) {
                return ResponseVO.fail("菜单名长度不能超过50个字符！");
            }

            if (!"F".equals(menu.getMenuType())) {
                String routerPath = menu.getPath().trim();
                if (RyStringUtils.isEmpty(routerPath)) {
                    return ResponseVO.fail("路由地址不能为空！");
                } else if (routerPath.length() > 200) {
                    return ResponseVO.fail("路由地址长度不能超过200个字符！");
                }
            }
            if (menu.getOrderNum() == null) {
                return ResponseVO.fail("排序不能为空！");
            } else if (!NumberUtil.isInteger(menu.getOrderNum() + "")) {
                return ResponseVO.fail("排序不是整型数值！");
            }

            if (RyStringUtils.isNotEmpty(menu.getComponent())) {
                if (menu.getComponent().length() > 200) {
                    return ResponseVO.fail("组件路径长度不能超过200个字符！");
                }
            }

            if (RyStringUtils.isNotEmpty(menu.getQuery())) {
                if (menu.getQuery().length() > 200) {
                    return ResponseVO.fail("路由参数长度不能超过200个字符！");
                }
            }

            if (RyStringUtils.isNotEmpty(menu.getPerms())) {
                if (menu.getPerms().length() > 100) {
                    return ResponseVO.fail("权限字符长度不能超过100个字符！");
                }
            }
            if (sysMenuService.selectMenuById(menu.getMenuId()) == null) {
                return ResponseVO.fail("非法访问不能修改！");
            }
            if (UserConstants.NOT_UNIQUE.equals(sysMenuService.checkMenuNameUnique(menu))) {
                return ResponseVO.fail("修改菜单'" + menu.getMenuName() + "'失败，菜单名称已存在！");
            } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !RyStringUtils.ishttp(menu.getPath())) {
                return ResponseVO.fail("修改菜单'" + menu.getMenuName() + "'失败，地址必须以http(s)://开头");
            } else if (menu.getMenuId().equals(menu.getParentId())) {
                return ResponseVO.fail("修改菜单'" + menu.getMenuName() + "'失败，上级菜单不能选择自己");
            }

            int bo = sysMenuService.updateMenu(menu);
            if (bo == 1) {
                return ResponseVO.success("修改菜单成功");
            } else {
                log.error("修改菜单失败");
                return ResponseVO.fail("修改菜单失败");
            }
        } catch (Exception e) {
            throw new CustomException("修改菜单异常", e);
        }
    }

    /**
     * 根据菜单编号获取详细信息
     */
    @GetMapping(value = "/{getDetailInfo}")
    @OperateLog(title = "菜单管理", businessType = BusinessType.QUERY, auditType = AuditType.SYS,operdesc = "获取菜单详细信息")
    @PreventReplay
    public ResponseVO getDetailInfo(String menuId) throws CustomException {
        try {
            Long menuid;
            if (StringUtils.isNotEmpty(menuId)) {
                if (NumberUtil.isLong(menuId)){
                    menuid = Long.parseLong(menuId);
                }
                else{
                    return ResponseVO.fail("菜单id不是类型不对！");
                }
            }
            else{
                return ResponseVO.fail("菜单id不能为空！");
            }
            SysMenu sysMenu = sysMenuService.selectMenuById(menuid);
            return ResponseVO.success(sysMenu);
        } catch (Exception e) {
            throw new CustomException("获取菜单明细异常", e);
        }
    }

    /**
     * 删除菜单信息
     */
    @PostMapping(value = "delMenu")
    @OperateLog(title = "菜单管理", businessType = BusinessType.DELETE, auditType = AuditType.SYS,operdesc = "删除菜单")
    @PreAuthorize("@ss.hasPermi('system:menu:remove')")
    @PreventReplay
    public ResponseVO delMenu(String menuId) throws CustomException {
        try {
            if (org.apache.commons.lang3.StringUtils.isEmpty(menuId)) {
                return ResponseVO.fail("删除菜单的id不能为空!");
            }
            if (sysMenuService.hasChildByMenuId(Long.parseLong(menuId))) {
                return ResponseVO.fail("存在子菜单,不允许删除");
            }

            if (sysMenuService.checkMenuExistRole(Long.parseLong(menuId))) {
                return ResponseVO.fail("菜单已分配,不允许删除");
            }
            int bo = sysMenuService.deleteMenuById(Long.parseLong(menuId));
            if (bo == 1) {
                return ResponseVO.success("删除菜单成功");
            } else {
                log.error("删除菜单失败");
                return ResponseVO.fail("删除菜单失败");
            }
        } catch (Exception e) {
            throw new CustomException("删除菜单异常", e);
        }
    }

    /**
     * 获取菜单下拉树列表
     */
    @GetMapping("/treeselect")
    @PreventReplay
    public ResponseVO treeselect(String pc) throws CustomException {
        try {
            SysMenu menu = new SysMenu();
//            menu.setPc(pc);
            // 查询出所有菜单
            List<SysMenu> menus = sysMenuService.selectMenuList(menu, SecurityContextUtil.getSysUser().getId());
            return ResponseVO.success(sysMenuService.buildMenuTreeSelect(menus,pc));
        } catch (Exception e) {
            throw new CustomException("获取菜单下拉树列表异常", e);
        }
    }

    /**
     * 加载对应角色菜单列表树
     */
    @GetMapping(value = "/roleMenuTreeselect")
    @OperateLog(title = "菜单管理", businessType = BusinessType.QUERY, auditType = AuditType.SYS,operdesc = "获取角色菜单列表")
    @PreventReplay
    public ResponseVO roleMenuTreeselect(String roleId) throws CustomException {
        try {
            Long roleid;
            if (StringUtils.isNotEmpty(roleId)) {
                if (NumberUtil.isLong(roleId)){
                    roleid = Long.parseLong(roleId);
                }
                else{
                    return ResponseVO.fail("角色id不是类型不对！");
                }
            }
            else{
                return ResponseVO.fail("角色id不能为空！");
            }
            SysRole sysRole = sysRoleService.selectRoleById(roleid);
            if (sysRole==null){
                return ResponseVO.fail("找不到角色不能查找角色关联树！");
            }

            List<SysMenu> menus = sysMenuService.selectMenuList(SecurityContextUtil.getSysUser().getId());
            Map<String, Object> map = new HashMap<>();
            map.put("checkedKeys", sysMenuService.selectMenuListByRoleId(roleid));
            map.put("menus", sysMenuService.buildMenuTreeSelect(menus,sysRole.getRoleKey()));
            return ResponseVO.success(map);
        } catch (Exception e) {
            throw new CustomException("获取对应角色菜单列表树异常", e);
        }
    }
    /**
     * 加载对应角色菜单列表树
     */
    @GetMapping(value = "/roleMenuTreeselectForUser")
    @OperateLog(title = "用户管理", businessType = BusinessType.QUERY, auditType = AuditType.SYS,operdesc = "获取角色菜单列表")
    @PreventReplay
    public ResponseVO roleMenuTreeselectForUser(String roleId) throws CustomException {
        try {
            Long roleid;
            if (StringUtils.isNotEmpty(roleId)) {
                if (NumberUtil.isLong(roleId)){
                    roleid = Long.parseLong(roleId);
                }
                else{
                    return ResponseVO.fail("角色id不是类型不对！");
                }
            }
            else{
                return ResponseVO.fail("角色id不能为空！");
            }
            SysRole sysRole = sysRoleService.selectRoleById(roleid);
            if (sysRole==null){
                return ResponseVO.fail("找不到角色不能查找角色关联树！");
            }

            List<SysMenu> menus = sysMenuService.selectMenuList(SecurityContextUtil.getSysUser().getId());
            Map<String, Object> map = new HashMap<>();
            map.put("checkedKeys", sysMenuService.selectMenuListByRoleId(roleid));
            // 将获取的菜单过滤出按钮级别
            List<SysMenu> notMenuTypeList = menus.stream().filter(menu -> !menu.getMenuType().equals("F")).collect(Collectors.toList());
            map.put("menus", sysMenuService.buildMenuTreeSelect(notMenuTypeList,sysRole.getRoleKey()));
            return ResponseVO.success(map);
        } catch (Exception e) {
            throw new CustomException("获取对应角色菜单列表树异常", e);
        }
    }
}
