package com.chinaweal.aiccs.org.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chinaweal.aiccs.common.base.controller.BaseController;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.org.entity.SysMenu;
import com.chinaweal.aiccs.org.entity.TUsermenu;
import com.chinaweal.aiccs.org.entity.dto.UserMenusDto;
import com.chinaweal.aiccs.org.service.SysMenuService;
import com.chinaweal.aiccs.org.service.TUsermenuService;
import com.chinaweal.aicorg.model.AICUser;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.util.AssertUtils;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Lee
 * @since 2021-06-21
 */
@RestController
@RequestMapping("/tUsermenu")
public class TUsermenuController extends BaseController {

    @Autowired
    private TUsermenuService tUsermenuService;
    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 通过用户id获取用户权限
     *
     * @param request
     * @param userId  用户id
     * @return
     */
    @ApiOperation("获取用户权限")
    @PostMapping("getUserRights")
    public RestResult<?> getUserRights(HttpServletRequest request, String userId) {
        AssertUtils.isNotBlank(userId);
        AICUser loginUser = getLoginUser(request);
        if (userId.equals(loginUser.getPrimaryKey())) {
            // 获取用户所有sysMenuId
            LambdaQueryWrapper<TUsermenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TUsermenu::getUserID, userId);
            List<TUsermenu> usermenus = tUsermenuService.list(wrapper);
            if (CollectionUtils.isEmpty(usermenus)) {
                return RestResult.error(ResultCode.DATA_NONE, "该用户未配置权限");
            }
            ArrayList<String> sysMenuIds = new ArrayList<>();
            for (TUsermenu usermenu : usermenus) {
                sysMenuIds.add(usermenu.getSysMenuID());
            }
            // 到sys_menu表查出所拥有权限
            LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(SysMenu::getSysMenuID, sysMenuIds).isNotNull(SysMenu::getResourceURL).orderByAsc(SysMenu::getOrgLevel);
            List<SysMenu> sysMenus = sysMenuService.list(queryWrapper);
            Iterator<SysMenu> iterator = sysMenus.iterator();
            while (iterator.hasNext()) {
                SysMenu next = iterator.next();
                if (StringUtils.isEmpty(next.getResourceURL())) {
                    iterator.remove();
                }
            }
            ArrayList<UserMenusDto> userMenus = new ArrayList<>();
            for (SysMenu sysMenu : sysMenus) {
                formatMenu(userMenus, sysMenu);
            }
            if (userMenus.size() > 1) {// 进行排序
//                Collections.sort(userMenus);
//                for (UserMenusDto userMenu : userMenus) {
//                    if(CollectionUtils.isNotEmpty(userMenu.getChildren()) && userMenu.getChildren().size()>1){
//                        Collections.sort(userMenu.getChildren());
//                    }
//                }
                userMenus = (ArrayList<UserMenusDto>) menuSort(userMenus);
                return RestResult.ok(userMenus);
            }
            if (userMenus.size() > 0) {
                return RestResult.ok(userMenus);
            } else {
                return RestResult.error(ResultCode.DATA_NONE, "该用户未配置权限");
            }
        }
        return RestResult.error(ResultCode.PARAM_IS_INVALID);

    }

    /**
     * 构建菜单列表
     *
     * @param userMenus
     * @param sysMenu
     * @return
     */
    private List<UserMenusDto> formatMenu(List<UserMenusDto> userMenus, SysMenu sysMenu) {
        if (StringUtils.isNotBlank(sysMenu.getParentID())) {
            // 先到userMenus添加上 看能否添加成功
            UserMenusDto userMenusDto = transfer(sysMenu);
            boolean isAdd = addtoMenuList(userMenus, userMenusDto);
            if (!isAdd) {
                SysMenu parentMenu = sysMenuService.getOne(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getSysMenuID, sysMenu.getParentID()));
                formatMenu(userMenus, parentMenu);
                addtoMenuList(userMenus, userMenusDto);
                return userMenus;
            }
        } else {// sysMenu为父节点
            boolean isExist = false;
            if (userMenus.size() > 0) {
                for (UserMenusDto userMenu : userMenus) {
                    if (userMenu.getSysMenuId().equals(sysMenu.getSysMenuID())) {
                        isExist = true;
                        break;
                    }
                }
            }
            if (!isExist) {
                UserMenusDto userMenusDto = transfer(sysMenu);
                userMenus.add(userMenusDto);//加入到菜单列表
            }
        }
        return userMenus;

    }

    /**
     * 往菜单列表添加菜单
     *
     * @param userMenus
     * @param userMenu
     * @return
     */
    private boolean addtoMenuList(List<UserMenusDto> userMenus, UserMenusDto userMenu) {
        boolean isAdd = false;
        if (userMenus.size() > 0) {
            for (UserMenusDto menu : userMenus) {
                if (menu.getSysMenuId().equals(userMenu.getPid())) {
                    if (StringUtils.isNotEmpty(userMenu.getPath())) {
                        menu.getChildren().add(userMenu);
                    }
                    isAdd = true;
                    break;
                } else if (CollectionUtils.isNotEmpty(menu.getChildren())) {
                    isAdd = addtoMenuList(menu.getChildren(), userMenu);
                    if (isAdd) break;
                }
            }
        }
        return isAdd;
    }

    /**
     * 将权限菜单结构转为对应前端路由数据结构
     *
     * @param sysMenu
     * @return
     */
    private UserMenusDto transfer(SysMenu sysMenu) {
        if (sysMenu != null) {
            UserMenusDto userMenusDto = new UserMenusDto();
            userMenusDto.setPid(sysMenu.getParentID());
            userMenusDto.setSysMenuId(sysMenu.getSysMenuID());
            userMenusDto.setTitle(sysMenu.getSysMenuName());
            userMenusDto.setPath(sysMenu.getResourceURL());
            userMenusDto.setLevel(sysMenu.getOrgLevel());
            userMenusDto.setChildren(new ArrayList<UserMenusDto>());
            if (StringUtils.isNotEmpty(sysMenu.getRemark()) && StringUtils.isNumeric(sysMenu.getRemark())) {
                userMenusDto.setNo(Integer.valueOf(sysMenu.getRemark()));
            } else {
                userMenusDto.setNo(0);
            }
            return userMenusDto;
        }
        return null;
    }

    private List<UserMenusDto> menuSort(List<UserMenusDto> menus) {
        if (CollectionUtils.isEmpty(menus)) return null;
        Collections.sort(menus);
        for (UserMenusDto menu : menus) {
            List<UserMenusDto> sort = menuSort(menu.getChildren());
            if (sort == null) {
                continue;
            }
            menu.setChildren(sort);
        }
        return menus;
    }

    /**
     * 通过用户id获取用户菜单权限
     *
     * @param userId 用户id
     * @return
     */
    @ApiOperation("获取用户权限")
    @PostMapping("/getUserMenus")
    public RestResult<?> getUserMenu(HttpServletRequest request, String userId) {
        AssertUtils.isNotBlank(userId);
        AICUser loginUser = getLoginUser(request);
        if (userId.equals(loginUser.getPrimaryKey())) {
            // 获取用户所有sysMenuId
            LambdaQueryWrapper<TUsermenu> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(TUsermenu::getUserID, userId);
            List<TUsermenu> usermenus = tUsermenuService.list(wrapper);
            if (CollectionUtils.isEmpty(usermenus)) {
                return RestResult.ok(new ArrayList<>());
            }
            List<String> sysMenuIds = usermenus.stream().map(TUsermenu::getSysMenuID).collect(Collectors.toList());
            // 到sys_menu表查出所拥有权限
            LambdaQueryWrapper<SysMenu> sysLqw = Wrappers.lambdaQuery();
            sysLqw.in(SysMenu::getSysMenuID, sysMenuIds).orderByAsc(SysMenu::getOrgLevel, SysMenu::getSysIndex);
            List<SysMenu> sysMenus = sysMenuService.list(sysLqw);
            //递归加载父菜单的数据
            findParent(sysMenus);
            List<UserMenusDto> userMenus = new ArrayList<>();
            for (SysMenu sysMenu : sysMenus) {
                userMenus.add(transfer(sysMenu));
            }
            //进行组装层级
            return RestResult.ok(assemble(userMenus));
        } else {
            return RestResult.error(ResultCode.DATA_NONE, "该用户未配置权限");
        }
    }

    /**
     * 组装菜单层级
     *
     * @param list
     * @return
     */
    private List<UserMenusDto> assemble(List<UserMenusDto> list) {
        //获取第一级
        List<UserMenusDto> oneList = list.stream().filter(item -> item.getLevel() == 1).collect(Collectors.toList());
        for (UserMenusDto userMenusDto : oneList) {
            userMenusDto.setChildren(findChildren(userMenusDto, list));
        }
        menuSort(oneList);
        return oneList;
    }

    /**
     * 获取子级菜单
     */
    private List<UserMenusDto> findChildren(UserMenusDto userMenusDto, List<UserMenusDto> dbList) {
        List<UserMenusDto> children = dbList.stream()
                .filter(item -> (StringUtils.equals(item.getPid(), userMenusDto.getSysMenuId()) && StringUtils.isNotBlank(item.getPath())))
                .collect(Collectors.toList());
        for (UserMenusDto child : children) {
            child.setChildren(findChildren(child, dbList));
        }
        return children;
    }

    /**
     * 递归查询父级所有元素，返回结果集是并列
     */
    private void findParent(List<SysMenu> list) {
        List<SysMenu> ergodicList = new ArrayList<>(list);
        for (SysMenu sysMenu : ergodicList) {
            //判断是否遍历过了，跳出
            if (sysMenu.isFindParent()) {
                continue;
            }
            //记录本次已经查过上一级父级
            sysMenu.setFindParent(true);
            //判断所在的上一级父级是不是在已有的集合列表上
            boolean b = list.stream().anyMatch(item -> item.getSysMenuID().equals(sysMenu.getParentID()));
            if (b) {
                continue;  //存在跳出
            }
            if (StringUtils.isNotBlank(sysMenu.getParentID())) {
                SysMenu pSysMenu = sysMenuService.getById(sysMenu.getParentID());
                if (pSysMenu != null) {
                    list.add(pSysMenu);
                }
            }
        }
        //判断是否查询完全
        boolean notFinished = list.stream().anyMatch(item -> !item.isFindParent());
        if (notFinished) {
            findParent(list);
        }
    }

}

