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

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.haoban.base.api.common.Constant;
import com.gic.haoban.manage.api.dto.DealParamMqDTO;
import com.gic.haoban.manage.api.dto.DepartmentDTO;
import com.gic.haoban.manage.api.dto.SecretSettingDTO;
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.SecretTypeEnum;
import com.gic.haoban.manage.api.enums.SyncTaskStatusEnum;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.entity.TabHaobanDepartment;
import com.gic.haoban.manage.service.entity.TabHaobanPreDealLog;
import com.gic.haoban.manage.service.entity.TabHaobanSyncTask;
import com.gic.haoban.manage.service.service.DepartmentService;
import com.gic.haoban.manage.service.service.PreDealService;
import com.gic.haoban.manage.service.service.SecretSettingService;
import com.gic.haoban.manage.service.service.SyncTaskService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.util.EmojiFilterUtil;
import com.gic.mq.sdk.GicMQClient;
import com.gic.redis.data.util.RedisUtil;
import com.gic.wechat.api.dto.qywx.UserDTO;
import com.gic.wechat.api.service.qywx.QywxUserApiService;

/**
 * 同步通讯录部门
 * Created 2020/4/13.
 *
 * @author hua
 */
@Service
public class QywxDeptSyncOperation implements BaseSyncOperation {
    private static final Logger logger = LoggerFactory.getLogger(QywxDeptSyncOperation.class);

    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private PreDealService preDealService;
    @Autowired
    private SyncTaskService syncTaskService;
    @Autowired
    private QywxUserApiService qywxUserApiService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private QywxStaffSyncOperation qywxClerkSyncOperation;
    @Autowired
    private SecretSettingService secretSettingService;
    @Autowired
    private Config config;

    @Override
    public void dealSingleByMq(DealParamMqDTO dealParamMqDTO, TabHaobanPreDealLog dataPre) {
        logger.info("处理企业微信部门：{}", JSONObject.toJSONString(dealParamMqDTO));
        String reason = "";
        TabHaobanDepartment parent = this.departmentService.getByWxId(dataPre.getpDataId(), dataPre.getWxEnterpriseId());
        if (parent == null && dataPre.getpDataId().equals("0")) {
            parent = new TabHaobanDepartment();
            parent.setLevel(0);
            parent.setDepartmentId("0");
            parent.setChainId("0");
            parent.setChainName("");
        }

        if (parent == null) {
            logger.info("不存在该父部门：c:{},p:{}", dataPre.getDataId(), dataPre.getpDataId());
            dealException(dealParamMqDTO.getTaskId(), dealParamMqDTO.getData(), dataPre.getEnterpriseId(), "父部们不存在");
            return;
        }
        TabHaobanDepartment department = departmentService.getByWxId(dealParamMqDTO.getData(), dataPre.getWxEnterpriseId());
        DepartmentDTO dto = new DepartmentDTO();
        if (department != null) {
            logger.info("已经同步过了:{}", dataPre.getDataId());
            dto = EntityUtil.changeEntityByJSON(DepartmentDTO.class, department);
        }

        logger.info("分组是否存在：{}", JSON.toJSONString(department));
        String dataContent = dataPre.getDataContent();
        com.gic.wechat.api.dto.qywx.DepartmentDTO qywxDepart = JSONObject.parseObject(dataContent, com.gic.wechat.api.dto.qywx.DepartmentDTO.class);
        boolean resultFlag = true;

        try {
            dto.setDepartmentName(qywxDepart.getName());
            dto.setLevel(parent.getLevel() + 1);
            dto.setWxEnterpriseId(dataPre.getWxEnterpriseId());
            dto.setWxDepartmentId(qywxDepart.getId() + "");
            dto.setParentDepartmentId(parent.getDepartmentId());
            if (dataPre.getpDataId().equals("0")) {
                dto.setChainId(parent.getChainId());
                dto.setChainName(parent.getChainName());
            } else {
                dto.setChainId(parent.getChainId() + Constant.ID_SEPARATOR + parent.getDepartmentId());
                dto.setChainName(parent.getChainName() + Constant.NAME_SEPARATOR + parent.getDepartmentName());
            }

            dto.setSort(qywxDepart.getOrder());
            dto.setIsStore(0);
            if (dto.getDepartmentId() == null) {
                this.departmentService.add(dto);
            } else {
                this.departmentService.edit(dto);
            }
        } catch (Exception e) {
            resultFlag = false;
            reason = "处理异常:";
            e.printStackTrace();
            logger.info("处理异常:{}", e);
        } finally {
            if (!resultFlag) {
                dealException(dealParamMqDTO.getTaskId(), dealParamMqDTO.getData(), dataPre.getEnterpriseId(), reason);
            } else {
                dealSuccess(dealParamMqDTO.getTaskId(), dealParamMqDTO.getData(), dataPre.getEnterpriseId(), dataPre.getWxEnterpriseId());
            }
        }

    }

    @Override
    public void dealException(String taskId, String dataId, String enterpriseId, String reason) {
        logger.info("部门同步异常：{},{}", taskId, dataId);
        preDealService.updateStatusByDataId(taskId, dataId, PreDealTypeEnum.dept.getVal(), PreDealStatusEnum.exception.getVal(), reason);
        logger.info("递归调用更新状态start==:{},d:{}", taskId, dataId);
        changeChildStatus(taskId, dataId);
        logger.info("递归调用更新状态end==:{},d:{}", taskId, dataId);
        checkDepartmentTask(taskId);
    }

    /**
     * 改变子状态
     *
     * @param taskId
     * @param dataId
     */
    private void changeChildStatus(String taskId, String dataId) {
        List<TabHaobanPreDealLog> child = preDealService.listByPDataId(taskId, dataId, PreDealTypeEnum.dept.getVal());
        if (CollectionUtils.isEmpty(child)) {
            return;
        }
        child.forEach(tab -> {
            preDealService.updateStatusByDataId(taskId, tab.getDataId(), PreDealTypeEnum.dept.getVal(), PreDealStatusEnum.exception.getVal(), "父分组同步异常");
            changeChildStatus(taskId, tab.getDataId());
        });
    }

    @Override
    public void dealSuccess(String taskId, String dataId, String enterpriseId, String wxEnterpriseId) {
        SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(wxEnterpriseId, SecretTypeEnum.CUSTOMIZED_APP.getVal());
        if (null == secretSetting || secretSetting.getCheckFlag() == 0) {
            logger.info("没有配置secret:{},{}", taskId, wxEnterpriseId);
            return;
        }
        TabHaobanPreDealLog preData = preDealService.getByDataId(taskId, dataId, PreDealTypeEnum.dept.getVal(), -1);
        String pDataId = preData.getpDataId();
        if ("0".equals(pDataId)) {
            //根级部门
            List<UserDTO> list = null ;
            WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId) ;
            if(qwDTO.getWxSecurityType()==4) {
                list = this.qywxUserApiService.listDepartmentUser(qwDTO.getThirdCorpid(), config.getWxSuiteid(),  dataId, 1) ;
                logger.info("从(第三方)获取通讯录={}",JSON.toJSONString(list)) ;
            }else {
                list = this.qywxUserApiService.listSelfDepartmentUser(qwDTO.getDkCorpid(), secretSetting.getSecretVal(), dataId, 1,qwDTO.getUrlHost());
                logger.info("从(代开)获取通讯录={}",JSON.toJSONString(list)) ;
            }
            if (null == list) {
                logger.info("微信获取部门成员异常：{},{}", taskId, dataId);
                return;
            }
            logger.info("获取部门列表");
            //预处理门店 写入预处理表
            if (CollectionUtils.isNotEmpty(list)) {
                List<String> dataList = preDealService.listDataIdByTaskIdAndDataType(taskId, PreDealTypeEnum.clerk.getVal());
                List<TabHaobanPreDealLog> preDealLogList = list.stream().filter(mid -> !dataList.contains(mid.getUserid())
                ).map(userDTO -> {
                    TabHaobanPreDealLog dealLog = new TabHaobanPreDealLog();
                    dealLog.setDataId(userDTO.getUserid());
                    dealLog.setpDataId(dataId);
                    dealLog.setDataType(PreDealTypeEnum.clerk.getVal());
                    dealLog.setStatusFlag(0);
                    dealLog.setDataContent(EmojiFilterUtil.removeAllEmoji(userDTO.getName()));
                    dealLog.setTaskId(taskId);
                    dealLog.setWxEnterpriseId(wxEnterpriseId);
                    dealLog.setEnterpriseId(enterpriseId);
                    return dealLog;
                }).collect(Collectors.toList());
                //插入不存在的我们pre表的企业微信数据
                preDealService.insert(preDealLogList);
            }
        }

        boolean b = preDealService.updateStatusByDataId(taskId, dataId, PreDealTypeEnum.dept.getVal(), PreDealStatusEnum.computed.getVal(), "成功");
        if (!b) {
            logger.info("成功修改错误！{}", dataId);
            return;
        }
        List<TabHaobanPreDealLog> preList = preDealService.listReByPDataId(taskId, dataId);
        if (CollectionUtils.isNotEmpty(preList)) {
            Set<String> mid = preList.stream().map(tab -> tab.getDataId()).collect(Collectors.toSet());
            dealDepartmentToMq(taskId, mid, SyncTaskStatusEnum.group_sync);
        } else {
            checkDepartmentTask(taskId);
        }
    }

    @Override
    public void checkDepartmentTask(String taskId) {
        boolean b = preDealService.checkTask(taskId, PreDealTypeEnum.dept.getVal());
        if (!b) {
            return;
        }
        logger.info("微信部门继续成功，开始门店同步:{}", taskId);
        String key = "haoban_sync_department_task_" + taskId;
        RedisUtil.lock(key, 3L);
        TabHaobanSyncTask syncTask = syncTaskService.getSyncTask(taskId);

        //同步成功 进入门店处理
        if (syncTask.getStatusFlag().equals(SyncTaskStatusEnum.group_sync.getVal())) {
            syncTaskService.updateTaskStatus(taskId, SyncTaskStatusEnum.clerk_sync.getVal());
            List<TabHaobanPreDealLog> dealLogs = preDealService.listByTaskId(taskId, PreDealTypeEnum.clerk.getVal(), PreDealStatusEnum.pre.getVal());
            if (CollectionUtils.isEmpty(dealLogs)) {
                qywxClerkSyncOperation.checkDepartmentTask(taskId);
            } else {
                logger.info("处理微信成员开始：{}", taskId);
                Set<String> dataIds = dealLogs.stream().map(TabHaobanPreDealLog::getDataId).collect(Collectors.toSet());
                dealDepartmentToMq(taskId, dataIds, SyncTaskStatusEnum.clerk_sync);
            }
        }
        RedisUtil.unlock(key);
    }

    /**
     * 放入mq处理部门数据
     *
     * @param taskId
     * @param dealList
     */
    private void dealDepartmentToMq(String taskId, Set<String> dealList, SyncTaskStatusEnum syncTaskStatusEnum) {
        //预处理分组任务
        syncTaskService.updateTaskStatus(taskId, syncTaskStatusEnum.getVal());
        dealList.forEach(relationId -> {
            DealParamMqDTO dealParamMqDTO = new DealParamMqDTO();
            dealParamMqDTO.setTaskId(taskId);
            dealParamMqDTO.setData(relationId);
            dealParamMqDTO.setType(syncTaskStatusEnum.getVal());
            GicMQClient clientInstance = GICMQClientUtil.getClientInstance();
            try {
                clientInstance.sendMessage("departmentSyncDealMq", JSONObject.toJSONString(dealParamMqDTO));
            } catch (Exception e) {
                logger.info("发送失败:{},{}", taskId, relationId);
                e.printStackTrace();
            }
        });
    }
}
