package com.sckw.system.service;

import java.util.Date;

import java.util.*;

import cn.hutool.core.collection.CollectionUtil;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.MenuTypeEnum;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.system.dao.*;
import com.sckw.system.model.*;
import com.sckw.system.model.pojo.FindMenuTreePojo;
import com.sckw.system.model.vo.req.FindMenuTreeReqVo;
import com.sckw.system.model.vo.req.MoveMenuReqVo;
import com.sckw.system.model.vo.req.QueryChildMenuReqVo;
import com.sckw.system.model.vo.req.RoleBindMenuReqVo;
import com.sckw.system.model.vo.res.FindMenuTreeResVo;
import com.sckw.system.model.vo.res.KwsMenuResVo;
import com.sckw.system.model.vo.res.MenuDetailResVo;
import com.sckw.system.model.vo.res.QueryChildMenuResVo;
import org.apache.zookeeper.Login;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 菜单service接口
 * @author zk
 * @date 2023-05-31
 */
@Service
public class KwsMenuService {

    @Autowired
    KwsMenuDao kwsMenuDao;

    @Autowired
    KwsMenuRightsDao kwsMenuRightsDao;

    @Autowired
    KwsUserDao kwsUserDao;

    @Autowired
    KwsUserRoleDao kwsUserRoleDao;

    @Autowired
    KwsEnterpriseDao kwsEnterpriseDao;

    /**
     * @param params 实体
     * @desc: 添加新纪录
     * @author: czh
     * @date: 2023/7/7
     */
    @Transactional(rollbackFor = {})
    public void add(KwsMenu params) throws SystemException {
        Long parentId = params.getParentId();
        KwsMenu parent = null;
        if (!Objects.isNull(parentId) && parentId.compareTo(0L) != 0) {
            parent = kwsMenuDao.selectByKey(parentId);
            if (Objects.isNull(parent)) {
                throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.PARENT_MENU_NOT_EXISTS);
            }
            params.setLevel(parent.getLevel() + 1);
        } else {
            params.setLevel(1);
            params.setParentId(0L);
        }



        //新增按钮时，有重复的序号，则把后面的都加1
        //按钮继承父菜单的using_roles
        if (params.getType() == MenuTypeEnum.BUTTON.getCode()) {
            if (!Objects.isNull(params.getSort())) {
                moveSort(params);
            }
            params.setUsingRoles(parent.getUsingRoles());
        }

        //新增菜单时，如果已经有同级菜单，则序号为最大的序号+1
        if (params.getType() == MenuTypeEnum.DIRECTORY.getCode()) {
            KwsMenu kwsMenuParam = new KwsMenu();
            kwsMenuParam.setType(params.getType());
            kwsMenuParam.setParentId(params.getParentId());
            List<KwsMenu> select = kwsMenuDao.select(kwsMenuParam);
            int sort = 1;
            if (!CollectionUtils.isEmpty(select)) {
                sort = select.get(select.size() - 1).getSort() + 1;
            }
            params.setSort(sort);
        }

        if (kwsMenuDao.insert(params) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
    }

    /**
     * @param params 需要新增的菜单
     * @desc: 菜单序号排序
     * @author: czh
     * @date: 2023/6/29
     */
    private void moveSort(KwsMenu params) {
        KwsMenu param = new KwsMenu();
        param.setParentId(params.getParentId());
        List<KwsMenu> list = kwsMenuDao.select(param);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list = list.stream().filter(item -> !Objects.isNull(item.getSort())).toList();
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        List<Integer> sortList = list.stream().map(KwsMenu::getSort).toList();
        int indexOf = sortList.indexOf(params.getSort());
        if (indexOf >= 0) {
            for (int n = indexOf; n < list.size(); n++) {
                KwsMenu kwsMenu = list.get(n);
                kwsMenu.setSort(kwsMenu.getSort() + 1);
                kwsMenuDao.update(kwsMenu);
                if (n + 1 < list.size() && list.get(n + 1).getSort() > kwsMenu.getSort()) {
                    break;
                }
            }
        }
    }

    /**
     * @param ids 主键di
     * @desc: 根据主键删除菜单
     * @author: czh
     * @date: 2023/6/25
     */
    public void deleteByKey(String ids) throws SystemException {
        List<Long> list = Arrays.stream(ids.split(Global.COMMA)).map(Long::parseLong).toList();
        /*1、删除菜单*/
        List<KwsMenu> kwsMenus = kwsMenuDao.selectByKeys(list);
        if (CollectionUtils.isEmpty(kwsMenus)) {
            return;
        }

        for (KwsMenu kwsMenu : kwsMenus) {
            kwsMenu.setDelFlag(Global.YES);
            if (kwsMenuDao.update(kwsMenu) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.DELETE_FAIL);
            }
        }

        /*2、删除菜单权限*/
        deleteMenuRightsByMenuIds(kwsMenus.stream().map(KwsMenu::getId).toList());
    }

    /**
     * @param menuIdList 菜单id集合
     * @desc: 删除菜单权限
     * @author: czh
     * @date: 2023/6/25
     */
    public void deleteMenuRightsByMenuIds(List<Long> menuIdList) throws SystemException {
        deleteMenuRights(kwsMenuRightsDao.selectByMenuIds(menuIdList));
    }

    /**
     * @param roleIdList 角色id集合
     * @desc: 删除菜单权限
     * @author: czh
     * @date: 2023/6/25
     */
    public void deleteMenuRightsByRoleIds(List<Long> roleIdList) throws SystemException {
        deleteMenuRights(kwsMenuRightsDao.selectByRoleIds(roleIdList));
    }

    private void deleteMenuRights(List<KwsMenuRights> kwsMenuRightsList) {
        if (CollectionUtils.isEmpty(kwsMenuRightsList)) {
            return;
        }

        for (KwsMenuRights kwsMenuRights : kwsMenuRightsList) {
            kwsMenuRights.setDelFlag(Global.YES);
            if (kwsMenuRightsDao.update(kwsMenuRights) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.DELETE_FAIL);
            }
        }
    }


    /**
     * @param params 更新记录
     * @desc: 更新记录
     * @author: czh
     * @date: 2023/7/3
     */
    public void update(KwsMenu params) throws SystemException {
        if (kwsMenuDao.update(params) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
    }

    /**
     * @param key 主键
     * @return KwsMenu
     * @desc: 根据主键查询
     * @author: czh
     * @date: 2023/7/7
     */
    public MenuDetailResVo selectByKey(Long key) throws SystemException {
        KwsMenu kwsMenu = kwsMenuDao.selectByKey(key);
        //前端特殊处理，当父id为0时，设成null
        if (kwsMenu.getParentId().compareTo(0L) == 0) {
            kwsMenu.setParentId(null);
        }

        MenuDetailResVo menuDetailResVo = new MenuDetailResVo();
        BeanUtils.copyProperties(kwsMenu, menuDetailResVo);
        return menuDetailResVo;
    }

    /**
     * @param reqVo 入参
     * @return KwsMenuResVo
     * @desc: 分页查询
     * @author: czh
     * @date: 2023/7/7
     */
    public List<FindMenuTreeResVo> findTree(FindMenuTreeReqVo reqVo) throws SystemException {
        FindMenuTreePojo findMenuTreePojo = new FindMenuTreePojo();
        BeanUtils.copyProperties(reqVo, findMenuTreePojo);

        //填充用户参数
        extracted(reqVo.getUserId(), findMenuTreePojo);

        List<KwsMenuResVo> menuList = kwsMenuDao.findList(findMenuTreePojo);
        List<KwsMenuResVo> rootList = new ArrayList<>();

        //获取根节点数据
        if (CollectionUtil.isNotEmpty(menuList)) {
            int level = menuList.get(0).getLevel();
            for (KwsMenuResVo kwsMenu : menuList) {
                if (kwsMenu.getLevel() == level) {
                    rootList.add(kwsMenu);
                }
            }
        }

        //遍历，找到二级机构（根机构的id和所有机构中的pid比较）
        for (KwsMenuResVo kwsMenu : rootList) {
            List<KwsMenuResVo> child = getChild(kwsMenu.getId(), menuList);
            kwsMenu.setChildren(child);
        }
        return BeanUtils.copyToList(rootList, FindMenuTreeResVo.class);
    }

    public List<KwsMenuResVo> findList(FindMenuTreePojo findMenuTreePojo) {
        return kwsMenuDao.findList(findMenuTreePojo);
    }

    private void extracted(Long userId, FindMenuTreePojo findMenuTreePojo) {
        if (Objects.equals(LoginUserHolder.getIsMain(), Global.YES)) {
            return;
        }

        if (Objects.isNull(userId)) {
            userId = LoginUserHolder.getUserId();
        }
        KwsUser kwsUser = kwsUserDao.selectByKey(userId);
        if (Objects.isNull(kwsUser)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ACCOUNT_NOT_EXISTS);
        }

        List<KwsUserRole> allByUserId = kwsUserRoleDao.findAllByUserId(userId);
        if (CollectionUtils.isEmpty(allByUserId)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ROLE_NOT_EXISTS);
        }
        findMenuTreePojo.setRoleIds(allByUserId.stream().map(KwsUserRole::getRoleId).toList());
    }

    /**
     * 递归获取下级菜单
     *
     * @param parentId 父级机构id
     * @param deptList 所有机构
     * @return KwsMenuResVo
     */
    public List<KwsMenuResVo> getChild(Long parentId, List<KwsMenuResVo> deptList) {
        List<KwsMenuResVo> childList = new ArrayList<>();
        for (KwsMenuResVo kwsMenu : deptList) {
            if (parentId.equals(kwsMenu.getParentId())) {
                //获取当前菜单id的所有子列表
                childList.add(kwsMenu);
            }
        }
        for (KwsMenuResVo kwsMenu : childList) {
            //将该id的子菜单进行遍历，通过递归调用，获取每一个子菜单的子菜单数据
            List<KwsMenuResVo> child = getChild(kwsMenu.getId(), deptList);
            kwsMenu.setChildren(child);
        }
        if (childList.size() == 0) {
            //子菜单的长度为0,返回null,null不会被阿里的FastJson包解析
            return null;
        }
        return childList;
    }

    /**
     * @param reqVo 菜单ID多个用","隔开
     * @desc: 角色分配菜单
     * @author: czh
     * @date: 2023/6/13
     */
    public void roleBindMenu(RoleBindMenuReqVo reqVo) {
        String[] split = reqVo.getMenuIds().split(",");
        List<KwsMenuRights> list = new ArrayList<>();
        Date date = new Date();
        for (String menuId : split) {
            KwsMenuRights kwsMenuRights = new KwsMenuRights();
            kwsMenuRights.setEntId(reqVo.getEntId());
            kwsMenuRights.setMenuId(Long.parseLong(menuId));
            kwsMenuRights.setRoleId(reqVo.getRoleId());
            kwsMenuRights.setId(new IdWorker(1L).nextId());
            kwsMenuRights.setRemark(reqVo.getRemark());
            kwsMenuRights.setStatus(Global.NO);
            kwsMenuRights.setCreateBy(LoginUserHolder.getUserId());
            kwsMenuRights.setCreateTime(date);
            kwsMenuRights.setUpdateBy(LoginUserHolder.getUserId());
            kwsMenuRights.setUpdateTime(date);
            kwsMenuRights.setDelFlag(Global.NO);
            list.add(kwsMenuRights);
        }
        if (kwsMenuRightsDao.saveBatch(list) < list.size()) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
    }

    public List<KwsMenu> selectAll() {
        return kwsMenuDao.selectAll();
    }

    @Transactional(rollbackFor = {})
    public void moveMenu(MoveMenuReqVo reqVo) {
        KwsMenu kwsMenu = kwsMenuDao.selectByKey(reqVo.getId());
        if (Objects.isNull(kwsMenu)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.MENU_NOT_EXISTS);
        }

        //查出要被换位置的按钮
        KwsMenu targetMenu = getTargetMenu(reqVo.getMoveType(), kwsMenu);
        if (Objects.isNull(targetMenu)) {
            return;
        }

        //修改要换位置的按钮
        kwsMenu.setSort(kwsMenu.getSort() + reqVo.getMoveType());
        if (kwsMenuDao.update(kwsMenu) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }

        //更新被换位置的按钮
        targetMenu.setSort(targetMenu.getSort() - reqVo.getMoveType());
        if (kwsMenuDao.update(targetMenu) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
    }


    private KwsMenu getTargetMenu(Integer moveType, KwsMenu kwsMenu) {
        KwsMenu kwsMenuParam = new KwsMenu();
        kwsMenuParam.setType(kwsMenu.getType());
        kwsMenuParam.setParentId(kwsMenu.getParentId());
        kwsMenuParam.setSort(kwsMenu.getSort() + moveType);
        kwsMenuParam.setDelFlag(Global.NO);
        List<KwsMenu> targetMenuList = kwsMenuDao.select(kwsMenuParam);
        return CollectionUtils.isEmpty(targetMenuList) ? null : targetMenuList.get(0);
    }


    public List<QueryChildMenuResVo> queryChildMenu(QueryChildMenuReqVo reqVo) {
        KwsMenu kwsMenuParam = new KwsMenu();
        kwsMenuParam.setParentId(reqVo.getId());
        kwsMenuParam.setType(reqVo.getType());
        kwsMenuParam.setName(reqVo.getName());
        kwsMenuParam.setPerms(reqVo.getPerms());
        List<KwsMenu> select = kwsMenuDao.queryChildMenu(kwsMenuParam);
        if (CollectionUtils.isEmpty(select)) {
            return Collections.emptyList();
        }
        return BeanUtils.copyToList(select, QueryChildMenuResVo.class);
    }

}
