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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.clerk.api.service.RightService;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.commons.util.ToolUtil;
import com.gic.enterprise.api.dto.*;
import com.gic.enterprise.api.service.AuthorizeService;
import com.gic.enterprise.api.service.EnterpriseService;
import com.gic.enterprise.api.service.StoreGroupService;
import com.gic.enterprise.api.service.StoreService;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.base.api.common.ServiceResponse;
import com.gic.haoban.base.api.common.errCode.HaoBanErrCodeCommon;
import com.gic.haoban.common.utils.PageUtil;
import com.gic.haoban.common.utils.UuidUtil;
import com.gic.haoban.manage.api.dto.*;
import com.gic.haoban.manage.api.enums.ChannelCodeEnum;
import com.gic.haoban.manage.api.service.WxEnterpriseRelatedApiService;
import com.gic.haoban.manage.service.dao.mapper.WxEnterpriseMapper;
import com.gic.haoban.manage.service.dao.mapper.WxEnterpriseRelatedMapper;
import com.gic.haoban.manage.service.entity.*;
import com.gic.haoban.manage.service.service.DepartmentService;
import com.gic.haoban.manage.service.service.MiniprogramSettingService;
import com.gic.haoban.manage.service.service.StoreRangeService;
import com.gic.haoban.manage.service.service.WxEnterpriseRelatedService;
import com.gic.mq.sdk.GicMQClient;
import com.gic.redis.data.util.RedisUtil;
import com.google.common.collect.Sets;
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 org.springframework.transaction.annotation.Transactional;

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

@Service
public class WxEnterpriseRelatedApiServiceImpl implements WxEnterpriseRelatedApiService {
    private static final Logger logger = LogManager.getLogger(WxEnterpriseRelatedApiServiceImpl.class);
    private static final String FLUSH_HAOBAN_BIND_STORE = "flush_haoban_bind_store:";
    private static final String FLUSH_HAOBAN_BIND_STORE_MQ = "flushHaobanBindStoreMq";
    //延迟判断redis的key
    private static final String FLUSH_HAOBAN_BIND_STORE_MQ_DELAY = "flushHaobanBindStoreMqDelay";
    private static final int DELAY_TIME = 10;
    @Autowired
    private WxEnterpriseRelatedMapper wxEnterpriseRelatedMapper;
    @Autowired
    private WxEnterpriseMapper wxEnterpriseMapper ;
    @Autowired
    private WxEnterpriseRelatedService wxEnterpriseRelatedService;
    @Autowired
    private StoreGroupService storeGroupService;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private MiniprogramSettingService miniprogramSettingService;
    @Autowired
    private AuthorizeService authorizeService;
    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private StoreRangeService storeRangeService;
    @Autowired
    private StoreService storeService;
    @Autowired
    private RightService rightService;
    @Autowired
    private ClerkService clerkService;

    /**
     * 查询好办所有的企业id
     *
     * @return : 返回好办关联的所有企业id
     */
    @Override
    public List<String> findAllEnterpriseId() {
        return wxEnterpriseRelatedMapper.findAllEnterpriseId();
    }

    @Override
    public List<EnterpriseDetailDTO> listEnterpriseByWxEnterpriseId(String wxEnterpriseId) {
        return this.listEnterpriseByWxEnterpriseId(wxEnterpriseId, null, false);
    }

    @Override
    public EnterpriseDetailDTO getByEnterpriseId(String wxEnterpriseId, String enterpriseId) {
        TabHaobanWxEnterpriseRelated entity = wxEnterpriseRelatedService.getByEnterpriseId(wxEnterpriseId, enterpriseId);
        if(null == entity) {
            return null ;
        }
        EnterpriseDetailDTO dto = EntityUtil.changeEntityByJSON(EnterpriseDetailDTO.class, entity);
        return dto;
    }

    @Override
    public List<EnterpriseDetailDTO> listEnterpriseByWxEnterpriseIdList(List<String> wxEnterpriseIdList) {
        List<TabHaobanWxEnterpriseRelated> relatedList = this.wxEnterpriseRelatedMapper.listByWxenterpriseIdList(wxEnterpriseIdList);
        if (CollectionUtils.isNotEmpty(relatedList)) {
            List<EnterpriseDetailDTO> list = EntityUtil.changeEntityListByJSON(EnterpriseDetailDTO.class, relatedList);
            for (EnterpriseDetailDTO item : list) {
                String enterpriseId = item.getEnterpriseId();
                EnterpriseDTO en = this.enterpriseService.getEnterpriseById(enterpriseId);
                if (null != en) {
                    item.setEnterpriseName(en.getBrandName());
                }
            }
            return list;
        }
        return null;
    }

    @Override
    public List<EnterpriseDetailDTO> listEnterpriseByWxEnterpriseId(String wxEnterpriseId, String phoneNumber, boolean filterFlag) {
        logger.info("listEnterpriseByWxEnterpriseId,wxeid={},phone={}", wxEnterpriseId, phoneNumber);
        List<TabHaobanWxEnterpriseRelated> relatedList = wxEnterpriseRelatedMapper.listByWxenterpriseId(wxEnterpriseId);
        List<EnterpriseDetailDTO> list = EntityUtil.changeEntityListByJSON(EnterpriseDetailDTO.class, relatedList);
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }
        List<String> enterpriseIds = list.stream().map(s -> s.getEnterpriseId()).collect(Collectors.toList());
        List<EnterpriseDTO> enterpriseList = enterpriseService.listEnterpriseByIds(enterpriseIds);
        Map<String, EnterpriseDTO> map = com.gic.commons.util.CollectionUtil.toMap(enterpriseList, "enterpriseId");
        Iterator<EnterpriseDetailDTO> it = list.iterator();
        while (it.hasNext()) {
            EnterpriseDetailDTO dto = it.next();
            EnterpriseDTO enterpriseDTO = map.get(dto.getEnterpriseId());
            if (enterpriseDTO != null) {
                dto.setEnterpriseName(enterpriseDTO.getEnterpriseName());
                dto.setEnterpriseLogo(enterpriseDTO.getQcloudImageUrl());
                dto.setBrandName(enterpriseDTO.getBrandName());
                dto.setConactsPhone(enterpriseDTO.getConactsPhone());
                dto.setCustomerPhone(enterpriseDTO.getCustomerPhone());
                dto.setAclFlag(1);
                if (StringUtils.isNotBlank(phoneNumber)) {
                    com.gic.api.base.commons.ServiceResponse<Boolean> resp = this.rightService.hasHaobanAcl(enterpriseDTO.getEnterpriseId(), phoneNumber);
                    if (!resp.getResult()) {
                        dto.setAclFlag(0);
                        if (filterFlag) {
                            it.remove();
                        }
                    }
                }
            }
        }
        return list;
    }

//    @Override
//    public String getGicEnterpriseIdByEnterpriseRelatedId(String wxEnterpriseRelatedId) {
//        TabHaobanWxEnterpriseRelated tab = wxEnterpriseRelatedService.getByGicEnterpriseIdByEnterpriseRelatedId(wxEnterpriseRelatedId);
//        return tab != null ? tab.getEnterpriseId() : null;
//    }

    @Override
    public boolean enterpriseUseNew(String enterpriseId) {
        if (null == enterpriseId) {
            return false;
        }
        List<String> eids = new ArrayList<>();
        eids.add(enterpriseId);
        List<TabHaobanWxEnterpriseRelated> retList = wxEnterpriseRelatedMapper.listEnterpriseByEnterpriseIds(eids);
        return !CollectionUtils.isEmpty(retList);
    }

    @Override
    public List<EnterpriseDetailDTO> queryAllHasGicEnterpriseId() {
        List<TabHaobanWxEnterpriseRelated> relatedList = wxEnterpriseRelatedMapper.queryAllHasGicEnterpriseId();
        List<EnterpriseDetailDTO> result = EntityUtil.changeEntityListByJSON(EnterpriseDetailDTO.class, relatedList);
        for (EnterpriseDetailDTO enterpriseDetailDTO : result) {
            String enterpriseId = enterpriseDetailDTO.getEnterpriseId();
            int gicAllCount = storeGroupService.gicDepartmentCount(enterpriseId);
            int syncCount = departmentService.countSyncDepartmentByEnterpriseId(enterpriseId);
            int nodeCount = gicAllCount - syncCount;
            enterpriseDetailDTO.setNodeCount(nodeCount);
        }
        return result;
    }

    @Override
    public List<EnterpriseDetailDTO> listEnterpriseByEnterpriseIds(
            List<String> enterpriseIds) {
        List<TabHaobanWxEnterpriseRelated> list = wxEnterpriseRelatedMapper.listEnterpriseByEnterpriseIds(enterpriseIds);
        List<EnterpriseDetailDTO> details = EntityUtil.changeEntityListByJSON(EnterpriseDetailDTO.class, list);
        return details;
    }

    private String isBindMany(String enterpriseId , String wxEnterpriseId) {
        List<TabHaobanWxEnterpriseRelated> list = this.wxEnterpriseRelatedMapper.listByEnterpriseId(enterpriseId) ;
        List<String> bindNameList = new ArrayList<>() ;
        if(CollectionUtils.isNotEmpty(list)) {
            for(TabHaobanWxEnterpriseRelated item : list) {
                TabHaobanWxEnterprise wxEnterprise = this.wxEnterpriseMapper.selectByPrimaryKey(item.getWxEnterpriseId()) ;
                if(null == wxEnterprise || 0 == wxEnterprise.getStatusFlag())  {
                    this.wxEnterpriseRelatedMapper.deleteById(item.getWxEnterpriseRelatedId()) ;
                } else {
                    if(!item.getWxEnterpriseId().equals(wxEnterpriseId)) {
                        bindNameList.add(wxEnterprise.getCorpName()) ;
                    }
                }
            }
            if(CollectionUtils.isNotEmpty(bindNameList)) {
                return bindNameList.stream().collect(Collectors.joining("、"));
            }
        }
        return null ;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResponse wxEnterpriseBind(WxEnterpriseRelationDetailDTO detailDTO) {
        ServiceResponse<Object> resp = new ServiceResponse<>();
        //校验是否分组被其它企业绑定
        if (!checkHasBindStoreGroup(detailDTO)) {
            logger.info("部分分组被其它企业绑定了：{}", JSONObject.toJSONString(detailDTO));
            resp.setCode(2);
            resp.setMessage("部分分组被其它企业绑定了！");
            return resp;
        }

        if (!checkRootEnterprise(detailDTO)) {
            logger.info("总部已经被设置不能存在多个总部：{}", JSONObject.toJSONString(detailDTO));
            resp.setCode(3);
            resp.setMessage("总部已经被设置不能存在多个总部！");
            return resp;
        }
        String enterpriseId = detailDTO.getEnterpriseId();
        String wxEnterpriseId = detailDTO.getWxEnterpriseId();
        //校验关联已经企业绑定
        TabHaobanWxEnterpriseRelated tab = wxEnterpriseRelatedMapper.findOneByEIdAndWxEid(enterpriseId, wxEnterpriseId);
        String bindMany = this.isBindMany(enterpriseId , wxEnterpriseId) ;
        if(StringUtils.isNotBlank(bindMany)) {
            logger.info("一GIC商户绑不能绑定多个");
            resp.setCode(2);
            resp.setMessage("商户不能绑多个企微("+bindMany+")");
            return resp;
        }
        if (tab != null && (!tab.getWxEnterpriseRelatedId().equals(detailDTO.getWxEnterpriseRelatedId()))) {
            logger.info("该企业已经被绑定过");
            resp.setCode(2);
            resp.setMessage("该企业已经被绑定过！");
            return resp;
        }
        EnterpriseDTO enterpriseDTO = enterpriseService.getEnterpriseById(enterpriseId);
        if (enterpriseDTO == null) {
            logger.info("该企业为空：{}", enterpriseId);
            resp.setCode(2);
            resp.setMessage("该企业为空");
            return resp;
        }
        if (tab == null) {
            logger.info("该gicEnterpriseId已经绑定过了:{}", JSONObject.toJSONString(detailDTO));
            //保存企业关联关系
            tab = EntityUtil.changeEntityNew(TabHaobanWxEnterpriseRelated.class, detailDTO);
            tab.setEnterpriseName(enterpriseDTO.getEnterpriseName());
            tab.setStatusFlag(1);
            tab.setRangeType(1);
            tab.setVersion("3.0");
            tab.setCreateTime(new Date());
            tab.setUpdateTime(new Date());
            tab.setWxEnterpriseRelatedId(UuidUtil.randomUUID());
            wxEnterpriseRelatedMapper.insertSelective(tab);
        } else {
            tab.setMemberOpenCardFlag(detailDTO.getMemberOpenCardFlag());
            tab.setWxEnterpriseType(detailDTO.getWxEnterpriseType());
            tab.setRangeType(1);
            tab.setUpdateTime(new Date());
            wxEnterpriseRelatedMapper.updateByPrimaryKeySelective(tab);
        }

        //保存门店范围
        storeRangeService.saveStoreRange(detailDTO.getRelations(), enterpriseId, wxEnterpriseId);

        List<EnterpriseWxaRelationDTO> relationDTOList = authorizeService.queryList(enterpriseId);
        if (CollectionUtils.isEmpty(relationDTOList)) {
            logger.info("relationDTOList is null");
            return resp;
        }
        EnterpriseWxaRelationDTO relationDTO = relationDTOList.stream().filter(dto -> dto.getWxaAppkey().equals(enterpriseDTO.getMallMiniprogramAppid())).findFirst().orElse(null);
        if (null == relationDTO) {
            logger.info("relationDTO is null");
            return resp;
        }
        TabMiniprogramSetting miniprogramSetting = miniprogramSettingService.getMiniprogramSettingNoMedia(wxEnterpriseId, enterpriseId);
        if (null == miniprogramSetting) {
            miniprogramSetting = new TabMiniprogramSetting();
        }
        miniprogramSetting.setWxEnterpriseId(wxEnterpriseId);
        miniprogramSetting.setAppId(relationDTO.getWxaAppkey());
        miniprogramSetting.setImageUrl(enterpriseDTO.getMallMiniprogramLogoUrl());
        miniprogramSetting.setMiniprogramName(relationDTO.getAuthName());
        miniprogramSetting.setEnterpriseId(enterpriseId);
        miniprogramSetting.setTitle(relationDTO.getAuthName());

        miniprogramSettingService.saveMiniprogramSetting(miniprogramSetting);
        //刷新门店信息
        ServiceResponse response = this.flushBindStoreByEnterpriseId(enterpriseId, wxEnterpriseId, detailDTO.getStaffId(), ChannelCodeEnum.RIGHT_CHANGE_UNBIND.getCode());
        logger.info("刷新返回信息：{}", JSONObject.toJSONString(response));
        //如果已经在刷新了 需要放入队列再刷新
        if (response.getCode() == 2) {
            logger.info("放入队列刷新：{}", enterpriseId);
            FlushStoreMqDTO flushStoreMqDTO = new FlushStoreMqDTO();
            flushStoreMqDTO.setEnterpriseId(enterpriseId);
            flushStoreMqDTO.setOptStaffId(detailDTO.getStaffId());
            flushStoreMqDTO.setWxEnterpriseId(wxEnterpriseId);
            flushStoreMqDTO.setChannalCode(ChannelCodeEnum.ADMIN_UNBIND.getCode());
            this.flushBindStoreToDelayMq(enterpriseId, flushStoreMqDTO);
        }
        return resp;
    }


    /**
     * 如果是总部的话 校验是否是自己本身 并且可以执行下去
     * 如果是代理 标识可以执行下  如果存在总部且不是保存的不能执行的
     *
     * @param detailDTO
     * @return
     */
    private boolean checkRootEnterprise(WxEnterpriseRelationDetailDTO detailDTO) {
        if (detailDTO.getWxEnterpriseType() == 1) {
            return true;
        }
        //校验总部
        TabHaobanWxEnterpriseRelated tab = wxEnterpriseRelatedMapper.findRootWxEnterpriseByEnterpriseId(detailDTO.getEnterpriseId());
        if (tab == null) {
            return true;
        }
        return detailDTO.getWxEnterpriseRelatedId() != null && tab.getWxEnterpriseRelatedId().equals(detailDTO.getWxEnterpriseRelatedId());

    }

    /**
     * 校验是否包含被其它企业绑定
     *
     * @param detailDTO
     * @return
     */
    private boolean checkHasBindStoreGroup(WxEnterpriseRelationDetailDTO detailDTO) {
        //判断绑定情况
        List<StoreOrGroupInfoDTO> relations = detailDTO.getRelations();
        List<String> needBind = relations.stream().map(dto -> dto.getRelationId()).collect(Collectors.toList());
        List<TabStoreRange> storeRanges = storeRangeService.queryStoreRangeByRelationId(detailDTO.getEnterpriseId(), needBind);
        if (CollectionUtils.isEmpty(storeRanges)) {
            return true;
        }
        logger.info("绑定的部分：{}，{}", detailDTO.getWxEnterpriseId(), JSONObject.toJSONString(storeRanges));
        Set<TabStoreRange> mid = storeRanges.stream().filter(tab -> !tab.getWxEnterpriseId().equals(detailDTO.getWxEnterpriseId())).collect(Collectors.toSet());
        return CollectionUtils.isEmpty(mid);
    }

    @Override
    public void flushBindStoreByDelayMq(String message) {
        logger.info("刷新绑定门店队列开始：{}", message);
        FlushStoreMqDTO flushStoreMqDTO = JSONObject.parseObject(message, FlushStoreMqDTO.class);
        ServiceResponse response = this.flushBindStoreByEnterpriseId(flushStoreMqDTO.getEnterpriseId(), flushStoreMqDTO.getWxEnterpriseId()
                , flushStoreMqDTO.getOptStaffId(), flushStoreMqDTO.getChannalCode());
        logger.info("刷新绑定结束：{}", JSONObject.toJSONString(response));
    }

    @Override
    public void flushBindStoreToDelayMq(String enterpriseId, FlushStoreMqDTO mqDTO) {
        String str = JSONObject.toJSONString(mqDTO);
        String key = FLUSH_HAOBAN_BIND_STORE_MQ_DELAY + ":" + enterpriseId;
        //无需加分布式锁
        Object cache = RedisUtil.getCache(key);
        if (null == cache) {
            logger.info("放入队列，刷新绑定门店：{}", enterpriseId);
            RedisUtil.setCache(key, 1, Long.valueOf(DELAY_TIME));
            GicMQClient clientInstance = GICMQClientUtil.getClientInstance();
            try {
                clientInstance.sendMessage(FLUSH_HAOBAN_BIND_STORE_MQ, str, DELAY_TIME);
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("发送消息异常：{}", str);
            }
        } else {
            logger.info("最近已有在刷新，无需重复刷新：{}", JSONObject.toJSONString(mqDTO));
        }
    }

    /**
     * 校验是否有同时执行 刷新企业
     *
     * @param enterpriseId
     * @param wxEnterpriseId
     * @return
     */
    private boolean checkFlush(String enterpriseId, String wxEnterpriseId) {
        String key = FLUSH_HAOBAN_BIND_STORE + enterpriseId;
        String lockKey = FLUSH_HAOBAN_BIND_STORE + "lock:" + enterpriseId;
        Object cache = RedisUtil.getCache(key);
        if (null != cache) {
            logger.info("已经有人在操作刷新，不能同步操作：{}", enterpriseId);
            return false;
        }
        RedisUtil.lock(lockKey, 2L);
        cache = RedisUtil.getCache(key);
        if (null == cache) {
            RedisUtil.setCache(key, wxEnterpriseId, 120L, TimeUnit.SECONDS);
            RedisUtil.unlock(lockKey);
            return true;
        } else {
            RedisUtil.unlock(lockKey);
            return false;
        }
    }

    @Override
    public ServiceResponse flushBindStoreByEnterpriseId(String enterpriseId, String wxEnterpriseId, String optStaffId, int channalCode) {
        ServiceResponse resp = new ServiceResponse();
        String key = FLUSH_HAOBAN_BIND_STORE + enterpriseId;
        //校验是否有同时执行
        if (!checkFlush(enterpriseId, wxEnterpriseId)) {
            logger.info("有正在执行，不能同时操作：{},{}", enterpriseId, optStaffId);
            resp.setCode(2);
            resp.setMessage("有正在执行，不能同时操作");
            return resp;
        }

        logger.info("刷新绑定门店：eid:{},staffid:{}", enterpriseId, optStaffId);
        List<TabStoreRange> groupInfoDTOS = storeRangeService.queryAllBindRangeByEnterpriseId(enterpriseId);
        if (CollectionUtils.isEmpty(groupInfoDTOS)) {
            RedisUtil.delCache(key);
            logger.info("无需刷新：{}", enterpriseId);
            resp.setCode(3);
            resp.setMessage("没有要刷新的数据");
            return resp;
        }

        //根据微信企业分组 wxEnterpriseId->(List)groupId
        Map<String, Set<String>> relationMapByWxEid = groupInfoDTOS.stream().filter(tab -> tab.getRelationType() == 1)
                .collect(Collectors.groupingBy(tab -> tab.getWxEnterpriseId(), Collectors.mapping(tab -> tab.getRelationId(), Collectors.toSet())));

        //分组所在的企业map groupId->wxEnterpriseId
        Map<String, String> groupMap = groupInfoDTOS.stream().filter(tab -> tab.getRelationType() == 1)
                .collect(Collectors.toMap(tab -> tab.getRelationId(), tab -> tab.getWxEnterpriseId()));
        Set<String> rightGroupIds = groupMap.keySet();


        // 获取所有门店信息
        List<StoreSimpleDTO> storeDtos = storeService.listSimpleStore(enterpriseId, null, null);
        logger.info("所有门店数={},{}", enterpriseId, storeDtos.size());
        Map<String, List<String>> storeMapByGroupId = storeDtos.stream().filter(dto -> StringUtils.isNotBlank(dto.getStoreGroupId())).collect(Collectors.groupingBy(dto -> dto.getStoreGroupId(), Collectors.mapping(dto -> dto.getStoreId(), Collectors.toList())));
        Map<String, StoreSimpleDTO> storeIdMap = storeDtos.stream().collect(Collectors.toMap(dto -> dto.getStoreId(), dto -> dto));

        //获取所有门店分组
        List<PowerStoreGroupDTO> storeGroupList = storeGroupService.getStoreGroupList(enterpriseId, "");
        Map<String, Set<String>> storeGroupChainMap = storeGroupList.stream().collect(Collectors.toMap(dto -> dto.getStoreGroupId(),
                dto -> Arrays.stream(dto.getStoreGroupChain().split("_")).filter(str -> StringUtils.isNotBlank(str)).collect(Collectors.toSet())));

        //获取集团门店的分组 然后根据分组来查询门店
        storeGroupChainMap.forEach((groupId, chainGroupIds) -> {
            Sets.SetView<String> midGroupIds = Sets.intersection(chainGroupIds, rightGroupIds);
            if (CollectionUtils.isEmpty(midGroupIds)) {
                return;
            }
            String midGroupId = null;

            //如果是1的话 加入对应企业

            if (midGroupIds.size() == 1) {
                midGroupId = midGroupIds.iterator().next();
            } else {

                //取交集层级最大 也就是冒泡最近的
                midGroupId = midGroupIds.stream().filter(s -> CollectionUtils.isNotEmpty(storeGroupChainMap.get(s))).max(Comparator.comparing(mid -> storeGroupChainMap.get(mid).size())).get();
            }
            relationMapByWxEid.get(groupMap.get(midGroupId)).add(groupId);
        });

        //组装门店的id
        List<TabStoreRelation> ret = new ArrayList<>();
        relationMapByWxEid.forEach((wxEid, groupIds) -> {
            List<TabStoreRelation> midRelations = groupIds.stream().filter(mid -> storeMapByGroupId.containsKey(mid))
                    .flatMap(midGid -> storeMapByGroupId.get(midGid).stream())
                    .map(storeId -> {
                        StoreSimpleDTO simpleDTO = storeIdMap.get(storeId);
                        TabStoreRelation tabStoreRelation = new TabStoreRelation();
                        tabStoreRelation.setWxEnterpriseId(wxEid);
                        tabStoreRelation.setStoreGroupId(simpleDTO.getStoreGroupId());
                        tabStoreRelation.setStoreId(simpleDTO.getStoreId());
                        tabStoreRelation.setStatusFlag(1);
                        tabStoreRelation.setStoreName(simpleDTO.getStoreName());
                        tabStoreRelation.setEnterpriseId(simpleDTO.getEnterpriseId());
                        tabStoreRelation.setStoreRelationId(ToolUtil.randomUUID());
                        tabStoreRelation.setCreateTime(new Date());
                        tabStoreRelation.setUpdateTime(new Date());
                        return tabStoreRelation;
                    }).collect(Collectors.toList());
            ret.addAll(midRelations);
        });

        storeRangeService.saveStoreRelations(ret, optStaffId, channalCode);
        RedisUtil.delCache(key);
        return resp;
    }

    @Override
    public WxEnterpriseRelationDetailDTO getEnterpriseBindInfo(String wxEnterpriseId, String enterpriseId) {
        TabHaobanWxEnterpriseRelated wxEnterpriseRelated = wxEnterpriseRelatedMapper.findOneByEIdAndWxEid(enterpriseId, wxEnterpriseId);
        if (null == wxEnterpriseRelated) {
            logger.info("企业未绑定：eid:{},weid:{}", enterpriseId, wxEnterpriseId);
            return null;
        }
        List<StoreOrGroupInfoDTO> infoDTOS = storeRangeService.queryBindStoreRange(enterpriseId, wxEnterpriseId);
        WxEnterpriseRelationDetailDTO detailDTO = new WxEnterpriseRelationDetailDTO();
        detailDTO.setRelations(infoDTOS);
        detailDTO.setEnterpriseId(enterpriseId);
        EnterpriseDTO enterpriseDTO = enterpriseService.getEnterpriseById(enterpriseId);
        if (null != enterpriseDTO) {
            detailDTO.setEnterpriseName(enterpriseDTO.getEnterpriseName());
        }
        detailDTO.setMemberOpenCardFlag(wxEnterpriseRelated.getMemberOpenCardFlag());
        detailDTO.setWxEnterpriseType(wxEnterpriseRelated.getWxEnterpriseType());
        detailDTO.setWxEnterpriseRelatedId(wxEnterpriseRelated.getWxEnterpriseRelatedId());
        detailDTO.setClerkEditFlag(wxEnterpriseRelated.getClerkEditFlag());
        return detailDTO;
    }

    @Override
    public List<WxEnterpriseDTO> listWxEnterpriseByEid(String enterpriseId) {
        List<TabHaobanWxEnterprise> wxEnterprises = wxEnterpriseRelatedService.listByEnterpriseId(enterpriseId);
        if (CollectionUtils.isEmpty(wxEnterprises)) {
            logger.info("没有关联企业");
            return null;
        }
        List<WxEnterpriseDTO> ret = EntityUtil.changeEntityListNew(WxEnterpriseDTO.class, wxEnterprises);
        return ret;
    }

    @Override
    public List<WxEnterpriseDTO> listWxEnterpriseByEid(String enterpriseId, String clerkPhoneNumber) {
        List<WxEnterpriseDTO> list = new ArrayList<>();
        ClerkDTO clerk = this.clerkService.getUserByPhoneNumber(clerkPhoneNumber, enterpriseId);
        if (null == clerk || (StringUtils.isBlank(clerk.getHbEnt()) && null != clerk.getSuperAdmin() && 0 == clerk.getSuperAdmin())) {
            logger.info("导购校验不通过,不存在或hbEnt为空,clerkPhoneNumber={},eid={}", clerkPhoneNumber, enterpriseId);
            return list;
        }
        List<WxEnterpriseDTO> dtoList = this.listWxEnterpriseByEid(enterpriseId);
        logger.info("用户管辖微信企业phone={},hbEnt={},dtoList={},super={}", clerkPhoneNumber, clerk.getHbEnt(), JSON.toJSONString(dtoList), clerk.getSuperAdmin());
        if (CollectionUtils.isEmpty(dtoList)) {
            return list;
        }
        if (null != clerk.getSuperAdmin() && 0 == clerk.getSuperAdmin()) {
            for (WxEnterpriseDTO item : dtoList) {
                if (clerk.getHbEnt().contains(item.getWxEnterpriseId())) {
                    list.add(item);
                }
            }
        } else {
            return dtoList;
        }
        return list;
    }

    @Override
    public List<StoreRangeInfoDTO> listAllBindStoreOrGroup(String enterpriseId) {
        List<TabStoreRange> tabStoreRanges = storeRangeService.queryAllBindRangeByEnterpriseId(enterpriseId);
        return EntityUtil.changeEntityListNew(StoreRangeInfoDTO.class, tabStoreRanges);
    }

    @Override
    public Page<BindStoreInfoDTO> pageBindStoreByEnterpriseId(String wxEnterpriseId, String enterpriseId, String search, BasePageInfo pageInfo) {
        Page<TabStoreRelation> relationPage = storeRangeService.pageStoreRelation(enterpriseId, wxEnterpriseId, search, pageInfo);
        if (CollectionUtils.isEmpty(relationPage.getResult())) {
            return null;
        }
        Page<BindStoreInfoDTO> retPage = PageUtil.changeToCurrentPage(relationPage, BindStoreInfoDTO.class);
        List<String> storeIds = relationPage.getResult().stream().map(tab -> tab.getStoreId()).collect(Collectors.toList());
        List<StoreDTO> dtoList = storeService.queryStore(storeIds);
        Map<String, StoreDTO> storeMap = dtoList.stream().collect(Collectors.toMap(dto -> dto.getStoreId(), dto -> dto));

        retPage.getResult().forEach(dto -> {
            StoreDTO storeDTO = storeMap.get(dto.getStoreId());
            if (null == storeDTO) {
                return;
            }
            dto.setStoreGroupName(storeDTO.getStoreGroupName());

        });
        return retPage;
    }

    @Override
    public List<String> listStoreIdByWxEnterpriseId(String wxEnterpriseId) {
        List<String> list = storeRangeService.listStoreIdByWxEnterpriseId(wxEnterpriseId, null);
        return list;
    }

    @Override
    public List<String> listStoreIdByEnterpriseId(String wxEnterpriseId, String enterpriseId) {
        List<String> list = storeRangeService.listStoreIdByWxEnterpriseId(wxEnterpriseId, enterpriseId);
        return list;
    }

    @Override
    public List<StoreOrGroupInfoDTO> listStoreRelationByEnterpriseId(String wxEnterpriseId, String enterpriseId, String search) {
        BasePageInfo basePageInfo = new BasePageInfo();
        basePageInfo.setPageSizeZero(true);
        basePageInfo.setPageSize(0);
        Page<TabStoreRelation> relationPage = storeRangeService.pageStoreRelation(enterpriseId, wxEnterpriseId, search, basePageInfo);
        List<TabStoreRelation> storeRelations = relationPage.getResult();
        if (CollectionUtils.isEmpty(storeRelations)) {
            return new ArrayList<>();
        }
        return storeRelations.stream().map(tab -> {
            StoreOrGroupInfoDTO groupInfoDTO = new StoreOrGroupInfoDTO();
            groupInfoDTO.setRelationId(tab.getStoreId());
            groupInfoDTO.setRelationName(tab.getStoreName());
            groupInfoDTO.setRelationType(2);
            return groupInfoDTO;
        }).collect(Collectors.toList());
    }

    @Override
    public boolean initHistoryEnterprise(String wxEnterpriseId) {
        List<TabHaobanWxEnterpriseRelated> needDealEnts = new ArrayList<>();
        if (StringUtils.isBlank(wxEnterpriseId)) {
            List<TabHaobanWxEnterpriseRelated> allEnts = wxEnterpriseRelatedMapper.queryAllHasGicEnterpriseId();
            needDealEnts = allEnts.stream().filter(dto -> dto.getRangeType() == null || dto.getRangeType() == 0).collect(Collectors.toList());
        } else {
            List<TabHaobanWxEnterpriseRelated> relatedList = wxEnterpriseRelatedMapper.listByWxenterpriseId(wxEnterpriseId);
            needDealEnts = relatedList.stream().filter(dto -> dto.getRangeType() == null || dto.getRangeType() == 0).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(needDealEnts)) {
            logger.info("没有需要处理的企业");
            return true;
        }
        for (TabHaobanWxEnterpriseRelated needDealEnt : needDealEnts) {
            logger.info("初始化企业：{},{}", needDealEnt.getWxEnterpriseId(), needDealEnt.getEnterpriseId());
            try {
                List<StoreGroupDTO> rootStoreGroupId = storeGroupService.getRootStoreGroupId(needDealEnt.getEnterpriseId());
                WxEnterpriseRelationDetailDTO detailDTO = new WxEnterpriseRelationDetailDTO();
                detailDTO.setWxEnterpriseRelatedId(needDealEnt.getWxEnterpriseRelatedId());
                detailDTO.setMemberOpenCardFlag(0);
                detailDTO.setWxEnterpriseType(0);
                detailDTO.setEnterpriseId(needDealEnt.getEnterpriseId());
                detailDTO.setWxEnterpriseId(needDealEnt.getWxEnterpriseId());
                StoreOrGroupInfoDTO groupInfoDTO = new StoreOrGroupInfoDTO();
                groupInfoDTO.setRelationType(1);
                groupInfoDTO.setRelationId(rootStoreGroupId.get(0).getStoreGroupId());
                detailDTO.setRelations(new ArrayList<>());
                detailDTO.getRelations().add(groupInfoDTO);
                this.wxEnterpriseBind(detailDTO);
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("企业历史初始化失败：{}, {}", needDealEnt.getEnterpriseId(), e);
                RedisUtil.setCache("init-fail-enterprise:" + needDealEnt.getWxEnterpriseRelatedId(), needDealEnt);
            }
        }
        return true;
    }

    @Override
    public boolean setClerkEditFlag(String wxEnterprieseRelatedId, int clerkEditFlag) {
        TabHaobanWxEnterpriseRelated tabHaobanWxEnterpriseRelated = wxEnterpriseRelatedService.getByGicEnterpriseIdByEnterpriseRelatedId(wxEnterprieseRelatedId);
        if (tabHaobanWxEnterpriseRelated == null) {
            return false;
        }
        wxEnterpriseRelatedService.setClerkEdit(wxEnterprieseRelatedId, clerkEditFlag);
        return true;
    }

    @Override
    public void saveClerkEditFlag(String wxEnterpriseId, String enterpriseId, int value) {
        this.wxEnterpriseRelatedMapper.saveClerkEditFlag(wxEnterpriseId, enterpriseId, value);
    }

    @Override
    public boolean checkIsGeneral(String wxEnterpriseId, String enterpriseId) {
        //TabHaobanWxEnterpriseRelated enterpriseRelated = wxEnterpriseRelatedService.getByEnterpriseId(wxEnterpriseId, enterpriseId);
        //if (null == enterpriseRelated) {
        //    return false;
        //}
        //return enterpriseRelated.getWxEnterpriseType() == 0;
        return true;
    }

    @Override
    public List<StoreOrGroupInfoDTO> queryBindStoreRange(String enterpriseId, String wxEnterpriseId) {
        return this.storeRangeService.queryBindStoreRange(enterpriseId, wxEnterpriseId);
    }

    @Override
    public List<String> listStoreIdByName(String wxEnterpriseId, String enterpriseId, String storeName) {
        if (StringUtils.isAnyBlank(wxEnterpriseId, enterpriseId, storeName)) {
            return null;
        }
        return this.storeRangeService.listStoreIdByName(wxEnterpriseId, enterpriseId, storeName);
    }

    /**
     * 查询当前商户信息
     *
     * @param wxEnterpriseId
     * @param enterpriseId
     * @return
     */
    @Override
    public com.gic.api.base.commons.ServiceResponse<EnterpriseDetailDTO> queryEnterpriseDetail(String wxEnterpriseId, String enterpriseId) {

        TabHaobanWxEnterpriseRelated oneByEnterpriseId = wxEnterpriseRelatedMapper.findOneByEIdAndWxEid(enterpriseId, wxEnterpriseId);
        if (oneByEnterpriseId == null) {
            return com.gic.api.base.commons.ServiceResponse.failure(HaoBanErrCodeCommon.ERR_8.getCode() + "", HaoBanErrCodeCommon.ERR_8.getMsg());
        }
        EnterpriseDetailDTO enterpriseDetailDTO = EntityUtil.changeEntity(EnterpriseDetailDTO.class, oneByEnterpriseId);
        EnterpriseDTO enterprise = enterpriseService.getEnterpriseById(enterpriseId);
        if (enterprise == null) {
            return com.gic.api.base.commons.ServiceResponse.failure(HaoBanErrCodeCommon.ERR_8.getCode() + "", HaoBanErrCodeCommon.ERR_8.getMsg());
        }
        enterpriseDetailDTO.setEnterpriseName(enterprise.getEnterpriseName());
        enterpriseDetailDTO.setEnterpriseLogo(enterprise.getQcloudImageUrl());
        enterpriseDetailDTO.setBrandName(enterprise.getBrandName());
        enterpriseDetailDTO.setConactsPhone(enterprise.getConactsPhone());
        enterpriseDetailDTO.setCustomerPhone(enterprise.getCustomerPhone());
        return com.gic.api.base.commons.ServiceResponse.success(enterpriseDetailDTO);
    }
    
    @Override
    public int getRelationCount(String enterpriseId) {
        return this.wxEnterpriseRelatedService.getRelationCount(enterpriseId);
    }
}
