package thyyxxk.webserver.service.settings;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.settings.MenuSettingsDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.settings.IntergrationMenu;
import thyyxxk.webserver.entity.settings.IntergrationPlatformRoleMenu;
import thyyxxk.webserver.service.hutoolcache.CacheEnums;
import thyyxxk.webserver.service.hutoolcache.ExtraCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.TokenUtil;
import thyyxxk.webserver.utils.TreeUtil;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class MenuSettingsService {
    private final MenuSettingsDao dao;
    private final UserCache cache;
    private final ExtraCache extraCache;

    public void menuPushRedis() {
        extraCache.put(CacheEnums.MENU.getName(), dao.getAll());
    }

    public List<IntergrationMenu> getMenuSettings() {
        return menuListByTree(dao.getAll());
    }

    public List<IntergrationMenu> getUserMenu() {
        return getRedisMenuByCodeTree(TokenUtil.getInstance().getTokenUserId());
    }

    private List<IntergrationMenu> menuListByTree(List<IntergrationMenu> list) {
        List<IntergrationMenu> res = TreeUtil.objectTree(list, (parent, child) -> {
            if (parent == null) {
                child.setCompletePath(child.getPath());
            } else {
                child.getCascaders().addAll(parent.getCascaders());
                child.getCascaders().add(child.getParentId());
                child.setCompletePath(parent.getCompletePath() + "/" + child.getPath());
            }
        });
        return TreeUtil.objectSort(res, "sort");
    }

    private List<IntergrationMenu> findParentMenus(List<IntergrationMenu> list, IntergrationMenu item) {
        List<IntergrationMenu> result = new ArrayList<>();
        for (IntergrationMenu menu : list) {
            if (menu.getId().equals(item.getParentId())) {
                result.add(menu);
                if (menu.getParentId() != null) {
                    result.addAll(findParentMenus(list, menu));
                }
                return result;
            }
        }
        return result;
    }

    private List<IntergrationMenu> getRedisMenuByCodeTree(String code) {
        return menuListByTree(getRedisMenuByCode(code));
    }

    public Set<String> getRedisMenuByCodeListName() {
        return getRedisMenuByCodeListName(TokenUtil.getInstance().getTokenUserId());
    }

    public Set<String> getRedisMenuByCodeListName(String code) {
        List<IntergrationMenu> redisMenuByCode = getRedisMenuByCode(code);
        Set<String> vo = new HashSet<>();
        redisMenuByCode.forEach(item -> {
            vo.add(item.getName());
        });
        return vo;
    }

    private List<IntergrationMenu> getRedisMenuByCode(String code) {
        UserInfo userInfo = cache.get(code);
        List<IntergrationMenu> menuList = extraCache.getValue(CacheEnums.MENU, dao::getAll);

        menuList = JSONArray.parseArray(JSONObject.toJSONString(menuList), IntergrationMenu.class);

        if (userInfo.getRoles().contains(1)) {
            return menuList;
        }
        List<IntergrationMenu> passRule = new ArrayList<>();
        for (IntergrationMenu item : menuList) {
            if (item.getMetaPassRule()) {
                passRule.add(item);
                passRule.addAll(findParentMenus(menuList, item));
            }
        }

        Map<Integer, List<IntergrationPlatformRoleMenu>> roleMap = extraCache.getValue(CacheEnums.ROLE_MENU, () -> {
            List<IntergrationPlatformRoleMenu> list = dao.selectPlatformRoleMenu();
            return list.stream()
                    .collect(Collectors.groupingBy(IntergrationPlatformRoleMenu::getRoleId));
        });

        Set<Integer> menuId = new HashSet<>();

        userInfo.getRoles().forEach(item -> {
            List<IntergrationPlatformRoleMenu> roleMenuList = roleMap.get(item);
            if (roleMenuList != null) {
                roleMenuList.forEach(roleMenu -> {
                    menuId.add(roleMenu.getMenuId());
                });
            }
        });

        for (IntergrationMenu item : menuList) {
            if (menuId.contains(item.getId())) {
                passRule.add(item);
            }
        }
        passRule = passRule.stream().distinct().collect(Collectors.toList());
        return passRule;
    }


    public ResultVo<String> updateMenuSettings(IntergrationMenu menuList) {
        if (menuList.getId() == null) {
            dao.insert(menuList);
            menuPushRedis();
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_NOTIFICATION, "插入成功。");
        } else {
            dao.updateById(menuList);
            menuPushRedis();
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_NOTIFICATION, "更新成功。");
        }
    }

    public ResultVo<String> deleteMenuSettings(Integer id) {
        LambdaQueryWrapper<IntergrationMenu> qw = new LambdaQueryWrapper<>();

        qw.eq(IntergrationMenu::getParentId, id);
        Long count = dao.selectCount(qw);

        if (count > 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请先删除子节点。");
        }
        dao.deleteById(id);
        menuPushRedis();
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_NOTIFICATION, "删除成功。");
    }


}
