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

import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.common.utils.PageUtil;
import com.gic.haoban.manage.api.dto.*;
import com.gic.haoban.manage.api.service.HandoverOperationApiService;
import com.gic.haoban.manage.api.service.WxEnterpriseApiService;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.entity.TabHandoverExternal;
import com.gic.haoban.manage.service.entity.TabHandoverStaff;
import com.gic.haoban.manage.service.entity.TabHandoverTransfer;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.service.HandoverService;
import com.gic.haoban.manage.service.service.StaffService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.mq.sdk.GicMQClient;
import com.gic.wechat.api.dto.qywx.QywxTransferCustomerInfoDTO;
import com.gic.wechat.api.dto.qywx.QywxUnassignedInfoDTO;
import com.gic.wechat.api.dto.qywx.response.QywxGetUnassignedListDTO;
import com.gic.wechat.api.dto.qywx.response.QywxTransferCustomerDTO;
import com.gic.wechat.api.service.qywx.QywxUserApiService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Created 2021/6/16.
 *
 * @author hua
 */
@Service
public class HandoverOperationApiServiceImpl implements HandoverOperationApiService {

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

    @Autowired
    private HandoverService handoverService;
    @Autowired
    private QywxUserApiService qywxUserApiService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private Config config;
    @Autowired
    private WxEnterpriseApiService wxEnterpriseApiService;
    @Autowired
    private StaffService staffService;


    @Override
    public void batchQywxHandoverTimeTask(String params) {
        logger.info("定时拉取离职基础的人员start：{}", params);
        List<YwWxEnterpriseDTO> dtoList = wxEnterpriseApiService.listAll();
        for (YwWxEnterpriseDTO enterpriseDTO : dtoList) {
            GicMQClient instance = GICMQClientUtil.getClientInstance();
            try {
                instance.sendMessage("dealQywxEnterpriseHandoverMq", enterpriseDTO.getWxEnterpriseId());
            } catch (Exception e) {
                logger.info("发送消息队列异常：{},{}", JSONObject.toJSONString(enterpriseDTO), e);
            }
        }
        logger.info("定时拉取离职基础的人员end：{}", params);
    }

    @Override
    public void dealQywxEnterpriseHandoverMq(String wxEnterpriseId) {
        logger.info("离职继承start...{}", wxEnterpriseId);
        dealQywxEnterpriseHandover(wxEnterpriseId);
        dealQywxEnterpriseHandoverResult(wxEnterpriseId);
        logger.info("离职继承end...{}", wxEnterpriseId);
    }

    @Override
    public void dealQywxEnterpriseHandover(String wxEnterpriseId) {
        logger.info("拉取单个企业微信的离职成员：{}", wxEnterpriseId);
        List<QywxUnassignedInfoDTO> allQywxUnassigned = getAllQywxUnassigned(wxEnterpriseId);
        logger.info("处理离职成员数量：{},{}", wxEnterpriseId, allQywxUnassigned.size());
        handoverService.saveHandover(wxEnterpriseId, allQywxUnassigned);
    }

    /**
     * 获取离职成员客户列表
     *
     * @param wxEnterpriseId
     * @return
     */
    private List<QywxUnassignedInfoDTO> getAllQywxUnassigned(String wxEnterpriseId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        //这里改成LinkedList，避免使用ArrayList导致频繁扩容，从而减少内存的浪费
        List<QywxUnassignedInfoDTO> ret = new LinkedList<>();
        QywxGetUnassignedListDTO unassignedListDTO = null;
        String cursor = null;
        do {
            //离职成员客户列表
            unassignedListDTO = qywxUserApiService.getUnassignedList(qwDTO.getThirdCorpid(), qwDTO.getSelf3thSecret(), cursor , qwDTO.isSelf(),qwDTO.getUrlHost());
            cursor = unassignedListDTO.getNextCursor();
            List<QywxUnassignedInfoDTO> infoList = unassignedListDTO.getInfo();
            if (CollectionUtils.isNotEmpty(infoList)) {
                //这里过滤staff成员id，避免ret数组过大
                ret.addAll(infoList);
                //根据handoverUserid去重
                List<QywxUnassignedInfoDTO> collect = infoList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(QywxUnassignedInfoDTO::getHandoverUserid))), ArrayList::new));
                for (QywxUnassignedInfoDTO dto : collect){
                    String handoverUserid = dto.getHandoverUserid();
                    TabHandoverStaff handoverStaff = handoverService.getHandoverStaff(wxEnterpriseId, handoverUserid);
                    if (null == handoverStaff) {
                        ret = ret.stream().filter(d -> !d.getHandoverUserid().equals(handoverUserid)).collect(Collectors.toList());
                    }
                }
            }
        } while (StringUtils.isNotBlank(cursor) && unassignedListDTO.getErrcode() == 0);
        if (CollectionUtils.isEmpty(ret)) {
            return ret;
        }
        //去重
        return ret.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(dto -> {
                            return dto.getExternalUserid() + dto.getHandoverUserid();
                        }))), ArrayList::new));

    }


    @Override
    public void dealQywxEnterpriseHandoverResult(String wxEnterpriseId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        Date date = DateUtils.addDays(new Date(), -3);
        String day = DateFormatUtils.format(date, "yyyy-MM-dd");
        List<TabHandoverTransfer> transfers = handoverService.listTransferByWxEnterpriseId(wxEnterpriseId, day);
        if (CollectionUtils.isEmpty(transfers)) {
            logger.info("没有需要转化的");
            return;
        }
        transfers.forEach(dto -> {
            try {
                TabHaobanStaff handover = staffService.selectById(dto.getHandoverStaffId());
                TabHaobanStaff takeover = staffService.selectById(dto.getTakeoverStaffId());
                if(null == handover) {
                    logger.info("handover is null={}",dto.getHandoverStaffId());
                    return;
                }
                if(null == takeover) {
                    logger.info("takeover is null={}",dto.getTakeoverStaffId());
                    return;
                }
                QywxTransferCustomerDTO customerDTO = qywxUserApiService.transferResult(qwDTO.getThirdCorpid(), qwDTO.getSelf3thSecret(), handover.getWxUserId(), takeover.getWxUserId(), true , qwDTO.isSelf() , qwDTO.getUrlHost());
                if (customerDTO.getErrcode() != 0) {
                    return;
                }
                List<QywxTransferCustomerInfoDTO> customerResults = customerDTO.getCustomer();
                handoverService.dealResult(wxEnterpriseId, dto.getHandoverTransferId(), customerResults);
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("处理异常：{},{}", JSONObject.toJSONString(dto), e);
            }
        });
    }

    @Override
    public List<HandoverStaffInfoDTO> listHandoverStaff(String wxEnterpriseId, String storeId) {
        List<TabHandoverStaff> handoverStaffs = handoverService.listByStoreId(wxEnterpriseId, storeId);
        if (CollectionUtils.isEmpty(handoverStaffs)) {
            return null;
        }
        Map<String, TabHandoverStaff> handoverStaffMap = handoverStaffs.stream().collect(Collectors.toMap(dto -> dto.getStaffId(), dto -> dto, (o, n) -> o));

        List<String> staffIds = handoverStaffs.stream().map(dto -> dto.getStaffId()).collect(Collectors.toList());
        List<TabHaobanStaff> tabHaobanStaffs = staffService.listNoStatusByStaffIds(wxEnterpriseId, staffIds);
        if (CollectionUtils.isEmpty(tabHaobanStaffs)) {
            logger.info("不存在staff列表");
            return null;
        }
        List<HandoverStaffFriendCountDTO> friendCountList = handoverService.listFriendCountByWxStaffIds(wxEnterpriseId, staffIds);
        Map<String, HandoverStaffFriendCountDTO> staffFriendCountMap = friendCountList.stream().collect(Collectors.toMap(dto -> dto.getStaffId(), dto -> dto));

        List<HandoverStaffInfoDTO> retList = EntityUtil.changeEntityListByJSON(HandoverStaffInfoDTO.class, tabHaobanStaffs);
        retList.forEach(dto -> {
            HandoverStaffFriendCountDTO staffFriend = staffFriendCountMap.get(dto.getStaffId());
            TabHandoverStaff tabHandoverStaff = handoverStaffMap.get(dto.getStaffId());
            dto.setDimissionTime(tabHandoverStaff.getDimissionTime());
            dto.setFriendCount(staffFriend != null ? staffFriend.getFriendCount() : 0);
            dto.setHaobanFriendCount(staffFriend != null ? staffFriend.getHaobanFriendCount() : 0);
        });
        return retList;
    }

    @Override
    public Page<HandoverExternalDTO> pageHandoverFriend(String wxEnterpriseId, String search, List<String> staffIds, List<String> transferIds, BasePageInfo pageInfo) {
        Page<HandoverExternalDTO> retPage = handoverService.pageByStaffIds(wxEnterpriseId, search, staffIds, transferIds, pageInfo, 1);
        if (CollectionUtils.isEmpty(retPage.getResult())) {
            return retPage;
        }
        List<String> midStaffIds = retPage.getResult().stream().map(dto -> dto.getStaffId()).collect(Collectors.toList());
        List<TabHaobanStaff> haobanStaffs = staffService.listNoStatusByStaffIds(wxEnterpriseId, midStaffIds);
        Map<String, String> staffNameMap = haobanStaffs.stream().collect(Collectors.toMap(dto -> dto.getStaffId(), dto -> dto.getStaffName(), (o, n) -> o));
        retPage.getResult().forEach(dto -> {
            String staffName = staffNameMap.get(dto.getStaffId());
            dto.setStaffName(staffName);
        });
        return retPage;
    }

    @Override
    public Page<ExternalInfoDTO> pageHandoverFriend(String wxEnterpriseId, String search, List<String> staffIds, List<String> transferIds, BasePageInfo pageInfo, int status) {
        Page<HandoverExternalDTO> retPage = handoverService.pageByStaffIds(wxEnterpriseId, search, staffIds, transferIds, pageInfo, status);
        if (CollectionUtils.isEmpty(retPage.getResult())) {
            return new Page<>();
        }
        Page<ExternalInfoDTO> ret = PageUtil.changeToCurrentPage(retPage, ExternalInfoDTO.class);
        List<ExternalInfoDTO> infoDTOS = ret.getResult();

        List<String> retTransferIds = infoDTOS.stream().map(dto -> dto.getHandoverTransferId()).collect(Collectors.toList());
        List<TabHandoverTransfer> transfers = handoverService.listTransferByIds(wxEnterpriseId, retTransferIds);
        Map<String, TabHandoverTransfer> transferMap = transfers.stream().collect(Collectors.toMap(dto -> dto.getHandoverTransferId(), dto -> dto));

        List<String> midStaffIds = transfers.stream().flatMap(dto -> {
            List<String> mid = new ArrayList<>();
            mid.add(dto.getHandoverStaffId());
            mid.add(dto.getTakeoverStaffId());
            return mid.stream();
        }).collect(Collectors.toList());

        List<TabHaobanStaff> haobanStaffs = staffService.listNoStatusByStaffIds(wxEnterpriseId, midStaffIds);
        Map<String, String> staffNameMap = haobanStaffs.stream().collect(Collectors.toMap(dto -> dto.getStaffId(), dto -> dto.getStaffName(), (o, n) -> o));
        ret.getResult().forEach(dto -> {
            TabHandoverTransfer handoverTransfer = transferMap.get(dto.getHandoverTransferId());
            String handoverStaff = staffNameMap.get(handoverTransfer.getHandoverStaffId());
            String takeoverStaff = staffNameMap.get(handoverTransfer.getTakeoverStaffId());
            dto.setTakeoverStaffName(takeoverStaff);
            dto.setHandoverStaffId(handoverTransfer.getHandoverStaffId());
            dto.setTakeoverStaffId(handoverTransfer.getTakeoverStaffId());
            dto.setHandoverStaffName(handoverStaff);
        });
        return ret;
    }

    @Override
    public void transferFriend(String wxEnterpriseId, List<String> handoverExternalIds, String disStaffId, String storeId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        TabHaobanStaff tabHaobanStaff = staffService.selectById(disStaffId);
        String takeoverUserId = tabHaobanStaff.getWxUserId();
        if (qwDTO.needOpenUserId3th()) {
            takeoverUserId = tabHaobanStaff.getWxOpenUseId();
        }
        List<TabHandoverExternal> externalList = handoverService.listByIds(wxEnterpriseId, handoverExternalIds);
        //分配人与客户的关联map
        Map<String, List<String>> handoverStaffExternalMap = externalList.stream().collect(Collectors.groupingBy(dto -> dto.getUserId(), Collectors.mapping(TabHandoverExternal::getExternalUserId, Collectors.toList())));
        //分配人wxUserId 对应的staffIdMap
        Map<String, String> handoverStaffIdMap = externalList.stream().collect(Collectors.toMap(dto -> dto.getUserId(), dto -> dto.getStaffId(), (o, n) -> o));
        //TabHandoverExternal 根据分配人wxUserId 分类 主键id
        Map<String, List<String>> userByIdMap = externalList.stream().collect(Collectors.groupingBy(dto -> dto.getUserId(), Collectors.mapping(dto -> dto.getHandoverExternalId(), Collectors.toList())));

        for (Map.Entry<String, List<String>> entry : handoverStaffExternalMap.entrySet()) {
            String wxUserId = entry.getKey();
            List<String> list = entry.getValue();
            QywxTransferCustomerDTO transferCustomerResp = qywxUserApiService.transferCustomer(qwDTO.getThirdCorpid(), qwDTO.getSelf3thSecret(), wxUserId, takeoverUserId, list,qwDTO.isSelf(),qwDTO.getUrlHost());
            if (transferCustomerResp.getErrcode() != 0) {
                logger.info("转移异常");
            }
            List<QywxTransferCustomerInfoDTO> customer = transferCustomerResp.getCustomer();
            if (CollectionUtils.isEmpty(customer)) {
                continue;
            }
            TabHandoverTransfer transfer = new TabHandoverTransfer();
            transfer.setExternalCount(list.size());
            transfer.setStoreId(storeId);
            transfer.setHandoverStaffId(handoverStaffIdMap.get(wxUserId));
            transfer.setTakeoverStaffId(disStaffId);
            transfer.setWxEnterpriseId(wxEnterpriseId);
            //执行保存分配后结果
            handoverService.saveHandoverTransfer(transfer, userByIdMap.get(wxUserId));
        }
    }

    @Override
    public List<HandoverExternalDTO> listByIds(String wxEnterpriseId, List<String> handoverExternalIds) {
        List<TabHandoverExternal> externalList = handoverService.listByIds(wxEnterpriseId, handoverExternalIds);
        return EntityUtil.changeEntityListByJSON(HandoverExternalDTO.class, externalList);
    }

    @Override
    public List<HandoverStaffInfoDTO> listDis(String wxEnterpriseId, String storeId) {
        List<TabHandoverTransfer> handoverTransfers = handoverService.listTransferByStoreId(wxEnterpriseId, storeId);
        if (CollectionUtils.isEmpty(handoverTransfers)) {
            return null;
        }
        Map<String, TabHandoverTransfer> handoverTransferMap = handoverTransfers.stream().collect(Collectors.toMap(dto -> dto.getHandoverStaffId(), dto -> dto, (o, n) -> o));

        List<String> handoverStaffIds = handoverTransfers.stream().map(dto -> dto.getHandoverStaffId()).collect(Collectors.toList());
        List<TabHaobanStaff> haobanStaffs = staffService.listNoStatusByStaffIds(wxEnterpriseId, handoverStaffIds);
        List<HandoverStaffInfoDTO> retList = EntityUtil.changeEntityListByJSON(HandoverStaffInfoDTO.class, haobanStaffs);
        retList.forEach(dto -> {
            TabHandoverTransfer mid = handoverTransferMap.get(dto.getStaffId());
            dto.setFriendCount(mid.getExternalCount());
        });

        return retList;
    }

    @Override
    public List<String> listTransferIdByHandoverStaffId(String wxEnterpriseId, String handoverStaffId) {
        List<TabHandoverTransfer> ret = handoverService.listTransferByHandoverStaffId(wxEnterpriseId, handoverStaffId);
        if (CollectionUtils.isEmpty(ret)) {
            return null;
        }
        return ret.stream().map(dto -> dto.getHandoverTransferId()).collect(Collectors.toList());
    }

    @Override
    public List<String> listTransferIdByTakeoverStaffId(String wxEnterpriseId, String takeoverStaffId) {
        List<TabHandoverTransfer> ret = handoverService.listTransferByTakeoverStaffId(wxEnterpriseId, takeoverStaffId);
        if (CollectionUtils.isEmpty(ret)) {
            return null;
        }
        return ret.stream().map(dto -> dto.getHandoverTransferId()).collect(Collectors.toList());
    }

    @Override
    public Integer countTransferIdByTakeoverStaffId(String wxEnterpriseId, String takeoverStaffId) {
        List<TabHandoverTransfer> ret = handoverService.listTransferByTakeoverStaffId(wxEnterpriseId, takeoverStaffId);
        if (CollectionUtils.isEmpty(ret)) {
            return null;
        }
        return ret.stream().mapToInt(dto -> dto.getExternalCount()).sum();
    }
}
