package com.muchinfo.mtp3century.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.muchinfo.mtp3century.service.ICommonService;
import com.muchinfo.mtp3century.service.IFuncmenulistService;
import com.muchinfo.mtp3century.vo.TreeNode;
import com.muchinfo.mtp3common.enumtype.Constants;
import com.muchinfo.mtp3common.enumtype.MessageType;
import com.muchinfo.mtp3common.enumtype.SysConstantsEnum;
import com.muchinfo.mtp3century.utils.AjaxResult;
import com.muchinfo.mtp3interface.mapper.IFuncmenulistMapper;
import com.muchinfo.mtp3interface.mapper.IRolefuncmenuMapper;
import com.muchinfo.mtp3interface.mapper.ISystemmanagerMapper;
import com.muchinfo.mtp3pojos.entity.Funcmenulist;
import com.muchinfo.mtp3pojos.entity.Rolefuncmenu;
import com.muchinfo.mtp3pojos.entity.Systemmanager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * <p>
 * 功能菜单表 服务实现类
 * </p>
 *
 * @author XKF
 * @since 2024-04-10
 */
@Service
public class FuncmenulistServiceImpl extends ServiceImpl<IFuncmenulistMapper, Funcmenulist> implements IFuncmenulistService {

    @Resource
    private IFuncmenulistMapper iFuncmenulistMapper;
    @Resource
    private IRolefuncmenuMapper iRolefuncmenuMapper;
    @Resource
    private ISystemmanagerMapper iSystemmanagerMapper;
    @Resource
    private ICommonService iCommonService;


    @Override
    public List<TreeNode> fingByAuthorities(List<String> stringList, Integer sysType) {
        List<Funcmenulist> funcmenulists = iFuncmenulistMapper.fingByAuthorities(stringList, sysType);
        return changeMenuToTreeNode(funcmenulists);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult dealMenus(TreeNode treeNode, HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));

        //处理菜单数据，存在修改，不存在新增
        Funcmenulist currentFuncmenulist = iFuncmenulistMapper.selectOne(new QueryWrapper<Funcmenulist>().eq("RESOURCECODE", treeNode.getResourceCode()));
        if (Objects.isNull(currentFuncmenulist)) {
            Funcmenulist funcmenulist = Funcmenulist.builder()
                    .resourcecode(treeNode.getResourceCode())
                    .parentcode(treeNode.getParentCode())
                    .url(treeNode.getUrl())
                    .authtype(treeNode.getAuthType())
                    .remark(treeNode.getRemark())
                    .urltype(treeNode.getUrlType())
                    .iconame(treeNode.getIcon())
                    .resourcename(treeNode.getTitle())
                    .component(treeNode.getComponent())
                    .sort(treeNode.getSort())
                    .buttontype(treeNode.getClassName())
                    .hidden(treeNode.getShow())
                    .menutype(SysConstantsEnum.SYS_TYPE_MANAGE_NEW.getCode())
                    .build();
            iFuncmenulistMapper.insert(funcmenulist);

            //新增菜单权限
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            for (GrantedAuthority authority : authorities) {
                Rolefuncmenu rolefuncmenu = Rolefuncmenu.builder()
                        .roleid(Long.parseLong(authority.getAuthority()))
                        .resourcecode(treeNode.getResourceCode())
                        .build();
                iRolefuncmenuMapper.insert(rolefuncmenu);

                if (systemmanager.getReletype() != 1) {
                    Rolefuncmenu current = Rolefuncmenu.builder()
                            .roleid(1L)
                            .resourcecode(treeNode.getResourceCode())
                            .build();
                    iRolefuncmenuMapper.insert(current);
                }
            }
        } else {
            currentFuncmenulist.setResourcename(treeNode.getTitle());
            currentFuncmenulist.setMenutype(SysConstantsEnum.SYS_TYPE_MANAGE_NEW.getCode());
            currentFuncmenulist.setParentcode(treeNode.getParentCode());
            currentFuncmenulist.setUrl(treeNode.getUrl());
            currentFuncmenulist.setIconame(treeNode.getIcon());
            currentFuncmenulist.setComponent(treeNode.getComponent());
            currentFuncmenulist.setUrltype(treeNode.getUrlType());
            currentFuncmenulist.setSort(treeNode.getSort());
            currentFuncmenulist.setButtontype(treeNode.getClassName());
            currentFuncmenulist.setAuthtype(treeNode.getAuthType());
            currentFuncmenulist.setRemark(treeNode.getRemark());
            currentFuncmenulist.setHidden(treeNode.getShow());
            iFuncmenulistMapper.update(currentFuncmenulist, new QueryWrapper<Funcmenulist>().eq("RESOURCECODE", currentFuncmenulist.getResourcecode()));
        }
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteMenus(TreeNode treeNode, HttpServletRequest request) {
        deleteAllMenus(treeNode);
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
    }

    @Override
    public List<TreeNode> menuAllList(Integer menuType) {
        List<Funcmenulist> funcmenulists = iFuncmenulistMapper.selectList(new QueryWrapper<Funcmenulist>()
                .eq("MENUTYPE", menuType)
                .eq("hidden", 1)
                .orderBy(true, true, "sort"));
        return changeMenuToTreeNode(funcmenulists);
    }

    private void deleteAllMenus(TreeNode treeNode) {
        iFuncmenulistMapper.delete(new QueryWrapper<Funcmenulist>().eq("RESOURCECODE", treeNode.getResourceCode()));
        //删除对应权限
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            iRolefuncmenuMapper.delete(new QueryWrapper<Rolefuncmenu>()
                    .eq("ROLEID", Long.parseLong(authority.getAuthority()))
                    .eq("RESOURCECODE", treeNode.getResourceCode()));
        }

        List<Funcmenulist> funcmenulist = iFuncmenulistMapper.selectList(new QueryWrapper<Funcmenulist>().eq("PARENTCODE", treeNode.getResourceCode()));
        if (!CollectionUtils.isEmpty(funcmenulist)) {
            funcmenulist.forEach(a -> {
                deleteAllMenus(TreeNode.builder().resourceCode(a.getResourcecode()).build());
            });
        }
    }

    public List<TreeNode> changeMenuToTreeNode(List<Funcmenulist> menus) {
        List<TreeNode> node = new ArrayList<>();
        if (menus == null || menus.isEmpty()) {
            return node;
        }
        Map<String, List<Funcmenulist>> treeMap = new HashMap<String, List<Funcmenulist>>();
        for (Funcmenulist menu : menus) {
            //一级菜单
            if (menu.getParentcode() == null || menu.getParentcode().trim().isEmpty()) {
                //开始存入
                if (treeMap.containsKey("0")) {
                    treeMap.get("0").add(menu);
                } else {
                    List<Funcmenulist> temp = new ArrayList<>();
                    temp.add(menu);
                    treeMap.put("0", temp);
                }
            } else {
                //二级菜单
                if (treeMap.containsKey(menu.getParentcode())) {
                    treeMap.get(menu.getParentcode()).add(menu);
                } else {
                    List<Funcmenulist> temp = new ArrayList<>();
                    temp.add(menu);
                    treeMap.put(menu.getParentcode(), temp);
                }
            }
        }
        //一级菜单
        List<Funcmenulist> first = treeMap.get("0");
        TreeNode node_ = null;
        if (first != null && !first.isEmpty()) {
            for (Funcmenulist menu_ : first) {
                //设置一级菜单
                node_ = initTreeNode(menu_);
                //设置一级菜单以下的所有菜单
                loadChild(treeMap, node_);
                //添加菜单
                if (node_.getChildren() != null && !node_.getChildren().isEmpty()) {
                    node.add(node_);
                } else if (StringUtils.isEmpty(node_.getParentCode())) {
                    node.add(node_);
                }
            }
        }

        return node;
    }

    private TreeNode initTreeNode(Funcmenulist menu) {
        TreeNode node = new TreeNode();
        node.setResourceCode(menu.getResourcecode());
        node.setParentCode(Optional.ofNullable(menu.getParentcode()).orElse(""));
        node.setAuthType(menu.getAuthtype());
        node.setTitle(menu.getResourcename());
        node.setUrlType(menu.getUrltype());
        node.setUrl(menu.getUrl());
        node.setIcon(menu.getIconame());
        node.setSort(menu.getSort());
        node.setShow(menu.getHidden());
        node.setRemark(Optional.ofNullable(menu.getRemark()).orElse(""));
        node.setComponent(menu.getComponent());
        node.setClassName(Optional.ofNullable(menu.getButtontype()).orElse(""));
        return node;
    }

    /**
     * 迭代子节点
     */
    private void loadChild(Map<String, List<Funcmenulist>> map, TreeNode parent) {
        String parentid = parent.getResourceCode();
        if (parentid == null) {
            return;
        }
        List<TreeNode> nodechilds = new ArrayList<TreeNode>();
        if (map.containsKey(parentid)) {
            //设置二级菜单
            List<Funcmenulist> list = map.get(parentid);
            for (Funcmenulist menu : list) {
                TreeNode node = initTreeNode(menu);
                //设置三级菜单
                loadChild(map, node);
                nodechilds.add(node);
            }
            parent.setChildren(nodechilds);
        } else {
            parent.setChildren(new ArrayList<>());
        }
    }

}
