package com.crunii.micro.service.sysmgr.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.crunii.micro.common.exception.BusinessException;
import com.crunii.micro.domain.entity.main.TsmMenu;
import com.crunii.micro.domain.entity.main.YcqMenuShortcut;
import com.crunii.micro.domain.repo.main.YcqMenuShortcutRepo;
import com.crunii.micro.service.sysmgr.dto.sysmgr.MenuShortcutTreeVO;
import com.crunii.micro.service.sysmgr.dto.sysmgr.MenuShortcutVO;
import com.crunii.micro.service.sysmgr.jdbc.YcqMenuShortcutJdbcDao;
import com.crunii.micro.service.sysmgr.service.YcqMenuShortcutService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 15294
 */
@Slf4j
@Service
public class YcqMenuShortcutServiceImpl implements YcqMenuShortcutService {

    @Resource
    private YcqMenuShortcutJdbcDao dao;

    @Resource
    private YcqMenuShortcutRepo repo;


    @Override
    public List<MenuShortcutTreeVO> queryUnselectedMenu(Integer loginId){
        List<TsmMenu> ycqMenuShortcuts = dao.queryUnselectedMenu(loginId);
        List<MenuShortcutTreeVO> list = new ArrayList<>(ycqMenuShortcuts.size());
        ycqMenuShortcuts.forEach(item -> {
            MenuShortcutTreeVO menuShortcutTreeVO = new MenuShortcutTreeVO();
            BeanUtils.copyProperties(item, menuShortcutTreeVO);
            list.add(menuShortcutTreeVO);
        });
        // 建树返回,只返回最顶级和叶子节点，中间层级全部去掉
        Map<String, MenuShortcutTreeVO> map = list.stream().collect(Collectors.toMap(MenuShortcutTreeVO::getMenuCode, Function.identity()));

        // 查询顶层节点列表
        List<MenuShortcutTreeVO> topList = list.stream()
                .filter(item -> Objects.equals(item.getParentMenuCode(), "1") && Objects.equals(item.getMenuType(), 0))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(topList)){
            log.error("当前用户：{} 查询到的顶级菜单节点数据有误：[{}]", loginId, JSONObject.toJSONString(list));
            throw new BusinessException("数据有误");
        }
        Iterator<MenuShortcutTreeVO> iterator = topList.iterator();
        while (iterator.hasNext()){
            MenuShortcutTreeVO menuShortcutTreeVO = iterator.next();
            List<MenuShortcutTreeVO> childList = new ArrayList<>();
            this.findLeafNodes(menuShortcutTreeVO, map, childList);
            if (CollectionUtils.isEmpty(childList)){
                iterator.remove();
            }else {
                menuShortcutTreeVO.setChildren(childList);
            }
        }
        return topList;
    }

    @Override
    public List<MenuShortcutTreeVO> querySelectedMenu(Integer loginId){
        List<TsmMenu> menuList = dao.querySelectedMenu(loginId);
        List<MenuShortcutTreeVO> list = new ArrayList<>(menuList.size());
        menuList.forEach(item -> {
            MenuShortcutTreeVO menuShortcutTreeVO = new MenuShortcutTreeVO();
            BeanUtils.copyProperties(item, menuShortcutTreeVO);
            list.add(menuShortcutTreeVO);
        });
        // 建树返回,只返回最顶级和叶子节点，中间层级全部去掉
        Map<String, MenuShortcutTreeVO> map = list.stream().collect(Collectors.toMap(MenuShortcutTreeVO::getMenuCode, Function.identity()));

        // 查询顶层节点列表
        List<MenuShortcutTreeVO> topList = list.stream()
                .filter(item -> Objects.equals(item.getParentMenuCode(), "1") && Objects.equals(item.getMenuType(), 0))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(topList)){
            log.error("当前用户：{} 查询到的顶级菜单节点数据有误：[{}]", loginId, JSONObject.toJSONString(list));
            throw new BusinessException("数据有误");
        }
        Iterator<MenuShortcutTreeVO> iterator = topList.iterator();
        while (iterator.hasNext()){
            MenuShortcutTreeVO menuShortcutTreeVO = iterator.next();
            List<MenuShortcutTreeVO> childList = new ArrayList<>();
            this.findLeafNodes(menuShortcutTreeVO, map, childList);
            menuShortcutTreeVO.setChildren(childList);
        }
        return topList;
    }

    @Transactional
    @Override
    public Boolean insertBatch(List<String> menuCodeList, Integer loginId){
        // 删除所有 并重新插入数据
        dao.deleteByLoginId(loginId);
        if (!CollectionUtils.isEmpty(menuCodeList)){
            List<YcqMenuShortcut> addList = new ArrayList<>(menuCodeList.size());
            HashSet<String> strings = new HashSet<>(menuCodeList);
            strings.forEach(item -> {
                YcqMenuShortcut ycqMenuShortcut = new YcqMenuShortcut();
                ycqMenuShortcut.setMenuCode(item);
                ycqMenuShortcut.setLoginId(loginId);
                ycqMenuShortcut.setCreateTime(new Date());
                addList.add(ycqMenuShortcut);
            });
            repo.saveAll(addList);
        }
        return true;
    }

    @Override
    public Boolean deleteBatch(List<String> menucodeList, Integer loginId) {
        if (CollectionUtils.isEmpty(menucodeList)){
            return true;
        }
        return dao.deleteBatch(menucodeList, loginId);
    }

    @Override
    public List<MenuShortcutVO> querySelectedMenuList(Integer loginId) {
        List<MenuShortcutVO> result = new ArrayList<>();
        List<TsmMenu> menuList = dao.querySelectedMenuWithoutTop(loginId);
        menuList.forEach(item -> {
            MenuShortcutVO menuShortcutVO = new MenuShortcutVO();
            BeanUtils.copyProperties(item, menuShortcutVO);
            result.add(menuShortcutVO);
        });
        return result;
    }

    public void findLeafNodes(MenuShortcutTreeVO currentNode, Map<String, MenuShortcutTreeVO> nodeMap, List<MenuShortcutTreeVO> childList) {
        for (MenuShortcutTreeVO node : nodeMap.values()) {
            if (Objects.equals(currentNode.getMenuCode(), node.getParentMenuCode()) && Objects.equals(node.getMenuType(), 1)) {
                MenuShortcutTreeVO menuShortcutTreeVO = new MenuShortcutTreeVO();
                BeanUtils.copyProperties(node, menuShortcutTreeVO);
                menuShortcutTreeVO.setParentMenuName(currentNode.getMenuName());
                childList.add(menuShortcutTreeVO);
            }
            if (Objects.equals(currentNode.getMenuCode(), node.getParentMenuCode()) && Objects.equals(node.getMenuType(), 0)){
                findLeafNodes(node, nodeMap, childList);
            }
        }
    }
}
