package com.gic.haoban.manage.service.service.role.impl;

import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.clerk.api.dto.right.EnterpriseSuperAdminRightMenuQDTO;
import com.gic.clerk.api.dto.right.MenuDTO;
import com.gic.clerk.api.dto.right.MenuListQDTO;
import com.gic.clerk.api.dto.right.RightMenuDTO;
import com.gic.clerk.api.service.MenuApiService;
import com.gic.clerk.api.service.RightService;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.haoban.manage.service.dao.mapper.WxEnterpriseRelatedMapper;
import com.gic.haoban.manage.service.dao.mapper.role.TabHaobanMenuMapper;
import com.gic.haoban.manage.service.dao.mapper.role.TabHaobanRoleMapper;
import com.gic.haoban.manage.service.dao.mapper.role.TabHaobanRoleMenuMapper;
import com.gic.haoban.manage.service.entity.TabHaobanWxEnterpriseRelated;
import com.gic.haoban.manage.service.entity.role.TabHaobanMenu;
import com.gic.haoban.manage.service.entity.role.TabHaobanRole;
import com.gic.haoban.manage.service.entity.role.TabHaobanRoleMenu;
import com.gic.haoban.manage.service.pojo.bo.role.HaobanMenuBO;
import com.gic.haoban.manage.service.service.MemberQueryService;
import com.gic.haoban.manage.service.service.role.HaobanMenuService;
import com.gic.haoban.manage.service.util.Constant;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @author mozhu
 * @since 2022-09-06 16:35:11
 */
@Service
public class HaobanMenuServiceImpl implements HaobanMenuService {
    private static final Logger logger = LogManager.getLogger(HaobanMenuService.class);

    @Autowired
    private TabHaobanMenuMapper tabHaobanMenuMapper;
    @Autowired
    private WxEnterpriseRelatedMapper wxEnterpriseRelatedMapper ;
    @Autowired
    private TabHaobanRoleMapper roleMapper ;
    @Autowired
    private TabHaobanRoleMenuMapper roleMenuMapper ;
    @Autowired
    private MenuApiService menuApiService ;
    @Autowired
    private RightService rightService ;

    @Override
    public TabHaobanMenu queryById(String menuCode) {
        if (StringUtils.isBlank(menuCode)) {
            return null;
        }
        return this.tabHaobanMenuMapper.queryById(menuCode);
    }

    /**
     * 新增数据
     *
     * @param tabHaobanMenu 实例对象
     * @return 实例对象
     */
    @Override
    public int insert(TabHaobanMenu tabHaobanMenu) {
        tabHaobanMenu.setCreateTime(new Date());
        tabHaobanMenu.setUpdateTime(new Date());
        return this.tabHaobanMenuMapper.insert(tabHaobanMenu);
    }

    @Override
    public int insertBatch(List<TabHaobanMenu> tabHaobanMenus) {
        for (TabHaobanMenu tabHaobanMenu : tabHaobanMenus) {
            tabHaobanMenu.setStatusFlag(1);
            tabHaobanMenu.setCreateTime(new Date());
            tabHaobanMenu.setUpdateTime(new Date());
        }
        return tabHaobanMenuMapper.insertBatch(tabHaobanMenus);
    }

    /**
     * 修改数据
     *
     * @param tabHaobanMenu 实例对象
     * @return 实例对象
     */
    @Override
    public int update(TabHaobanMenu tabHaobanMenu) {
        tabHaobanMenu.setUpdateTime(new Date());
        return this.tabHaobanMenuMapper.update(tabHaobanMenu);
    }

    @Override
    public List<HaobanMenuBO> getAllMenuList() {
        List<TabHaobanMenu> allMenuList = tabHaobanMenuMapper.getAllMenuList();
        return EntityUtil.changeEntityListNew(HaobanMenuBO.class, allMenuList);
    }

    @Override
    public List<HaobanMenuBO> getMenuTreeList() {
        List<TabHaobanMenu> pidMenuList = tabHaobanMenuMapper.getPidMenuList();
        List<TabHaobanMenu> notPidMenuList = tabHaobanMenuMapper.getNotPidMenuList();
        List<HaobanMenuBO> pidMenuBOList = EntityUtil.changeEntityListNew(HaobanMenuBO.class, pidMenuList);
        List<HaobanMenuBO> notPidMenuBOList = EntityUtil.changeEntityListNew(HaobanMenuBO.class, notPidMenuList);
        for (HaobanMenuBO haobanMenuBO : pidMenuBOList) {
            List<HaobanMenuBO> menus = iterateMenus(notPidMenuBOList, haobanMenuBO.getMenuCode());
            haobanMenuBO.setMenuBOList(menus);
        }
        return pidMenuBOList;
    }

    @Override
    public List<RightMenuDTO> getGicBuyMenus(String enterpriseId) {
        logger.info("查询gic权限={}",enterpriseId);
        if(StringUtils.isBlank(enterpriseId) || "-1".equals(enterpriseId)) {
            return null ;
        }
        // 查询gic购买的好办小程序权限
        EnterpriseSuperAdminRightMenuQDTO qdto = new EnterpriseSuperAdminRightMenuQDTO() ;
        qdto.setEnterpriseId(enterpriseId);
        qdto.setNamespace(Constant.hb_wxa_namespace);
        List<RightMenuDTO> list = this.rightService.listSuperAdminRightMenu(qdto) ;
        logger.info("查询gic购买的好办小程序权限={},返回={}",enterpriseId,JSONObject.toJSONString(list));
        return list ;
    }

    // Integer clerkType
    @Override
    public List<String> getGicBuyCodes(String enterpriseId , Integer clerkType) {
        List<RightMenuDTO> list = this.getGicBuyMenus(enterpriseId) ;
        if(CollectionUtils.isNotEmpty(list)) {
            List<String> codeList = list.stream().filter(o->{
                return o.getHaobanRoles().contains(clerkType+"") ;
            }).map(o->o.getMenuCode()).collect(Collectors.toList());
            logger.info("满足的gic权限={},clerkType={}",codeList,clerkType);
            return codeList ;
        }
        return null ;
    }

    @Override
    public List<HaobanMenuBO> getHaobanMenuTreeList(String wxEnterpriseId, String enterpriseId ,Integer clerkType) {
        List<TabHaobanMenu> pidMenuList = tabHaobanMenuMapper.getHaobanPidMenuList(wxEnterpriseId, clerkType, 0);
        List<TabHaobanMenu> notPidMenuList = tabHaobanMenuMapper.getHaobanNotPidMenuList(wxEnterpriseId, clerkType, 0);
        List<HaobanMenuBO> pidMenuBOList = EntityUtil.changeEntityListNew(HaobanMenuBO.class, pidMenuList);
        List<HaobanMenuBO> notPidMenuBOList = EntityUtil.changeEntityListNew(HaobanMenuBO.class, notPidMenuList);
        if(CollectionUtils.isEmpty(pidMenuBOList)) {
            pidMenuBOList = new ArrayList<>() ;
        }
        if(CollectionUtils.isEmpty(notPidMenuBOList)) {
            notPidMenuBOList = new ArrayList<>() ;
        }
        List<String> gicMenulist = this.getGicBuyCodes(enterpriseId,clerkType) ;
        if(CollectionUtils.isNotEmpty(gicMenulist)) {
            List<HaobanMenuBO> allMenuList = this.getAllMenuList();
            Map<String,HaobanMenuBO> map = allMenuList.stream().collect(Collectors.toMap(HaobanMenuBO::getMenuCode,o->o,(k1,k2)->k1)) ;
            for(String menuCode : gicMenulist) {
                HaobanMenuBO bo = map.get(menuCode) ;
                if(null != bo) {
                    if (menuCode.equals(bo.getParentCode())) {
                        pidMenuBOList.add(bo) ;
                    }else {
                        notPidMenuBOList.add(bo) ;
                    }
                }
            }
        }
        if (CollectionUtils.isEmpty(pidMenuBOList)) {
            return new ArrayList<>();
        }
        pidMenuBOList = pidMenuBOList.stream().distinct().collect(Collectors.toList());
        notPidMenuBOList = notPidMenuBOList.stream().distinct().collect(Collectors.toList());
        for (HaobanMenuBO haobanMenuBO : pidMenuBOList) {
            if (CollectionUtils.isNotEmpty(notPidMenuBOList)) {
                List<HaobanMenuBO> menus = iterateMenus(notPidMenuBOList, haobanMenuBO.getMenuCode());
                haobanMenuBO.setMenuBOList(menus);
            }
        }
        return pidMenuBOList;
    }

    @Override
    public List<String> getHaobanMenuList(String wxEnterpriseId, Integer clerkType) {
        return tabHaobanMenuMapper.getHaobanMenuListByClerkType(wxEnterpriseId, clerkType, 0);
    }

    @Override
    public List<String> getHaobanMenuByPid(List<String> menuCodes) {
        List<String> list = new ArrayList<>();
        List<String> pidCodes = tabHaobanMenuMapper.getHaobanMenuCodeListByCode(menuCodes);
        List<String> childCodes = tabHaobanMenuMapper.getHaobanChildMenuCodeByPCode(menuCodes);
        list.addAll(pidCodes);
        list.addAll(childCodes);
        return list;
    }

    @Override
    public List<HaobanMenuBO> getHaobanMenuList(List<String> menuCodes) {
        if (CollectionUtils.isEmpty(menuCodes)) {
            return Collections.emptyList();
        }
        List<TabHaobanMenu> haobanMenuListByCode = tabHaobanMenuMapper.getHaobanMenuListByCode(menuCodes);
        return EntityUtil.changeEntityListNew(HaobanMenuBO.class, haobanMenuListByCode);
    }

    @Override
    public HaobanMenuBO getMenuByCode(String menuCode) {
        if (StringUtils.isBlank(menuCode)) {
            return null;
        }
        return EntityUtil.changeEntityNew(HaobanMenuBO.class, tabHaobanMenuMapper.getMenuByCode(menuCode));
    }

    @Override
    public void deleteAll() {
        tabHaobanMenuMapper.deleteAll();
    }

    public List<HaobanMenuBO> iterateMenus(List<HaobanMenuBO> menuBOList, String pCode) {
        List<HaobanMenuBO> result = new ArrayList<>();
        for (HaobanMenuBO haobanMenuBO : menuBOList) {
            String menuCode = haobanMenuBO.getMenuCode();
            String parentCode = haobanMenuBO.getParentCode();
            if (StringUtils.isNotBlank(parentCode)) {
                if (parentCode.equals(pCode)) {
                    // 递归查询当前子菜单的子菜单
                    List<HaobanMenuBO> iterateMenu = iterateMenus(menuBOList, menuCode);
                    haobanMenuBO.setMenuBOList(iterateMenu);
                    result.add(haobanMenuBO);
                }
            }
        }
        return result;
    }

    @Override
    public void deleteByMenuCode(String menuCode) {
        this.tabHaobanMenuMapper.deleteByMenuCode(menuCode);
    }

    @Override
    public void saveMenuFromGicEvent(String params) {
        logger.info("服务开通事件-好办小程序={}",params);
        JSONObject json = JSONObject.parseObject(params) ;
        String serviceCode = json.getString("serviceCode") ;
        String enterpriseId = json.getString("enterpriseId") ;
        String operationType = json.getString("operationType") ;
        Integer packageCode = json.getInteger("packageCode") ;
        // 进行授权 auth  取消授权 cancel
        if("cancel".equals(operationType)) {
            logger.info("取消不处理");
            return ;
        }
        List<TabHaobanWxEnterpriseRelated> wxEnterpriseList = this.wxEnterpriseRelatedMapper.listByEnterpriseId(enterpriseId) ;
        if(CollectionUtils.isEmpty(wxEnterpriseList)) {
            logger.info("无好办={}",enterpriseId);
            return ;
        }
        MenuListQDTO qdto = new MenuListQDTO() ;
        qdto.setNamespace(Constant.hb_wxa_namespace);
        qdto.setServiceCode(serviceCode);
        qdto.setPackageCode(packageCode);
        ServiceResponse<List<MenuDTO>> resp = this.menuApiService.listMenu(qdto) ;
        logger.info("查询gic权限={},{}",JSONObject.toJSONString(qdto),JSONObject.toJSONString(resp));
        if(!resp.isSuccess() || CollectionUtils.isEmpty(resp.getResult())) {
            logger.info("无相关菜单,不处理");
            return;
        }
        logger.info("gic关联的企微={}", JSONObject.toJSONString(wxEnterpriseList));
        List<MenuDTO> menuDTOList = resp.getResult() ;
        for(MenuDTO gicMenu : menuDTOList) {
            // 授权方式，是否自动授权给子管理员 0，不做处理 1:自动授权子管理员
            Integer authType = gicMenu.getAuthType() ;
            String gicMenuCode = gicMenu.getMenuCode();
            String haobanRoles = gicMenu.getHaobanRoles() ;
            if(null == authType || authType == 0) {
                logger.info("authType无值{}",gicMenuCode);
                continue;
            }
            if(StringUtils.isBlank(haobanRoles)) {
                logger.info("haobanRoles无值{}",gicMenuCode);
                continue;
            }
            List<String> menuCodeList = Arrays.asList(gicMenuCode) ;
            String[] arr = haobanRoles.split("\\|") ;
            List<Integer> addRoleTypeList = Arrays.stream(arr).filter(o->StringUtils.isNotBlank(o)).map(o->Integer.valueOf(o)).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(addRoleTypeList)) {
                logger.info("haobanRoles null {} , {}",gicMenuCode , haobanRoles);
                continue;
            }
            Date now = new Date() ;
            for(int i=0;i<wxEnterpriseList.size();i++) {
                TabHaobanWxEnterpriseRelated item = wxEnterpriseList.get(i) ;
                String wxEnterpriseId = item.getWxEnterpriseId() ;
                List<TabHaobanRoleMenu> insertMenuList = new ArrayList<>() ;
                List<TabHaobanRole> hbRoleList = this.roleMapper.getListByWxEnterpriseId(wxEnterpriseId,1) ;
                TabHaobanRoleMenu menu = null ;
                for(TabHaobanRole role : hbRoleList) {
                    int roleType = role.getClerkType() ;
                    if(!addRoleTypeList.contains(roleType)) {
                        logger.info("角色不符合={},{}",addRoleTypeList,roleType);
                        continue;
                    }
                    Long roleId = role.getRoleId() ;
                    for(String menuCode : menuCodeList) {
                        // 判断是否已存在
                        List<String> oldList = this.roleMenuMapper.getMenuInMenuCodes(wxEnterpriseId,roleId,Arrays.asList(menuCode)) ;
                        if(CollectionUtils.isNotEmpty(oldList)) {
                            logger.info("权限已存在roleId={},{}",role,menuCode);
                            continue;
                        }
                        menu = new TabHaobanRoleMenu() ;
                        menu.setRoleMenuId(UniqueIdUtils.uniqueLong());
                        menu.setRoleId(roleId);
                        menu.setUpdateTime(now);
                        menu.setCreateTime(now);
                        menu.setStatusFlag(1);
                        menu.setWxEnterpriseId(wxEnterpriseId);
                        menu.setMenuCode(menuCode);
                        insertMenuList.add(menu) ;
                    }
                }
                if(CollectionUtils.isNotEmpty(insertMenuList)) {
                    this.roleMenuMapper.insertBatch(insertMenuList);
                }
            }
        }
    }
}
