package com.gic.haoban.manage.service.task.friend;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.haoban.manage.api.dto.DealParamMqDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.enums.PreDealStatusEnum;
import com.gic.haoban.manage.api.enums.PreDealTypeEnum;
import com.gic.haoban.manage.api.enums.SyncTaskStatusEnum;
import com.gic.haoban.manage.api.service.MemberUnionidRelatedApiService;
import com.gic.haoban.manage.service.entity.TabHaobanPreDealLog;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.entity.TabHaobanSyncTask;
import com.gic.haoban.manage.service.service.PreDealService;
import com.gic.haoban.manage.service.service.StaffService;
import com.gic.haoban.manage.service.service.SyncTaskService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.task.BaseSyncOperation;
import com.gic.mq.sdk.GicMQClient;
import com.gic.redis.data.util.RedisUtil;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 微信好友
 */
@Service
public class FriendClerkSyncNewOperation implements BaseSyncOperation {

    private static final Logger logger = LoggerFactory.getLogger(FriendClerkSyncNewOperation.class);
    @Autowired
    private PreDealService preDealService;
    @Autowired
    private MemberUnionidRelatedApiService memberUnionidRelatedApiService;
    @Autowired
    private SyncTaskService syncTaskService;
    @Autowired
    private StaffService staffService ;
    @Autowired
    private WxEnterpriseService wxEnterpriseService ;

    private static final String TRY_AGAIN = "haoban_fresh_wx_friend_again_";

    @Override
    public void dealSingleByMq(DealParamMqDTO dealParamMqDTO, TabHaobanPreDealLog dataPre) {
        logger.info("刷新好友列表（7-8),dealParamMqDTO={},dataPre={}", JSON.toJSONString(dealParamMqDTO), JSON.toJSONString(dataPre));
        String reason = "";
        boolean dealFlag = true;
        try {
            String wxEnterpriseId = dataPre.getWxEnterpriseId();
            String staffId = dataPre.getDataId() ;
            this.preDealService.addTaskStatusCache(dataPre.getTaskId());
            TabHaobanStaff staff = this.staffService.selectById(staffId) ;
            if(null == staff) {
                logger.info("staff不存在,staffId={}",staffId);
                return ;
            }
            WxEnterpriseQwDTO qwDTO =  this.wxEnterpriseService.getQwInfo(wxEnterpriseId) ;
            //获取所有外部联系人的外部联系人ids
            String dkWxUserId = staff.getWxUserId() ;
            if(qwDTO.needOpenUserIdDk()) {
                dkWxUserId = staff.getWxOpenUseId();
            }
            List<String> selfUserIdList = memberUnionidRelatedApiService.listSelfExterialList(wxEnterpriseId, dkWxUserId);
            List<String> delUserIdList = selfUserIdList ;
            logger.info("selfUserIdList={}", JSONObject.toJSONString(selfUserIdList));
            if (null == selfUserIdList) {
                dealFlag = tryAgainToMq(dataPre);
                reason = "企微接口失败";
                return;
            }
            if (CollectionUtils.isEmpty(selfUserIdList)) {
                dealFlag = false;
                reason = "无外部联系人";
                return;
            }
            String wxUserId3th = staff.getWxUserId() ;
            if(qwDTO.needOpenUserId3th()) {
                wxUserId3th = staff.getWxOpenUseId() ;
            }
            List<String> userIdList = null ;
            if(!qwDTO.isSelf()) {
                userIdList = memberUnionidRelatedApiService.listExterialList(wxEnterpriseId, wxUserId3th);
                delUserIdList = userIdList ;
                if (null == userIdList) {
                    dealFlag = tryAgainToMq(dataPre);
                    reason = "企微接口失败";
                    logger.info("第三方服务商外部联系人调用失败进入重试：{}", dataPre.getDataId());
                    return;
                }
                if (CollectionUtils.isEmpty(userIdList)) {
                    dealFlag = false;
                    reason = "无外部联系人";
                    return;
                }
            }
            //清理外部联系人
             memberUnionidRelatedApiService.cleanNoExsitFriendNew(wxEnterpriseId, staffId, delUserIdList);
            //写入外部联系人的处理队列
            List<TabHaobanPreDealLog> dealLogList = new ArrayList<>();
            for (String externalUserId : selfUserIdList) {
                TabHaobanPreDealLog dealLog = new TabHaobanPreDealLog();
                dealLog.setDataId(externalUserId + "###" + dkWxUserId);
                dealLog.setpDataId(staffId);
                dealLog.setDataType(PreDealTypeEnum.self_friend.getVal());
                dealLog.setStatusFlag(0);
                dealLog.setTaskId(dataPre.getTaskId());
                dealLog.setDataContent(externalUserId);
                dealLog.setWxEnterpriseId(wxEnterpriseId);
                dealLogList.add(dealLog);
            }

            preDealService.insert(dealLogList);
            
            if(!qwDTO.isSelf()) {
                //写入外部联系人的处理队列
                List<TabHaobanPreDealLog> thirddealLogList = new ArrayList<>();
                for (String externalUserId : userIdList) {
                    TabHaobanPreDealLog dealLog = new TabHaobanPreDealLog();
                    dealLog.setDataId(externalUserId + "###" + wxUserId3th);
                    dealLog.setpDataId(staffId);
                    dealLog.setDataType(PreDealTypeEnum.friend.getVal());
                    dealLog.setStatusFlag(0);
                    dealLog.setTaskId(dataPre.getTaskId());
                    dealLog.setDataContent(externalUserId);
                    dealLog.setWxEnterpriseId(wxEnterpriseId);
                    thirddealLogList.add(dealLog);
                }
                preDealService.insert(thirddealLogList);
            }
            //成功更新状态
            dealSuccess(dealParamMqDTO.getTaskId(), dealParamMqDTO.getData(), dataPre.getEnterpriseId(), dataPre.getWxEnterpriseId());
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("同步失败：{},{}", JSONObject.toJSONString(dataPre), e);
            reason = "成员好友处理异常";
            dealFlag = false;
        } finally {
            if (!dealFlag) {
                dealException(dealParamMqDTO.getTaskId(), dealParamMqDTO.getData(), dataPre.getEnterpriseId(), reason);
            }
        }
    }

    @Override
    public void dealException(String taskId, String dataId, String enterpriseId, String reason) {
        preDealService.updateStatusByDataId(taskId, dataId, PreDealStatusEnum.exception.getVal(), reason);
    }

    @Override
    public void dealSuccess(String taskId, String dataId, String enterpriseId, String wxEnterpriseId) {
        preDealService.updateStatusByDataId(taskId, dataId, PreDealStatusEnum.dealing.getVal(), "预处理中");
        List<String> dataIds = preDealService.listReDataIdByPDataId(taskId, dataId, PreDealTypeEnum.self_friend.getVal());
        logger.info("下一步处理的数据：{},dataId={}", JSONObject.toJSONString(dataIds) , dataId);
        dealDepartmentToMq(taskId, new HashSet<>(dataIds), SyncTaskStatusEnum.self_friend_sync);
    }

    @Override
    public void checkDepartmentTask(String taskId) {
    }


    /**
     * 放入mq处理部门数据
     *
     * @param taskId
     * @param dealList
     */
    private void dealDepartmentToMq(String taskId, Set<String> dealList, SyncTaskStatusEnum syncTaskStatusEnum) {
        //预处理分组任务
        syncTaskService.updateTaskStatus(taskId, syncTaskStatusEnum.getVal());
        List<String> ret = dealList.stream().map(relationId -> {
            DealParamMqDTO dealParamMqDTO = new DealParamMqDTO();
            dealParamMqDTO.setData(relationId);
            dealParamMqDTO.setTaskId(taskId);
            dealParamMqDTO.setType(syncTaskStatusEnum.getVal());
            return JSONObject.toJSONString(dealParamMqDTO);
        }).collect(Collectors.toList());

        GicMQClient clientInstance = GICMQClientUtil.getClientInstance();
        try {
            logger.info("放入队列={}",ret);
            clientInstance.sendBatchMessages("departmentSyncDealMq", ret);
        } catch (Exception e) {
            logger.info("发送失败:{},{}", taskId);
            e.printStackTrace();
        }
    }

    private boolean tryAgainToMq(TabHaobanPreDealLog dataPre) {
        logger.info("需要重试：{}", dataPre.getDataId());
        String key = TRY_AGAIN + dataPre.getTaskId() + ":" + dataPre.getDataId();
        Object cache = RedisUtil.getCache(key);
        if (null == cache) {
            RedisUtil.setCache(key, 1, 2L, TimeUnit.HOURS);
        } else {
            int count = Integer.parseInt(cache.toString());
            RedisUtil.setCache(key, count + 1);
            if (count > 4) {
                return false;
            }
        }
        HashSet<String> reTrysIds = new HashSet<>();
        reTrysIds.add(dataPre.getDataId());
        dealDepartmentToMq(dataPre.getTaskId(), reTrysIds, SyncTaskStatusEnum.friend_clerk_sync);
        return true;
    }

}
