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

import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.haoban.app.customer.dto.SearchComputeDTO;
import com.gic.haoban.app.customer.dto.SearchDataDTO;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.manage.api.dto.DealParamMqDTO;
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.ExternalClerkRelatedApiService;
import com.gic.haoban.manage.service.entity.TabHaobanPreDealLog;
import com.gic.haoban.manage.service.entity.TabHaobanSyncTask;
import com.gic.haoban.manage.service.service.PreDealService;
import com.gic.haoban.manage.service.service.SyncTaskService;
import com.gic.haoban.manage.service.task.BaseSyncOperation;
import com.gic.mq.sdk.GicMQClient;
import com.gic.redis.data.util.RedisUtil;
import com.gic.search.engine.api.constant.MemberDataEnum;
import com.gic.search.engine.api.constant.OperateEnum;
import com.gic.search.engine.api.dto.ESResponseQueryBatch;
import com.gic.search.engine.api.dto.dynamic.DynamicSearchDTO;
import com.gic.search.engine.api.service.dynamic.ESDataDynamicOperationApiService;
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.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created 2021/6/23.
 *
 * @author hua
 */
@Service
public class FriendTagSyncOperation implements BaseSyncOperation {

    private static final Logger logger = LoggerFactory.getLogger(FriendTagSyncOperation.class);
    @Autowired
    private PreDealService preDealService;
    @Autowired
    private SyncTaskService syncTaskService;
    @Autowired
    private FriendMemberTagSyncOperation friendMemberTagSyncOperation;
    @Autowired
    private ExternalClerkRelatedApiService externalClerkRelatedApiService;
    @Autowired
    private ESDataDynamicOperationApiService esDataDynamicOperationApiService;


    @Override
    public void dealSingleByMq(DealParamMqDTO dealParamMqDTO, TabHaobanPreDealLog dataPre) {
        logger.info("处理标签同步初始化：{}", JSONObject.toJSONString(dealParamMqDTO));
        boolean resultFlag = true;
        String reason = "";
        String tagId = dataPre.getDataId();
        String enterpriseId = dataPre.getEnterpriseId();
        String wxEnterpriseId = dataPre.getWxEnterpriseId();
        String taskId = dataPre.getTaskId();
        try {

            List<String> items = new ArrayList<>();
            items.add(tagId);
            Set<String> memberIds = listMemberIds(wxEnterpriseId, enterpriseId, items);
            logger.info("memberIds");

            List<TabHaobanPreDealLog> preDealLogs = memberIds.stream().map(memberId -> {
                TabHaobanPreDealLog dealLog = new TabHaobanPreDealLog();
                dealLog.setDataId(memberId);
                dealLog.setpDataId(dataPre.getDataId());
                dealLog.setDataType(PreDealTypeEnum.tag_member.getVal());
                dealLog.setStatusFlag(0);
                dealLog.setTaskId(taskId);
                dealLog.setWxEnterpriseId(wxEnterpriseId);
                dealLog.setEnterpriseId(enterpriseId);
                return dealLog;
            }).collect(Collectors.toList());
            preDealService.insert(preDealLogs);

        } 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());
            }
        }

    }

    private Set<String> listMemberIds(String wxEnterpriseId, String enterpriseId, List<String> memberTagIds) {
        Set<String> ret = new HashSet<>();
        int pageSize = 5000;
        BasePageInfo pageInfo = new BasePageInfo();
        pageInfo.setPageSize(pageSize);
        Page<String> page = externalClerkRelatedApiService.pageExternalByEnterpriseId(wxEnterpriseId, enterpriseId, pageInfo);
        Set<String> midMemberIDs = this.listMemberIds(wxEnterpriseId, enterpriseId, memberTagIds, page.getResult());
        ret.addAll(midMemberIDs);
        while (page.getCurrentPageSize() == pageSize) {
            pageInfo.setPageNum(page.getCurrentPage() + 1);
            page = externalClerkRelatedApiService.pageExternalByEnterpriseId(wxEnterpriseId, enterpriseId, pageInfo);
            midMemberIDs = this.listMemberIds(wxEnterpriseId, enterpriseId, memberTagIds, page.getResult());
            ret.addAll(midMemberIDs);
        }
        return ret;
    }

    private Set<String> listMemberIds(String wxEnterpriseId, String enterpriseId, List<String> itemIds, List<String> memberIds) {

        String searchParams = StringUtils.join(itemIds, " ");
        List<SearchComputeDTO> andList = new ArrayList<>();
        SearchDataDTO tagSearchDto = new SearchDataDTO(MemberDataEnum.member_tag.getCode(), OperateEnum.OPERATE_CONTAIN.getValue(), searchParams);
        SearchDataDTO memberIdDto = new SearchDataDTO(MemberDataEnum.member_id.getCode(), OperateEnum.OPERATE_CONTAIN.getValue(), searchParams);

        SearchComputeDTO memberTagCompute = new SearchComputeDTO("data", null, tagSearchDto);
        SearchComputeDTO memberIdCompute = new SearchComputeDTO("data", null, memberIdDto);
        andList.add(memberIdCompute);
        andList.add(memberTagCompute);

        SearchComputeDTO searchComputeDTO = new SearchComputeDTO(OperateEnum.OPERATE_AND.getValue(), andList, null);

        DynamicSearchDTO searchDTO = new DynamicSearchDTO();
        searchDTO.setEnterpriseId(enterpriseId);
        searchDTO.setColumnCategoryCode("member");
        searchDTO.setReturnFileds(MemberDataEnum.member_id.getCode());
        searchDTO.setSearchJson(searchComputeDTO.toJSONObject());
        logger.info("searchJson:" + searchDTO.getSearchJson());

        ESResponseQueryBatch queryDataBatch = esDataDynamicOperationApiService.queryDataBatch(searchDTO, false, null);
        List<JSONObject> res = queryDataBatch.getRes();
        if (CollectionUtils.isEmpty(res)) {
            return new HashSet<>();
        }
        return res.stream().map(mid -> mid.getString(MemberDataEnum.member_id.getCode())).collect(Collectors.toSet());

    }

    @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("递归调用更新状态end==:{},d:{}", taskId, dataId);
        checkDepartmentTask(taskId);
    }


    @Override
    public void dealSuccess(String taskId, String dataId, String enterpriseId, String wxEnterpriseId) {

        boolean b = preDealService.updateStatusByDataId(taskId, dataId, PreDealTypeEnum.tag.getVal(), PreDealStatusEnum.computed.getVal(), "成功");
        if (!b) {
            logger.info("成功修改错误！{}", dataId);
            return;
        }
        checkDepartmentTask(taskId);

    }


    @Override
    public void checkDepartmentTask(String taskId) {
        boolean b = preDealService.checkTask(taskId, PreDealTypeEnum.tag.getVal());
        if (!b) {
            return;
        }
        logger.info("没有完成，开始门店同步:{}", taskId);
        String key = "haoban_sync_tag_task_" + taskId;
        RedisUtil.lock(key, 3L);
        TabHaobanSyncTask syncTask = syncTaskService.getSyncTask(taskId);

        //同步成功 进入会员标签同步
        if (syncTask.getStatusFlag().equals(SyncTaskStatusEnum.tag.getVal())) {
            syncTaskService.updateTaskStatus(taskId, SyncTaskStatusEnum.member_tag.getVal());
            List<TabHaobanPreDealLog> dealLogs = preDealService.listByTaskId(taskId, PreDealTypeEnum.tag_member.getVal(), PreDealStatusEnum.pre.getVal());
            if (CollectionUtils.isEmpty(dealLogs)) {
                friendMemberTagSyncOperation.checkDepartmentTask(taskId);
            } else {
                logger.info("处理标签：{}", taskId);
                Set<String> dataIds = dealLogs.stream().map(TabHaobanPreDealLog::getDataId).collect(Collectors.toSet());
                dealDepartmentToMq(taskId, dataIds, SyncTaskStatusEnum.member_tag);
            }
        }
        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();
            }
        });
    }
}
