package com.hs.admin.service.impl;

import com.hs.admin.common.enums.StateType;
import com.hs.admin.mapper.SysMenuMapper;
import com.hs.admin.mapper.SysRoleMenuRsMapper;
import com.hs.admin.mapper.SysUserMenuRsMapper;
import com.hs.admin.model.SysMenu;
import com.hs.admin.model.SysRoleMenuRs;
import com.hs.admin.model.SysUserMenuRs;
import com.hs.admin.model.reqmodel.MenuReq;
import com.hs.admin.model.respmodel.SysMenuList;
import com.hs.admin.model.respmodel.SysRoleMenuRsList;
import com.hs.admin.model.respmodel.SysUserMenuRsList;
import com.hs.admin.service.SysMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl implements SysMenuService {

    @Resource
    private SysMenuMapper sysMenuMapper;
    @Resource
    private SysUserMenuRsMapper sysUserMenuRsMapper;
    @Resource
    private SysRoleMenuRsMapper sysRoleMenuRsMapper;

    @Override
    public List<SysMenuList> getMenu(Integer userId) throws Exception {
        List<SysMenuList> userList = sysMenuMapper.selectMenuAllByUser(userId);
        List<SysMenuList> roleList = sysMenuMapper.selectMenuByRole(userId);

        List<SysMenuList> userRoleList = new ArrayList<>();

        for(SysMenuList roleMenu : roleList){
            userRoleList.add(roleMenu);
            for(SysMenuList userMenu : userList){
                int userMuenuState = userMenu.getState().intValue();
                if(userMenu.getId().equals(roleMenu.getId()) && userMuenuState == StateType.OFF.getValue()){
                    //角色表存在，用户表存在，但是已删除  =  不显示
                    userRoleList.remove(roleMenu);
                }else if(userMenu.getId().equals(roleMenu.getId()) && userMuenuState == StateType.ON.getValue()){
                    //角色表存在，用户表存在，未删除  =  显示
                    continue;
                }else if(!userMenu.getId().equals(roleMenu.getId()) && userMuenuState == StateType.ON.getValue()){
                    userRoleList.add(userMenu);
                }
            }
        }

        userRoleList = userRoleList.stream().distinct().collect(Collectors.toList());

        List<SysMenuList> resultList = getLevelData(userRoleList,Long.valueOf(MENU_TOP_PARENT_ID));
        resultList = resultList.stream().sorted(Comparator.comparing(SysMenu::getSort)).collect(Collectors.toList());
        return resultList;
    }

    private List<SysMenuList> getLevelData(List<SysMenuList> list,Long parentcode) {
        List<SysMenuList> resultList = new ArrayList<>();
        for(SysMenuList data : list){
            if(data.getParentId() == parentcode){
                List<SysMenuList> childList = getLevelData(list,Long.valueOf(data.getId()));
                childList = childList.stream().sorted(Comparator.comparing(SysMenu::getSort)).collect(Collectors.toList());
                data.setSysMenuList(childList);
                resultList.add(data);
            }
        }
        return resultList;
    }

    @Override
    public List<SysMenuList> getParentAll(MenuReq.GetMenuReq menu) {
        List<SysMenuList> list = sysMenuMapper.selectParentAll();
        if(menu.getMenuName() != null){
            list = list.stream().filter(
                    o -> (o.getMenuName() != null && o.getMenuName().toLowerCase().contains(menu.getMenuName().toLowerCase())))
                    .collect(Collectors.toList());
        }
        List<SysMenuList> resultList = getLevelData(list,Long.valueOf(MENU_TOP_PARENT_ID));
        resultList = resultList.stream().sorted(Comparator.comparing(SysMenu::getSort)).collect(Collectors.toList());
        return resultList;
    }

    public List<SysMenu> getAll() {
        List<SysMenu> list = sysMenuMapper.selectAll();
        return list;
    }


    @Override
    public SysMenu info(MenuReq.InfoMenuReq menu) {
        SysMenu sysMenu = sysMenuMapper.selectByPrimaryKey(menu.getMenuId());
        return sysMenu;
    }

    @Override
    public boolean addMenu(Long userId,MenuReq.AddMenuReq menu) {
        if(menu != null){
            SysMenu sysMenu = new SysMenu();
            sysMenu.setCreateData(new Date());
            sysMenu.setCreateUserid(userId);
            sysMenu.setState((short)StateType.ON.getValue());
            sysMenu.setMenuName(menu.getMenuName());
            sysMenu.setMenuUrl(menu.getMenuUrl());
            sysMenu.setMenuImage(menu.getMenuImage());
            sysMenu.setPageCode(menu.getPageCode());
            sysMenu.setParentId(menu.getParentId());
            sysMenu.setSort((long)sysMenuMapper.selectMaxSort(menu.getParentId()));
            sysMenuMapper.insert(sysMenu);
            return true;
        }
        return false;
    }

    @Override
    public boolean deleteMenu(MenuReq.DeleteMenuReq menu) {
        if(menu != null){
            SysMenu sysMenu = sysMenuMapper.selectByPrimaryKey(menu.getMenuId());
            if(sysMenu != null){
                sysMenu.setState((short)StateType.OFF.getValue());
                sysMenuMapper.updateByPrimaryKey(sysMenu);
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean updateMenu(MenuReq.UpdateMenuReq menu) {
        if(menu != null){
            SysMenu sysMenu = sysMenuMapper.selectByPrimaryKey(menu.getMenuId());
            if(sysMenu != null){
                sysMenu.setMenuName(menu.getMenuName());
                sysMenu.setMenuUrl(menu.getMenuUrl());
                sysMenu.setMenuImage(menu.getMenuImage());
                sysMenu.setPageCode(menu.getPageCode());
                sysMenu.setParentId(menu.getParentId());
                sysMenuMapper.updateByPrimaryKey(sysMenu);
                return true;
            }
        }
        return false;
    }


    /**
     * 查询用户菜单关系
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public List<SysUserMenuRsList> getUserMenu(Integer userId) {
        List<SysUserMenuRsList> list = sysUserMenuRsMapper.selectByUser(userId);
        return list;
    }

    /**
     * 用户配置菜单
     *
     * @param userId 操作人ID
     * @param menu 用户菜单关系数据
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveUserMenu(Long userId,MenuReq.SaveUserMenuReq menu) {
        int result = 0;
        if(menu != null && menu.getMenus() != null && menu.getMenus().size() > 0 && menu.getUserId() != null){
            sysUserMenuRsMapper.deleteAllByUser(menu.getUserId());
            for(Long menuId : menu.getMenus()){
                SysUserMenuRs um = sysUserMenuRsMapper.selectByUserWithMenu(menu.getUserId(),menuId);
                if(um != null){
                    um.setState((short)StateType.ON.getValue());
                    result += sysUserMenuRsMapper.updateByPrimaryKey(um);
                }else{
                    um = new SysUserMenuRs();
                    um.setCreateDate(new Date());
                    um.setState((short)StateType.ON.getValue());
                    um.setCreateUserid(userId);
                    um.setUserId(menu.getUserId());
                    um.setMenuId(menuId);
                    result += sysUserMenuRsMapper.insert(um);
                }
            }
        }
        return result > 0;
    }

    /**
     * 查询角色菜单关系
     *
     * @param roleId 角色ID
     * @return
     */
    @Override
    public List<SysRoleMenuRsList> getRoleMenu(Integer roleId) {
        List<SysRoleMenuRsList> list = sysRoleMenuRsMapper.selectByRole(roleId);
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveRoleMenu(Long userId,MenuReq.SaveRoleMenuReq menu) {
        int result = 0;
        if(menu != null && menu.getMenus() != null && menu.getMenus().size() > 0 && menu.getRoleId() != null){
            sysRoleMenuRsMapper.deleteAllByRole(menu.getRoleId());
            for(Long menuId : menu.getMenus()){
                SysRoleMenuRs rm = sysRoleMenuRsMapper.selectByUserWithRole(menu.getRoleId(),menuId);
                if(rm != null){
                    rm.setState((short)StateType.ON.getValue());
                    result += sysRoleMenuRsMapper.updateByPrimaryKey(rm);
                }else{
                    rm = new SysRoleMenuRs();
                    rm.setCreateDate(new Date());
                    rm.setState((short)StateType.ON.getValue());
                    rm.setCreateUserid(userId);
                    rm.setRoleId(menu.getRoleId());
                    rm.setMenuId(menuId);
                    result += sysRoleMenuRsMapper.insert(rm);
                }
            }
        }
        return result > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateSort(Long userId,MenuReq.UpdateSortReq menu) {
        int result = 0;
        if(menu != null && menu.getMenus() != null && menu.getMenus().size() > 0){
            for(SysMenu info : menu.getMenus()){
                SysMenu sysMenu = sysMenuMapper.selectByPrimaryKey(info.getId());
                sysMenu.setParentId(info.getParentId());
                sysMenu.setSort(info.getSort());
                result += sysMenuMapper.updateByPrimaryKey(sysMenu);
            }
        }
        return result > 0;
    }
}
