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

import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.commons.util.ToolUtil;
import com.gic.enterprise.api.dto.StoreGroupDTO;
import com.gic.enterprise.api.service.StoreGroupService;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.common.utils.PageUtil;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.dto.StoreOrGroupInfoDTO;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanStoreRangeMapper;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanStoreRelationMapper;
import com.gic.haoban.manage.service.entity.TabStoreRange;
import com.gic.haoban.manage.service.entity.TabStoreRelation;
import com.gic.haoban.manage.service.service.StaffClerkRelationService;
import com.gic.haoban.manage.service.service.StoreRangeService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Created 2021/4/9.
 *
 * @author hua
 */
@Service
public class StoreRangeServiceImpl implements StoreRangeService {

    private static final Logger logger = getLogger(StoreRangeServiceImpl.class);

    @Autowired
    private TabHaobanStoreRangeMapper tabHaobanStoreRangeMapper;

    @Autowired
    private TabHaobanStoreRelationMapper tabHaobanStoreRelationMapper;

    @Autowired
    private StaffClerkRelationService staffClerkRelationService;
    @Autowired
    private StoreGroupService storeGroupService;


    @Override
    public boolean saveStoreRange(List<StoreOrGroupInfoDTO> relations, String enterpriseId, String wxEnterpriseId) {
        tabHaobanStoreRangeMapper.deleteByEnterpriseId(wxEnterpriseId, enterpriseId);
        List<TabStoreRange> ranges = relations.stream().map(dto -> {
            TabStoreRange tabStoreRange = new TabStoreRange();
            tabStoreRange.setEnterpriseId(enterpriseId);
            tabStoreRange.setWxEnterpriseId(wxEnterpriseId);
            tabStoreRange.setRelationId(dto.getRelationId());
            tabStoreRange.setRelationType(dto.getRelationType());
            tabStoreRange.setStoreRangeId(ToolUtil.randomUUID());
            return tabStoreRange;
        }).collect(Collectors.toList());
        tabHaobanStoreRangeMapper.insertBatch(ranges);
        return true;
    }

    @Override
    public List<StoreOrGroupInfoDTO> queryBindStoreRange(String enterpriseId, String wxEnterpriseId) {
        List<TabStoreRange> tabStoreRanges = tabHaobanStoreRangeMapper.queryByEnterpriseId(wxEnterpriseId, enterpriseId);
        if (CollectionUtils.isEmpty(tabStoreRanges)) {
            return null;
        }
        return tabStoreRanges.stream().map(tab -> {
            StoreOrGroupInfoDTO infoDTO = new StoreOrGroupInfoDTO();
            infoDTO.setRelationId(tab.getRelationId());
            infoDTO.setRelationType(tab.getRelationType());
            return infoDTO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<TabStoreRange> queryAllBindRangeByEnterpriseId(String enterpriseId) {
        List<TabStoreRange> tabStoreRanges = tabHaobanStoreRangeMapper.queryByEnterpriseId(null, enterpriseId);
        if (CollectionUtils.isEmpty(tabStoreRanges)) {
            return null;
        }
        return tabStoreRanges;
    }

    @Override
    public Page<TabStoreRelation> pageStoreRelation(String enterpriseId, String wxEnterpriseId, String search, BasePageInfo pageInfo) {
        PageHelper.startPage(pageInfo);
        List<TabStoreRelation> storeRelations = tabHaobanStoreRelationMapper.searchStoreRange(wxEnterpriseId, enterpriseId, search);
        Page<TabStoreRelation> retPage = PageUtil.changePageHelperToCurrentPage(new PageInfo<>(storeRelations));
        return retPage;
    }

    @Override
    public boolean saveStoreRelations(List<TabStoreRelation> list, String optStaffId, int channelCode) {
        if (CollectionUtils.isEmpty(list)) {
            logger.info("没有需要保存的: 有问题的授权");
            return true;
        }
        String enterpriseId = list.get(0).getEnterpriseId();
        String wxEnterpriseId = list.get(0).getWxEnterpriseId();
        //更新前绑定门店列表
        List<TabStoreRelation> storeRelations = tabHaobanStoreRelationMapper.listStoreRange(enterpriseId);
        Map<String, Set<String>> oldStoreIdByMap = storeRelations.stream().collect(Collectors.groupingBy(TabStoreRelation::getWxEnterpriseId, Collectors.mapping(dto -> dto.getStoreId(), Collectors.toSet())));

        //根据wxEnterpriseId 分组
        Map<String, Set<String>> newStoreIdBywxEnterpriseMap = list.stream().collect(Collectors.groupingBy(TabStoreRelation::getWxEnterpriseId, Collectors.mapping(dto -> dto.getStoreId(), Collectors.toSet())));
        //所有就的门店old绑定列表
        Map<String, Set<String>> oldStoreIdBywxEnterpriseMap = getOldStoreIdsByWxEnterpriseId(enterpriseId, oldStoreIdByMap);

        //需要解绑门店
        Set<String> needUnBindStoreIds = new HashSet<>();
        //需要新增权限门店
        Set<String> needAddStoreIds = new HashSet<>();
        oldStoreIdBywxEnterpriseMap.forEach((wxEid, oldStoreIds) -> {
            Set<String> newStoreIds = newStoreIdBywxEnterpriseMap.get(wxEid);
            logger.info("wxEnterpriseId-difference-" + wxEid + ":{}，{}", JSONObject.toJSONString(oldStoreIds), JSONObject.toJSONString(newStoreIds));
            if (CollectionUtils.isEmpty(newStoreIds)) {
                //没有新的 老的都需要删除
                needUnBindStoreIds.addAll(oldStoreIds);
                return;
            }
            Sets.SetView<String> needDelStoreIds = Sets.difference(oldStoreIds, newStoreIds);
            logger.info("wxEnterpriseId:{}，{}", wxEid, JSONObject.toJSONString(needDelStoreIds));
            Set<String> mid = needDelStoreIds.stream().collect(Collectors.toSet());
            needUnBindStoreIds.addAll(mid);

            //需要新增
            Set<String> old = oldStoreIdByMap.get(wxEid);
            if (CollectionUtils.isEmpty(old)) {
                needAddStoreIds.addAll(newStoreIds);
                return;
            }
            Sets.SetView<String> needAdd = Sets.difference(newStoreIds, old);
            if (CollectionUtils.isNotEmpty(needAdd)) {
                needAddStoreIds.addAll(needAdd);
            }
        });
        newStoreIdBywxEnterpriseMap.forEach((wid, newStoreIds) -> {
            if (!oldStoreIdBywxEnterpriseMap.containsKey(wid)) {
                needAddStoreIds.addAll(newStoreIds);
            }
        });
        //这些门店解除绑定
        staffClerkRelationService.delBindByStoreIds(wxEnterpriseId, needUnBindStoreIds, optStaffId, channelCode);
        //批量处理关联关系
        dealStoreRelation(list, enterpriseId, needUnBindStoreIds, needAddStoreIds);
        return true;
    }

    /**
     * 批量处理关联关系
     *
     * @param storeRelations
     * @param enterpriseId
     * @param delStoreIds
     * @param addStoreIds
     */
    private void dealStoreRelation(List<TabStoreRelation> storeRelations, String enterpriseId, Set<String> delStoreIds, Set<String> addStoreIds) {
        //先删除 后新增
        if (CollectionUtils.isNotEmpty(delStoreIds)) {
            logger.info("批量删除门店：{}", JSONObject.toJSONString(delStoreIds));
            tabHaobanStoreRelationMapper.deleteStoreRalationByStoreIds(enterpriseId, delStoreIds);
        }
        if (CollectionUtils.isNotEmpty(addStoreIds)) {
            logger.info("批量新增门店：{}", JSONObject.toJSONString(addStoreIds));
            List<TabStoreRelation> adds = storeRelations.stream().filter(dto -> addStoreIds.contains(dto.getStoreId())).collect(Collectors.toList());
            //批量插入
            insertStoreRelationBatch(adds);
        }
    }

    /**
     * 批量插入
     *
     * @param storeRelations
     */
    private void insertStoreRelationBatch(List<TabStoreRelation> storeRelations) {
        int batchSize = 1000;
        int sumSize = storeRelations.size();
        int count = (sumSize / batchSize) + ((sumSize % batchSize > 0) ? 1 : 0);
        for (int i = 0; i < count; i++) {
            int from = i * batchSize;
            int subSize = sumSize - from;
            int to = (subSize > batchSize) ? from + batchSize : from + subSize;
            List<TabStoreRelation> relations = storeRelations.subList(from, to);
            tabHaobanStoreRelationMapper.insertBatch(relations);
        }
    }

    /**
     * 获取企业下的老的绑定门店
     *
     * @param enterpriseId
     * @return
     */
    private Map<String, Set<String>> getOldStoreIdsByWxEnterpriseId(String enterpriseId, Map<String, Set<String>> oldStoreIdBywxEnterpriseMap) {
        Map<String, Set<String>> ret = new HashMap<>();

        Set<String> wxEnterpriseIds = new HashSet<>();
        if (oldStoreIdBywxEnterpriseMap != null && oldStoreIdBywxEnterpriseMap.size() > 0) {
            wxEnterpriseIds.addAll(oldStoreIdBywxEnterpriseMap.keySet());
        }

        //导购绑定列表
        List<StaffClerkRelationDTO> staffClerkRelationDTOS = staffClerkRelationService.listBindStoreIdByEnterpriseId(enterpriseId);
        Map<String, Set<String>> oldStaffStoreIdByWxEidMap = staffClerkRelationDTOS.stream().collect(Collectors.groupingBy(StaffClerkRelationDTO::getWxEnterpriseId, Collectors.mapping(dto -> dto.getStoreId(), Collectors.toSet())));
        if (oldStaffStoreIdByWxEidMap != null && oldStaffStoreIdByWxEidMap.size() > 0) {
            wxEnterpriseIds.addAll(oldStaffStoreIdByWxEidMap.keySet());
        }

        if (CollectionUtils.isEmpty(wxEnterpriseIds)) {
            return ret;
        }
        //聚合两者就是总门店了
        wxEnterpriseIds.forEach(wxid -> {
            if (!ret.containsKey(wxid)) {
                ret.put(wxid, new HashSet<>());
            }
            Set<String> storeIds = oldStaffStoreIdByWxEidMap.get(wxid);
            if (CollectionUtils.isNotEmpty(storeIds)) {
                ret.get(wxid).addAll(storeIds);
            }

            Set<String> staffStoreIds = oldStoreIdBywxEnterpriseMap.get(wxid);
            if (CollectionUtils.isNotEmpty(staffStoreIds)) {
                ret.get(wxid).addAll(staffStoreIds);
            }
        });
        return ret;
    }

    @Override
    public List<TabStoreRange> queryStoreRangeByRelationId(String enterpriseId, List<String> relationIds) {
        return tabHaobanStoreRangeMapper.listStoreRangeByRelationId(relationIds, enterpriseId);
    }

    @Override
    public List<String> listStoreIdByWxEnterpriseId(String wxEnterpriseId, String enterpriseId) {
        return tabHaobanStoreRelationMapper.listStoreIdByWxEnterpriseId(wxEnterpriseId, enterpriseId);
    }

    @Override
    public void updatwStoreName(String enterpriseId, String storeId, String storeName) {
        tabHaobanStoreRelationMapper.updateStoreName(enterpriseId, storeId, storeName);
    }

    @Override
    public boolean isFlagByStoreId(String storeId, String wxEnterpriseId, String enterpriseId) {
        List<String> storeIds = tabHaobanStoreRelationMapper.listStoreIdByStoreIdWxEnterpriseId(storeId, wxEnterpriseId, enterpriseId);
        return CollectionUtils.isNotEmpty(storeIds);
    }

    @Override
    public List<String> listStoreGroupIdByWxEnterpriseId(String wxEnterpriseId, String enterpriseId) {
        List<TabStoreRange> list =  this.tabHaobanStoreRangeMapper.queryByEnterpriseId(wxEnterpriseId,enterpriseId);
        if(CollectionUtils.isNotEmpty(list)) {
            return list.stream().map(item->item.getRelationId()).collect(Collectors.toList()) ;
        }
        return null ;
    }
    
    @Override
    public List<String> listStoreIdByName(String wxEnterpriseId, String enterpriseId, String storeName) {
        return tabHaobanStoreRelationMapper.listStoreIdByName(wxEnterpriseId,enterpriseId,storeName);
    }

    @Override
    public boolean hasStore(String wxEnterpriseId , String enterpriseId, String storeId) {
        List<String> storeGroupIds = this.listStoreGroupIdByWxEnterpriseId(wxEnterpriseId, enterpriseId);
        if (CollectionUtils.isEmpty(storeGroupIds)) {
            logger.info("好办门店分组id为空");
            return false ;
        }
        String[] array = storeGroupIds.toArray(new String[0]);
        List<StoreGroupDTO> storeGroupDTOS = storeGroupService.listStoreGroup(array, enterpriseId);
        List<String> parentGroupIds = storeGroupDTOS.stream().map(StoreGroupDTO::getParentGroupId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(parentGroupIds) && parentGroupIds.contains("0")) {
            logger.info("企微包含所有门店",wxEnterpriseId);
            return true ;
        }
        if(isFlagByStoreId(storeId,wxEnterpriseId,enterpriseId)) {
            return true ;
        }
        return false ;
    }
}
