package com.kiisoo.ic.customer.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.kiisoo.ic.common.utils.MD5FileUtil;
import com.kiisoo.ic.common.utils.httpClientUtil.HttpClientUtil;
import com.kiisoo.ic.config.WxCpConfiguration;
import com.kiisoo.ic.constants.Constants;
import com.kiisoo.ic.customer.entity.*;
import com.kiisoo.ic.customer.mapper.OpCustomerDOMapper;
import com.kiisoo.ic.customer.mapper.OpVipDOMapper;
import com.kiisoo.ic.domain.service.PrivilageDomainService;
import com.kiisoo.ic.employee.entity.CpUserCustomerRelationDO;
import com.kiisoo.ic.employee.entity.PrivilageCpUserDO;
import com.kiisoo.ic.employee.mapper.PrivilageCpUserDOMapper;
import com.kiisoo.ic.generalize.entity.PoiCustomerContactDataStat;
import com.kiisoo.ic.generalize.entity.PrivilageOrganizational;
import com.kiisoo.ic.generalize.mapper.PoiCustomerContactDataStatMapper;
import com.kiisoo.ic.generalize.mapper.RetailCompanyMapper;
import com.kiisoo.ic.generalize.service.RetailCompanyService;
import com.kiisoo.ic.store.bean.BsdShareCodeResponse;
import com.kiisoo.ic.store.bean.BsdVipResponse;
import com.kiisoo.ic.store.bean.MemberDtlDTO;
import com.kiisoo.ic.store.entity.PoiStore;
import com.kiisoo.ic.store.entity.PoiStoreStaff;
import com.kiisoo.ic.store.entity.PrivilageCpUserStoreDO;
import com.kiisoo.ic.store.mapper.PoiStoreDOMapper;
import com.kiisoo.ic.store.mapper.PrivilageCpUserStoreDOMapper;
import com.kiisoo.ic.synchronous.entity.TurnBackDTO;
import com.kiisoo.ic.synchronous.entity.WxDataDTO;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.kiisoo.ic.config.WxCpConfiguration.APPLICATIONID;

/**
 * @Description: 客户数据概览service
 * @Author: wangyinjia
 * @Date: 2020/4/9
 * @Company: kiisoo
 * @Version: 1.0
 */
@Slf4j
@Service
public class CustomerViewService {

    /**有效*/
    static final Integer VALID = 1;

    static final Integer TEN = 10;

    /**区域*/
    static final Integer LEVEL_REGION = 1;
    /**零售公司*/
    static final Integer LEVEL_COMPANY = 2;
    static final Long LEVEL_COMPANY_L = 2L;
    /**客户*/
    static final Integer LEVEL_CUSTOMER = 3;

    @Autowired
    private RetailCompanyService retailCompanyService;
    /**
     * 用户权限mapper
     */
    @Autowired
    private PrivilageDomainService privilageDomainService;
    /**
     * 用户权限mapper
     */
    @Autowired
    private PrivilageCpUserDOMapper privilageCpUserDOMapper;
    /**
     * 用户权限mapper
     */
    @Autowired
    private PrivilageCpUserStoreDOMapper privilageCpUserStoreDOMapper;

    /**
     * 店铺mapper
     */
    @Autowired
    private PoiStoreDOMapper poiStoreDOMapper;

    /**
     * 客户mapper
     */
    @Autowired
    private OpCustomerDOMapper opCustomerDOMapper;

    /**
     * 拉黑mapper
     */
    @Autowired
    private PoiCustomerContactDataStatMapper poiCustomerContactDataStatMapper;

    /**
     * vip mapper
     */
    @Autowired
    private OpVipDOMapper opVipDOMapper;

    /**
     * 组织mapper
     */
    @Autowired
    private RetailCompanyMapper retailCompanyMapper;


    @Value("${bsd.vip}")
    private String vipBsdUrl;

    /**
     * 客户概览main——趋势图
     * @param userId 用户id
     * @param selectStartTime 选中开始时间
     * @param selectEndTime 选中结束时间
     * @param startTime 柱状图开始时间
     * @param endTime 柱状图结束时间
     * @return 客户概览VO
     */
    public CustomerViewVO selectCustomerViewMain(Long userId, String selectStartTime, String selectEndTime, String startTime, String endTime){
        CustomerViewVO customerViewVO = new CustomerViewVO();
        //shopIds
        List<Long> shopIds = getShopIds(userId);
        if(CollectionUtils.isEmpty(shopIds)){
            return customerViewVO;
        }
        //柱状图好友趋势图
        List<OpCustomer> customerList = opCustomerDOMapper.selectCustomerList(shopIds, null, null, startTime, endTime);

        //会员总数
        Long vipCount = opVipDOMapper.selectVipCountNew();
        customerViewVO.setAllVipCount(vipCount);

        //设置趋势柱状图list
        List<OpCustomer> validCustomerList = customerList.stream().filter(customerDO -> VALID.equals(customerDO.getValidType())).collect(Collectors.toList());
        handleChartData(customerList, validCustomerList, customerViewVO);

        //设置新增好友，新增好友（去重），vip人数
        setCustomerViewData(customerViewVO, customerList, validCustomerList, selectStartTime, selectEndTime);

        return customerViewVO;
    }

    /**
     * 客户概览——Top榜
     * @param userId 用户id
     * @param selectStartTime 选中开始时间
     * @param selectEndTime 选中结束时间
     * @return 客户概览VO
     */
    public CustomerViewVO selectCustomerViewMainDate(Long userId, String selectStartTime, String selectEndTime){
        CustomerViewVO customerViewVO = new CustomerViewVO();
        //shopIds
        List<Long> shopIds = getShopIds(userId);
        if(CollectionUtils.isEmpty(shopIds)){
            return customerViewVO;
        }
        //柱状图好友list
        List<OpCustomer> customerList = opCustomerDOMapper.selectCustomerList(shopIds, null, null, selectStartTime, selectEndTime);

        //零售公司店均新增
        List<CustomerViewCompanyVO> shopAverageNewCustomerList = getOrgShopAvgNewCustomerList(customerList, userId);
        customerViewVO.setCompanyShopAverageNewCustomerList(shopAverageNewCustomerList);

        //前十名排行list等
        List<CustomerViewCompanyVO> orgNewCustomerList = getOrgNewCustomerList(customerList);
        List<CustomerViewShopVO> shopNewCustomerList = getShopNewCustomerList(customerList);
        List<CustomerViewZeroExtendVO> zeroExtendList = getZeroExtendList(customerList, shopIds);
        customerViewVO.setOrgNewCustomerList(orgNewCustomerList);
        customerViewVO.setShopNewCustomerList(shopNewCustomerList);
        customerViewVO.setZeroExtendList(zeroExtendList);

        return customerViewVO;
    }


    /**
     * 客户概览——拉黑数
     * @param userId 用户id
     * @return 客户概览VO
     */
    public CustomerViewVO getDelNum(Long userId){
        List<Long> shopIds = getShopIds(userId);
        //删除拉黑数
        Long validDeleteCustomerCount = poiCustomerContactDataStatMapper.selectDeleteCustomer(shopIds).stream()
                .filter(contactDO -> contactDO.getNegativeFeedbackCnt() != null)
                .map(PoiCustomerContactDataStat::getNegativeFeedbackCnt).mapToLong(a -> a).sum();
        //返回对象
        CustomerViewVO result = new CustomerViewVO();
        result.setValidDeleteCustomer(validDeleteCustomerCount);
        return result;
    }

    /**
     * shopIds
     * @param userId 用户id
     * @return shopIds
     */
    public List<Long> getShopIds(Long userId){
        List<Long> shopIds = privilageDomainService.listUserDatePermission(userId);
        return shopIds;
    }

    /**
     * 新增好友，好友总数，拉黑数，vip人数
     * @param customerViewVO 客户概览VO
     * @param customerList 新增好友list
     * @param validCustomerList 新增好友（去重）list
     * @param selectStartTime 选中开始时间
     * @param selectEndTime 选中结束时间
     */
    public void setCustomerViewData(CustomerViewVO customerViewVO, List<OpCustomer> customerList,
                                    List<OpCustomer> validCustomerList, String selectStartTime, String selectEndTime){
        //新增好友
        Long newCustomerCount = customerList.stream().filter(customerDO -> filterCustomerByRegisterTime(customerDO, selectStartTime, selectEndTime)).count();
        customerViewVO.setNewCustomer(newCustomerCount);
        //新增好友(去重)
        Long newValidCustomerCount = validCustomerList.stream().filter(customerDO -> filterCustomerByRegisterTime(customerDO, selectStartTime, selectEndTime)).count();
        customerViewVO.setNewValidCustomer(newValidCustomerCount);

    }

    /**
     * 选中时间过滤客户
     * @param customerDO 好友DO
     * @param selectStartTime 选中开始时间
     * @param selectEndTime 选中结束时间
     * @return true/false
     */
    public boolean filterCustomerByRegisterTime(OpCustomer customerDO, String selectStartTime, String selectEndTime){
        Date registerDate = customerDO.getRegisterTime();
        if(registerDate == null){
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            long startTime = sdf.parse(selectStartTime).getTime();
            long endTime = sdf.parse(selectEndTime).getTime();
            long registerTime = registerDate.getTime();
            return startTime <= registerTime && endTime >= registerTime;
        }catch (Exception e){
            log.error("格式化时间出错", e);
            return false;
        }
    }

    /**
     * 店铺组织信息list
     * @param shopIds 店铺ids
     * @param companyFlag 零售公司
     * @param regionFlag 区域
     * @return 店铺组织信息list
     */
    public List<ShopOrgInfoVO> getOrgInfoByShopIds(List<Long> shopIds, Boolean companyFlag, Boolean regionFlag){
        //店铺-客户组织list
        List<Long>  newShopIds = shopIds.stream().distinct().collect(Collectors.toList());

        List<ShopOrgInfoVO> shopOrgInfoList = opCustomerDOMapper.selectCustomerOrgByShopIds(newShopIds, LEVEL_CUSTOMER);
        if(companyFlag == null || !companyFlag){
            return shopOrgInfoList;
        }
        //零售公司list
        List<Long> companyIds = shopOrgInfoList.stream().map(ShopOrgInfoVO::getCompanyId).collect(Collectors.toList());
        List<PrivilageOrganizational> companyList = new ArrayList<>();
        if(companyIds.size() > 0){
            QueryWrapper<PrivilageOrganizational> orgWrapper = new QueryWrapper<>();
            orgWrapper.eq("level", LEVEL_COMPANY);
            orgWrapper.in("id", companyIds);
            companyList = retailCompanyMapper.selectList(orgWrapper);
        }
        Map<Long, String> companyNameMap = companyList.stream().collect(Collectors.toMap(PrivilageOrganizational::getId, PrivilageOrganizational::getName));
        shopOrgInfoList.stream().filter(shopOrgDO -> shopOrgDO.getCompanyId() != null).forEach(shopOrgDO -> shopOrgDO.setCompanyName(companyNameMap.get(shopOrgDO.getCompanyId())));
        //区域list
        if(regionFlag == null || !regionFlag){
            return shopOrgInfoList;
        }

        return shopOrgInfoList;
    }

    /**
     * 公司店均新增柱状图
     * @param newCustimerList 好友list
     * @param userId 用户id
     * @return 公司店均新增list
     */
    public List<CustomerViewCompanyVO> getOrgShopAvgNewCustomerList(List<OpCustomer> newCustimerList, Long userId){
        List<CustomerViewCompanyVO> orgShopAvgNewCustomerList = new ArrayList<>();
        //初始化所有零售公司
        List<PrivilageOrganizational> companyList = retailCompanyService.listOfRetailOrg(userId, null, null, null).stream().filter(org -> LEVEL_COMPANY_L.equals(org.getLevel())).distinct().collect(Collectors.toList());
        companyList.forEach(companyDO -> {
            CustomerViewCompanyVO companyVO = new CustomerViewCompanyVO();
            companyVO.setOrgId(companyDO.getId());
            companyVO.setOrgName(companyDO.getName());
            companyVO.setNewCustomerCount(0);
            orgShopAvgNewCustomerList.add(companyVO);
        });
        //店铺id-新增好友数map
        Map<Long, Long> shopIdCountMap = newCustimerList.stream().collect(Collectors.groupingBy(OpCustomer::getShopId, Collectors.counting()));
        //店铺id→零售公司名称
        List<Long> shopIds = newCustimerList.stream().map(OpCustomer::getShopId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(shopIds)){
            return orgShopAvgNewCustomerList;
        }
        //零售公司id-公司店铺list map
        List<ShopOrgInfoVO> shopOrgInfoList = getOrgInfoByShopIds(shopIds, true, null);
        Map<Long, List<ShopOrgInfoVO>> companyShopListMap = shopOrgInfoList.stream().distinct().collect(Collectors.groupingBy(ShopOrgInfoVO::getCompanyId));
        //每个公司店均新增数
        companyShopListMap.forEach((companyId,companyShopList) -> {
            CustomerViewCompanyVO orgViewDO = new CustomerViewCompanyVO();
            orgViewDO.setOrgId(companyId);
            orgViewDO.setOrgName(companyShopList.get(0).getCompanyName());
            AtomicInteger newCustomerCount = new AtomicInteger(0);
            companyShopList.forEach(companyShopVO -> {
                Long shopId = companyShopVO.getShopId();
                int tmpCount = shopIdCountMap.get(shopId) == null ? 0 : Math.toIntExact(shopIdCountMap.get(shopId));
                newCustomerCount.updateAndGet(v -> v + tmpCount);
            });
            //平均
            if(companyShopList.size() > 0){
                newCustomerCount.updateAndGet(v -> Math.round(v / (float)companyShopList.size()));
            }
            orgViewDO.setNewCustomerCount(newCustomerCount.get());
            orgShopAvgNewCustomerList.stream().filter(orgShopAvg -> orgShopAvg.getOrgName().equals(orgViewDO.getOrgName())).forEach(orgShopAvg -> orgShopAvg.setNewCustomerCount(orgViewDO.getNewCustomerCount()));
        });
        //公司店均
        return orgShopAvgNewCustomerList;
    }

    /**
     * 趋势柱状图数据
     * @param customerList 好友list
     * @param validCustomerList 好友（去重）list
     * @param customerViewVO 概览VO
     */
    public void handleChartData(List<OpCustomer> customerList, List<OpCustomer> validCustomerList, CustomerViewVO customerViewVO){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Map<String, Long> customerSizeMap = customerList.stream().filter(customer -> customer.getRegisterTime() != null).collect(Collectors.groupingBy(customer -> sdf.format(customer.getRegisterTime()), Collectors.counting()));
        Map<String, Long> validCustomerSizeMap = validCustomerList.stream().filter(customer -> customer.getRegisterTime() != null).collect(Collectors.groupingBy(customer -> sdf.format(customer.getRegisterTime()), Collectors.counting()));
        List<OpCustomerSimpleVO> simpleCustomerList = new ArrayList<>();
        List<OpCustomerSimpleVO> simpleValidCustomerList = new ArrayList<>();
        customerSizeMap.forEach((k,v) -> {
            OpCustomerSimpleVO customerSimpleVO = new OpCustomerSimpleVO();
            customerSimpleVO.setRegisterTime(k);
            customerSimpleVO.setCustomerSize(v);
            simpleCustomerList.add(customerSimpleVO);
        });
        validCustomerSizeMap.forEach((k,v) -> {
            OpCustomerSimpleVO validCustomerSimpleVO = new OpCustomerSimpleVO();
            validCustomerSimpleVO.setRegisterTime(k);
            validCustomerSimpleVO.setCustomerSize(v);
            simpleValidCustomerList.add(validCustomerSimpleVO);
        });
        customerViewVO.setCustomerList(simpleCustomerList);
        customerViewVO.setValidCustomerList(simpleValidCustomerList);
    }

    /**
     * 零售公司新增排行list
     * @param newCustimerList 新增好友list
     * @return 零售公司新增排行list
     */
    List<CustomerViewCompanyVO> getOrgNewCustomerList(List<OpCustomer> newCustimerList){
        List<CustomerViewCompanyVO> orgNewCustomerList = new ArrayList<>();
        //店铺id-新增好友数map
        Map<Long, Long> shopIdCountMap = newCustimerList.stream().collect(Collectors.groupingBy(OpCustomer::getShopId, Collectors.counting()));
        //店铺id→零售公司名称
        List<Long> shopIds = newCustimerList.stream().map(OpCustomer::getShopId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(shopIds)){
            return orgNewCustomerList;
        }
        //零售公司id-公司店铺list map
        List<ShopOrgInfoVO> shopOrgInfoList = getOrgInfoByShopIds(shopIds, true, null);
        Map<Long, List<ShopOrgInfoVO>> companyShopListMap = shopOrgInfoList.stream().distinct().collect(Collectors.groupingBy(ShopOrgInfoVO::getCompanyId));
        //每个公司店均新增数
        List<CustomerViewCompanyVO> tmpList = new ArrayList<>();
        companyShopListMap.forEach((companyId,companyShopList) -> {
            CustomerViewCompanyVO orgViewDO = new CustomerViewCompanyVO();
            orgViewDO.setOrgId(companyId);
            orgViewDO.setOrgName(companyShopList.get(0).getCompanyName());
            AtomicInteger newCustomerCount = new AtomicInteger(0);
            companyShopList.forEach(companyShopVO -> {
                Long shopId = companyShopVO.getShopId();
                int tmpCount = shopIdCountMap.get(shopId) == null ? 0 : Math.toIntExact(shopIdCountMap.get(shopId));
                newCustomerCount.updateAndGet(v -> v + tmpCount);
            });
            //平均
            if(companyShopList.size() > 0){
                newCustomerCount.updateAndGet(v -> Math.round(v / (float)companyShopList.size()));
            }
            orgViewDO.setNewCustomerCount(newCustomerCount.get());
            tmpList.add(orgViewDO);
        });
        //排序
        orgNewCustomerList = tmpList.stream().sorted(Comparator.comparing(CustomerViewCompanyVO::getNewCustomerCount).reversed()).limit(TEN).collect(Collectors.toList());
        return orgNewCustomerList;
    }

    /**
     * 店铺新增排行list
     * @param newCustimerList 新增好友list
     * @return 店铺新增排行list
     */
    List<CustomerViewShopVO> getShopNewCustomerList(List<OpCustomer> newCustimerList){
        //店铺分组
        Map<Long, List<OpCustomer>> shopIdMap = newCustimerList.stream().collect(Collectors.groupingBy(OpCustomer::getShopId));
        List<Long> shopIds = newCustimerList.stream().map(OpCustomer::getShopId).collect(Collectors.toList());
        if(shopIds.size() == 0){
            return new ArrayList<>();
        }
        Map<Long, String> shopNameMap = poiStoreDOMapper.selectBatchIds(shopIds).stream().collect(Collectors.toMap(PoiStore::getId, PoiStore::getName));
        List<CustomerViewShopVO> shopViewList = new ArrayList<>();
        shopIdMap.forEach((k,v) -> {
            CustomerViewShopVO shopVO = new CustomerViewShopVO();
            shopVO.setShopId(k);
            shopVO.setNewCustomerCount(v.size());
            shopVO.setShopName(shopNameMap.get(k));
            shopViewList.add(shopVO);
        });
        //排序
        List<CustomerViewShopVO> shopNewCustomerList = shopViewList.stream().sorted(Comparator.comparing(CustomerViewShopVO::getNewCustomerCount).reversed()).limit(TEN).collect(Collectors.toList());
        return shopNewCustomerList;
    }

    /**
     * 零推广list
     * @param newCustimerList 新增好友list
     * @param shopIds 管辖店铺ids
     * @return 零推广list
     */
    List<CustomerViewZeroExtendVO> getZeroExtendList(List<OpCustomer> newCustimerList, List<Long> shopIds){
        List<CustomerViewZeroExtendVO> zeroExtendList = new ArrayList<>();
        //有推广的店铺ids
        List<Long> notZeroShopIds = newCustimerList.stream().map(OpCustomer::getShopId).distinct().collect(Collectors.toList());
        //零售公司id-公司店铺list map
        List<ShopOrgInfoVO> shopOrgInfoList = getOrgInfoByShopIds(shopIds, true, null);
        Map<Long, List<ShopOrgInfoVO>> companyShopListMap = shopOrgInfoList.stream().distinct().collect(Collectors.groupingBy(ShopOrgInfoVO::getCompanyId));

        List<CustomerViewZeroExtendVO> tmpZeroExtendList = new ArrayList<>();
        companyShopListMap.forEach((companyId, companyShopList) -> {
            List<Long> tmpShopIds = companyShopList.stream().map(ShopOrgInfoVO::getShopId).distinct().collect(Collectors.toList());
            int tmpShopCount = tmpShopIds.size();
            CustomerViewZeroExtendVO zeroExtendVO = new CustomerViewZeroExtendVO();
            zeroExtendVO.setOrgId(companyId);
            zeroExtendVO.setOrgName(companyShopList.get(0).getCompanyName());
            zeroExtendVO.setAllShopCount(tmpShopCount);
            //推广的店铺
            tmpShopIds.retainAll(notZeroShopIds);
            zeroExtendVO.setZeroShopCount(tmpShopCount - tmpShopIds.size());
            tmpZeroExtendList.add(zeroExtendVO);
        });
        zeroExtendList = tmpZeroExtendList.stream()
                .filter(zeroExtendDO -> zeroExtendDO.getZeroShopCount() > 0)
                .sorted(Comparator.comparing(CustomerViewZeroExtendVO::getZeroShopCount).reversed())
                .limit(TEN).collect(Collectors.toList());
        return zeroExtendList;
    }

    /**
     * 零推广list
     * @param newCustimerList 新增好友list
     * @param shopIds 管辖店铺ids
     * @param regionId 区域
     * @param companyId 零售公司
     * @param customerId 客户组织
     * @return 零推广list
     */
    List<CustomerViewZeroExtendVO> getZeroExtendList2(List<OpCustomer> newCustimerList, List<Long> shopIds, int pageNum, int pageSize, Long regionId , Long companyId, Long customerId){
        //有推广的店铺ids
        List<Long> notZeroShopIds = newCustimerList.stream().map(OpCustomer::getShopId).distinct().collect(Collectors.toList());
        //无推广id
        shopIds.removeAll(notZeroShopIds);
        PageHelper.startPage(pageNum,pageSize);
        List<CustomerViewZeroExtendVO> list = opCustomerDOMapper.selectOrgInfoByShopIds(shopIds, regionId, companyId, customerId);
        AtomicInteger number = new AtomicInteger(1 + ((pageNum-1) * pageSize));
        //求分页总数
        Page<CustomerViewZeroExtendVO> pageList = (Page<CustomerViewZeroExtendVO>)list;
        Long totalSize = pageList.getTotal();
        list.forEach(item -> {
            item.setTotalSize(totalSize);
            item.setNumber(number.get());
            number.incrementAndGet();
        });

        return list;
    }

    /**
     * 找到推广为0
     * @param regionId 大区id
     * @param companyId 公司id
     * @param customerId 客户id
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public List<CustomerViewZeroExtendVO> zeroExtendList(long userId, Long regionId , Long companyId, Long customerId,
                                                         String startTime, String endTime, int pageNum, int pageSize){
        Set<Long> shopIds;
        //根据店铺查询所有扫码客户信息
        if(customerId != null){
            shopIds = getCompanyShop(customerId, userId);
        }else if(companyId != null){
            shopIds = getCompanyShop(companyId, userId);
        } else if(regionId != null){
            shopIds = getCompanyShop(regionId, userId);
        }else{
            //查询用户权限店铺
            shopIds = new HashSet<>(privilageDomainService.listUserDatePermission(userId));
        }
        if(CollectionUtils.isEmpty(shopIds)){
            return new ArrayList<>();
        }
        //柱状图好友list
        List<OpCustomer> customerList = opCustomerDOMapper.selectCustomerList(new ArrayList<>(shopIds), null, null, startTime, endTime);
        List<CustomerViewZeroExtendVO> zeroExtendList = getZeroExtendList2(customerList, new ArrayList<>(shopIds),pageNum,pageSize, regionId, companyId, customerId);
        return zeroExtendList;
    }

    public Set<Long> getCompanyShop(Long companyId, long userId){
        //找到最小公司
        Set<Long> param = new HashSet<>();
        param.add(companyId);
        Set<Long> minCompany = new HashSet<>();
        retailCompanyService.getMinCompany(param,minCompany);

        //找到公司店铺
        List<PoiStore> shops = new ArrayList<>();
        minCompany.forEach(item -> {
            shops.addAll(retailCompanyService.selectCustomerShopByCompany(item));
        });
        //公司店铺和权限做交集
        Set<Long> shopIds = shops.stream().map(p -> p.getId()).collect(Collectors.toSet());
        List<Long> userAllShops = privilageDomainService.listUserDatePermission(userId);
        shopIds.retainAll(userAllShops);
        return shopIds;
    }

    /**
     * 客户概览main
     * @return 客户概览VO
     */
    public CustomerViewVO getAllCount() {
        Long all = privilageCpUserDOMapper.selectAllCount();
        Long dis = privilageCpUserDOMapper.selectDistinctAllCount();
        CustomerViewVO result = new CustomerViewVO();
        result.setAllCustomer(all);
        result.setAllValidCustomer(dis);
        return result;
    }

    public void syncAllCount() throws WxErrorException, InterruptedException {
        //初始化线程
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(8);

        //查询现有企业微信账号
        List<PrivilageCpUserDO> privilageCpUserDOS = privilageCpUserDOMapper.selectList(null);
        Map<String,PrivilageCpUserDO> cpUserIdMap = new HashMap<>();
        for (PrivilageCpUserDO privilageCpUserDO : privilageCpUserDOS) {
            cpUserIdMap.put(privilageCpUserDO.getCpUserId(),privilageCpUserDO);
        }
        WxCpService wxCpService = WxCpConfiguration.getCpService(APPLICATIONID);
        WxCpExternalContactService externalContactService = wxCpService.getExternalContactService();
        //查询企业微信已配置联系我的用户
        List<String> cpUserIds = externalContactService.listFollowUser();

        if (CollectionUtils.isNotEmpty(cpUserIds)){
            //分组
            final List<List<String>> afterPageList = com.kiisoo.ic.utils.CollectionUtils.portListByQuantity(cpUserIds, 100);
            //定义线程池长度
            int threadPoolSize = afterPageList.size();
            //定义countDownLatch
            final CountDownLatch countDownLatch = new CountDownLatch(threadPoolSize);
            for (int i = 0; i < afterPageList.size(); i++) {
                List<String> ids = afterPageList.get(i);
                newFixedThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            for (String cpUserId : ids) {
                                List<String> customerStrs;
                                try {
                                    //获取客户联系人
                                    customerStrs = externalContactService.listExternalContacts(cpUserId);
                                }catch (Exception e){
                                    PrivilageCpUserDO privilageCpUserDO = cpUserIdMap.get(cpUserId);
                                    if (privilageCpUserDO != null){
                                        privilageCpUserDO.setStatus(9);
                                        privilageCpUserDOMapper.updateById(privilageCpUserDO);
                                    }
                                    continue;
                                }
                                if (CollectionUtils.isEmpty(customerStrs)){
                                    continue;
                                }
                                PrivilageCpUserDO privilageCpUserDO = cpUserIdMap.get(cpUserId);
                                if (privilageCpUserDO == null){
                                    //企业微信账号不存在，创建一个账号
                                    privilageCpUserDO = new PrivilageCpUserDO();
                                    privilageCpUserDO.setCpUserId(cpUserId);
                                    privilageCpUserDO.setStatus(1);
                                    privilageCpUserDOMapper.insert(privilageCpUserDO);
                                }
                                //批量添加账号
                                for (String customerStr : customerStrs) {
                                    CpUserCustomerRelationDO cpUserCustomerRelationDO = privilageCpUserDOMapper.selectCpUserCustomerRelation(customerStr, cpUserId, privilageCpUserDO.getId());
                                    if (cpUserCustomerRelationDO == null){
                                        privilageCpUserDOMapper.insertCpUserCustomerRelation(customerStr,cpUserId,privilageCpUserDO.getId());
                                    }
                                }
                                //移除已经请求过的数据库内账号
                                cpUserIdMap.remove(cpUserId);
                            }
                        } catch (Exception e) {
                            log.error("同步客户明细", e);
                        } finally {
                            //每次减去一，避免死锁
                            countDownLatch.countDown();
                        }
                    }
                });
            }
            countDownLatch.await();
            Set<String> removeCpUserIds = cpUserIdMap.keySet();
            for (String cpUserId:removeCpUserIds){
                PrivilageCpUserDO privilageCpUserDO = cpUserIdMap.get(cpUserId);
                if (privilageCpUserDO != null){
                    //删除
                    privilageCpUserDOMapper.deleteById(privilageCpUserDO.getId());
                }
            }
        }
    }

    public void syncAliveCount() throws WxErrorException, InterruptedException {
        //初始化线程
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(8);

        //查询现有企业微信账号
        List<PrivilageCpUserStoreDO> relations = privilageCpUserStoreDOMapper.selectList(null);
        List<Long> ids = relations.stream().map(relation -> relation.getCpUserId()).collect(Collectors.toList());
        QueryWrapper<PrivilageCpUserDO> qw = new QueryWrapper<>();
        qw.ne("status",9).in("id",ids);
        List<PrivilageCpUserDO> privilageCpUserDOS = privilageCpUserDOMapper.selectList(null);
        WxCpService wxCpService = WxCpConfiguration.getCpService(APPLICATIONID);
        WxCpExternalContactService externalContactService = wxCpService.getExternalContactService();

        if (CollectionUtils.isNotEmpty(privilageCpUserDOS)){
            //分组
            final List<List<PrivilageCpUserDO>> afterPageList = com.kiisoo.ic.utils.CollectionUtils.portListByQuantity(privilageCpUserDOS, 100);
            //定义线程池长度
            int threadPoolSize = afterPageList.size();
            //定义countDownLatch
            final CountDownLatch countDownLatch = new CountDownLatch(threadPoolSize);
            for (int i = 0; i < afterPageList.size(); i++) {
                List<PrivilageCpUserDO> cpUserDOS = afterPageList.get(i);
                newFixedThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            //查询企业微信已配置联系我的用户
                            for (PrivilageCpUserDO privilageCpUserDO : cpUserDOS) {
                                List<String> customerStrs;
                                try {
                                    //获取客户联系人
                                    customerStrs = externalContactService.listExternalContacts(privilageCpUserDO.getCpUserId());
                                }catch (Exception e){
                                    privilageCpUserDO.setStatus(9);
                                    privilageCpUserDOMapper.updateById(privilageCpUserDO);
                                    continue;
                                }
                                if (CollectionUtils.isEmpty(customerStrs)){
                                    continue;
                                }
                                //批量添加账号
                                for (String customerStr : customerStrs) {
                                    CpUserCustomerRelationDO cpUserCustomerRelationDO = privilageCpUserDOMapper.selectCpUserCustomerRelation(customerStr, privilageCpUserDO.getCpUserId(), privilageCpUserDO.getId());
                                    if (cpUserCustomerRelationDO == null){
                                        privilageCpUserDOMapper.insertCpUserCustomerRelation(customerStr,privilageCpUserDO.getCpUserId(),privilageCpUserDO.getId());
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.error("同步客户明细", e);
                        } finally {
                            //每次减去一，避免死锁
                            countDownLatch.countDown();
                        }
                    }
                });
            }
            countDownLatch.await();
        }
    }

    /**
     * 同步会员数据
     * @return
     */
    public void syncVip() throws InterruptedException {
        //查询现有企业微信账号
        List<OpCustomer> customers = opCustomerDOMapper.selectList(null);

        //查询企业微信已配置联系我的用户
        int i = 0;
        for (OpCustomer customer : customers) {
            i++;
            try{
                String wechatUniId = customer.getWechatUniId();
                if (StringUtils.isBlank(wechatUniId)){
                    continue;
                }
                if (customer.getMemberId() != 0L){
                    continue;
                }
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String message = HttpClientUtil.httpPost(vipBsdUrl + MD5FileUtil.getMD5String("BOSIDENG" + sdf.format(new Date()))+"&unionId="+wechatUniId, "").getMessage();
                if (StringUtils.isBlank(message)){
                    continue;
                }
                System.out.println(i+"/"+customers.size()+"------"+message);
                JSONObject vipJson = JSONObject.parseObject(message);
                BsdVipResponse bsdResponse = vipJson.toJavaObject(BsdVipResponse.class);
                if (bsdResponse.getSuccess() && bsdResponse.getData() != null){
                    MemberDtlDTO data = bsdResponse.getData();

                    OpCustomer opCustomer = new OpCustomer(data.getMemberName(), data.getMobileNo());
                    opCustomer.setUpdateBy(Constants.SYS_OPERATION);

                    // 根据手机号码去重
                    QueryWrapper<OpVip> wrapper = new QueryWrapper<>();
                    wrapper.eq("phone", data.getMobileNo()).last("limit 1");
                    OpVip opVip = opVipDOMapper.selectOne(wrapper);
                    OpVip opVip1 = new OpVip();
                    opVip1.setStatus(1L);
                    opVip1.setLevel(data.getMemberLevel().toString());
                    opVip1.setPhone(data.getMobileNo());
                    opVip1.setName(data.getMemberName());
                    opVip1.setBirthday(data.getBirthday());
                    opVip1.setRegisterTime(data.getCreateDate());
                    if (opVip == null) {
                        //数据库没有这个数据--新建数据
                        opVip1.setCreateBy(Constants.SYS_OPERATION);
                        opVip1.setCreateTime(new Date());
                        opVipDOMapper.insert(opVip1);
                        //有vip信息就绑定信息
                        opCustomer.setMemberId(opVip1.getId());
                    } else {
                        opVip1.setId(opVip.getId());
                        opVip1.setUpdateTime(new Date());
                        opVip1.setUpdateBy(Constants.SYS_OPERATION);
                        opVipDOMapper.updateById(opVip1);
                        //有vip信息就绑定信息
                        opCustomer.setMemberId(opVip.getId());
                    }
                    QueryWrapper<OpCustomer> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("wechat_uni_id", wechatUniId);
                    opCustomerDOMapper.update(opCustomer, wrapper1);
                }
            }catch (Exception e){
                log.error("同步vip出错",e);
            }
        }
    }
}
