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

import cn.hutool.crypto.SecureUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.minlog.Log;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.haoban.manage.api.dto.DealParamMqDTO;
import com.gic.haoban.manage.api.dto.ExternalUserDTO;
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.exception.WxApiLimitException;
import com.gic.haoban.manage.service.service.PreDealService;
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.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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 SelfFriendSyncNewOperation implements BaseSyncOperation {

    private static final Logger logger = LoggerFactory.getLogger(SelfFriendSyncNewOperation.class);
    @Autowired
    private PreDealService preDealService;
    @Autowired
    private MemberUnionidRelatedApiService memberUnionidRelatedApiService;
    @Autowired
    private SyncTaskService syncTaskService;
    @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,代开发={}", JSONObject.toJSONString(dataPre));
        String reason = "成功";
        boolean dealFlag = true;
        try {
            String wxEnterpriseId = dataPre.getWxEnterpriseId();
            String wxUserId = dataPre.getDataId().split("###")[1] ;
            String staffId = dataPre.getpDataId() ;
            String taskId = dealParamMqDTO.getTaskId();
            String externalUserId = dataPre.getDataContent();
            // 查询企微侧外部联系人详情
            ExternalUserDTO externalUserDTO = memberUnionidRelatedApiService.getCorpSelfExternalUseridInfo(wxEnterpriseId, wxUserId, externalUserId);
            if (externalUserDTO == null) {
                logger.info("代开发外部联系人详情查询失败,staffId={},{},{}", staffId,wxUserId,externalUserId);
                dealException(taskId, dataPre.getDataId(), null, "好友不存在");
                return;
            }
            //自有应用信息
            JSONObject json = new JSONObject();
            json.put("name", externalUserDTO.getName());
            json.put("unionId", externalUserDTO.getUnionId());
            json.put("avatar", externalUserDTO.getAvatar());
            json.put("externalUserId", externalUserDTO.getExternalUserId());
            json.put("addCreateTime", externalUserDTO.getAddCreateTime());
            String str = staffId + "_" + externalUserDTO.getName() + "_" + externalUserDTO.getAddCreateTime() ;
            String relationKey = SecureUtil.md5(str);
            logger.info("生成代开发relationKey={},staff={},{}",relationKey,staffId,str);
            WxEnterpriseQwDTO qwDTO =  this.wxEnterpriseService.getQwInfo(wxEnterpriseId) ;
            if(qwDTO.isSelf()) {
                externalUserDTO.setSelfExternalUserId(externalUserDTO.getExternalUserId());
                String ret =  this.memberUnionidRelatedApiService.dealMergeForReflsh(externalUserDTO, wxEnterpriseId, staffId) ;
                if (StringUtils.isNotBlank(ret)) {
                    logger.info("好友创建失败：{},{}", ret, JSONObject.toJSONString(externalUserDTO));
                    dealFlag = false;
                    reason = ret + ":" + relationKey;
                    return;
                }
            }
            //更新状态
            this.preDealService.updateFriendStatusByDataId(taskId, dataPre.getDataId(), PreDealStatusEnum.computed.getVal(), reason, json.toJSONString(), relationKey , PreDealTypeEnum.self_friend.getVal());
            dealSuccess(taskId, dataPre.getDataId(), dataPre.getpDataId(), wxEnterpriseId);
        } catch (WxApiLimitException e) {
            logger.info("接口次数限制：{}", JSONObject.toJSONString(dataPre));
            dealFlag = tryAgainToMq(dataPre);
            reason = "重试次数过多";
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("同步失败：{},{}", JSONObject.toJSONString(dataPre), e);
            reason = "自建应用好友处理异常";
            dealFlag = false;

        } finally {
            if (!dealFlag) {
                dealException(dealParamMqDTO.getTaskId(), dataPre.getDataId(), dataPre.getpDataId(), reason);
            }
        }
    }

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

    @Override
    public void dealSuccess(String taskId, String dataId, String pDataId, String wxEnterpriseId) {
        checkDepartmentTask(taskId, pDataId);
    }


    /**
     * 自定义处理流程
     *
     * @param taskId
     * @param pDataId
     */
    public void checkDepartmentTask(String taskId, String pDataId) {
        this.preDealService.addTaskStaffStatusCache(taskId,pDataId,7);
    }

    @Override
    public void checkDepartmentTask(String taskId) {
    }

    private boolean tryAgainToMq(TabHaobanPreDealLog dataPre) {
        logger.info("需要重试self：{}", 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 {
            Integer count = Integer.valueOf(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.self_friend_sync);
        return true;
    }
    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 {
            Log.info("发送队列SelfFriendSyncNewOperation={}",JSON.toJSONString(ret));
            clientInstance.sendBatchMessages("departmentSyncDealMq", ret);
        } catch (Exception e) {
            logger.info("发送失败:{},{}", taskId);
            e.printStackTrace();
        }
    }
}
