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

import cn.hutool.core.date.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.gic.api.base.commons.BusinessException;
import com.gic.api.base.commons.Constant;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.enterprise.api.constant.EnterpriseServiceEnum;
import com.gic.enterprise.api.dto.StoreDTO;
import com.gic.enterprise.api.service.StoreService;
import com.gic.haoban.app.customer.dto.CustomerDTO;
import com.gic.haoban.app.customer.dto.MemberInfoListParamsDTO;
import com.gic.haoban.app.customer.dto.contact.ContactParamDTO;
import com.gic.haoban.app.customer.dto.contact.ContactSumDTO;
import com.gic.haoban.app.customer.service.api.service.CustomerApiService;
import com.gic.haoban.app.objectives.api.service.ObjectivesManageApiService;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.manage.api.constants.Manage3Constants;
import com.gic.haoban.manage.api.dto.contact.ContactConfigDTO;
import com.gic.haoban.manage.api.dto.contact.ContactLogDTO;
import com.gic.haoban.manage.api.enums.contact.ContactAutoTypeEnum;
import com.gic.haoban.manage.api.enums.contact.ContactBizTypeEnum;
import com.gic.haoban.manage.api.enums.contact.ContactFollowTypeEnum;
import com.gic.haoban.manage.api.qdto.contact.ContactFollowQDTO;
import com.gic.haoban.manage.api.qdto.contact.ContactLogQDTO;
import com.gic.haoban.manage.service.dao.mapper.contact.TabContactFollowMapper;
import com.gic.haoban.manage.service.dao.mapper.contact.TabContactLogMapper;
import com.gic.haoban.manage.service.entity.contact.TabContactFollow;
import com.gic.haoban.manage.service.entity.contact.TabContactLog;
import com.gic.haoban.manage.service.service.ESMemberInfoService;
import com.gic.haoban.manage.service.service.contact.ContactConfigService;
import com.gic.haoban.manage.service.service.contact.ContactFollowService;
import com.gic.haoban.manage.service.service.contact.ContactLogService;
import com.gic.haoban.manage.service.service.content.adaptor.EnterpriseAdaptor;
import com.gic.member.api.dto.MemberStoreClerkDTO;
import com.gic.member.api.service.MemberService;
import com.gic.mq.sdk.GicMQClient;
import com.gic.search.engine.api.dto.ESResponse;
import com.gic.search.engine.api.dto.dynamic.DynamicDocDTO;
import com.gic.search.engine.api.service.dynamic.ESDataDynamicOperationApiService;
import com.gic.store.goods.service.StoreGoodsService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@Service("contactLogService")
public class ContactLogServiceImpl implements ContactLogService {

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

    @Autowired
    private TabContactLogMapper contactLogMapper;
    @Autowired
    private TabContactFollowMapper contactFollowMapper;
    @Autowired
    private ContactConfigService contactConfigService;
    @Autowired
    private ContactFollowService contactFollowService;
    @Autowired
    private StoreGoodsService storeGoodsService;
    @Autowired
    private ClerkService clerkService;
    @Autowired
    private StoreService storeService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private CustomerApiService customerApiService;
    @Autowired
    private ObjectivesManageApiService objectivesManageApiService;
    @Autowired
    private ESDataDynamicOperationApiService esDataDynamicOperationApiService;
    @Autowired
    private ESMemberInfoService esMemberInfoService;
    @Autowired
    private EnterpriseAdaptor enterpriseAdaptor;

    @Override
    public boolean contactCheck(String enterpriseId,String memberId,ClerkDTO clerkDTO,Integer bizType) {
        if (clerkDTO == null) {
            return false;
        }
        CustomerDTO params = new CustomerDTO();
        int clerkType = clerkDTO.getClerkType();
        if (clerkType > 2) {
            return false;
        }
        String clerkId = clerkDTO.getClerkId();
        String storeId = "";
        if (clerkType == 0 || clerkType == 1) {
            storeId = clerkDTO.getStoreId();
        }
        params.setClerkType(clerkType + "");
        params.setSearchParams("");
        params.setStoreId(storeId);
        params.setClerkId(clerkId);
        params.setEnterpriseId(enterpriseId);
        if (bizType!=null) {
            return checkPotential(memberId, params, bizType);
        } else {
            boolean checkPotential = checkPotential(memberId, params, ContactBizTypeEnum.POTENTIAL_CUSTOMER.getType());
            if (checkPotential) {
                return true;
            }
            checkPotential = checkPotential(memberId, params, ContactBizTypeEnum.OPPORTUNITY_CUSTOMER.getType());
            if (checkPotential) {
                return true;
            }
        }
        return false;
    }

    private boolean checkPotential(String memberId, CustomerDTO params,Integer bizType) {
        boolean hasRight = enterpriseAdaptor.checkEnterpriseHasRightByContactBizType(params.getEnterpriseId(), bizType);
        if (!hasRight) {
            return false;
        }
        ContactParamDTO contact = new ContactParamDTO();
        // 搜索信息
        MemberInfoListParamsDTO memberInfoListParamsDTO = com.gic.haoban.common.utils.StringUtil.getBean("{}", MemberInfoListParamsDTO.class);
        if (Objects.equals(bizType, ContactBizTypeEnum.OPPORTUNITY_CUSTOMER.getType())) {
            memberInfoListParamsDTO.setCrowdClerkId(params.getClerkId());
            memberInfoListParamsDTO.setCrowdType(-1);
            memberInfoListParamsDTO.setMemberType(4);
        }
        memberInfoListParamsDTO.setMemberId(memberId);
        contact.setContactType(0);
        contact.setBizType(bizType);
        params.setContactParamDTO(contact);
        ServiceResponse<ContactSumDTO> noContactResponse = customerApiService.contactMemberSum(new BasePageInfo(), params, memberInfoListParamsDTO);
        if (noContactResponse.isSuccess() && noContactResponse.getResult() != null) {
            if (noContactResponse.getResult().getTotalCount() > 0) {
                return true;
            }
        }
        contact.setContactType(1);
        params.setContactParamDTO(contact);
        ServiceResponse<ContactSumDTO> contactResponse = customerApiService.contactMemberSum(new BasePageInfo(), params, memberInfoListParamsDTO);
        if (contactResponse.isSuccess() && contactResponse.getResult() != null) {
            if (contactResponse.getResult().getTotalCount() > 0) {
                return true;
            }
        }
        return false;
    }


    @Override
    public void saveContactLog(ContactLogQDTO qdto) throws BusinessException {
        logger.info("保存建联记录:{}", JSON.toJSONString(qdto));
        String enterpriseId = qdto.getEnterpriseId();
        boolean hasRight = enterpriseAdaptor.checkEnterpriseHasRightByContactBizType(qdto.getEnterpriseId(), qdto.getBizType());
        if (!hasRight) {
            logger.info("无服务权限");
            throw new BusinessException("-1", "无服务权限");
        }
        String storeId = qdto.getStoreId();
        String clerkId = qdto.getClerkId();
        String memberId = qdto.getMemberId();
        Integer contactAutoType = qdto.getContactAutoType();
        Integer followType = qdto.getFollowType();
        Integer bizType = qdto.getBizType();
        Integer sourceType = qdto.getSourceType();
        Long sourceLogId = qdto.getSourceLogId();
        Date date = qdto.getSyncContactTime() != null ? qdto.getSyncContactTime() : DateUtil.date();
        MemberStoreClerkDTO memberStoreClerk = memberService.getMemberStoreClerk(memberId);
        if (memberStoreClerk == null) {
            logger.info("无专属导购无法建联");
            throw new BusinessException("-1", "无专属导购无法建联");
        }
        String mainClerkId = memberStoreClerk.getClerkId();
        if (!Objects.equals(mainClerkId, clerkId)) {
            logger.info("非专属导购无法建联");
            throw new BusinessException("-1", "非专属导购无法建联");
        }
        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
        // 建联校验
        boolean contactCheck = contactCheck(enterpriseId, memberId, clerkDTO, bizType);
        logger.info("非未建联或建联未转化:{}",contactCheck);
        if (!contactCheck) {
            throw new BusinessException("-1", "非未建联或建联未转化，无法建联");
        }
        // 是否周期内首次建联 同周期内是否有记录
        Integer contactCycle = 1;
        // 建联周期 14天内同周期/14天以上周期+1
        Integer contactCycleFirst = Constant.FLAG_TRUE;
        Map<Integer, TabContactLog> contactLogMap = getLastByTime(memberId, clerkId, null, null);
        TabContactLog lastContactLog = contactLogMap.get(bizType);
        Date lastContactTime = null;
        if (lastContactLog != null) {
            lastContactTime = lastContactLog.getContactTime();
            Integer contactOrderLimitDay = getContactOrderLimitDay(lastContactTime);
            if (DateUtil.between(date, lastContactTime, DateUnit.SECOND) > contactOrderLimitDay * 24 * 60 * 60) {
                contactCycle = lastContactLog.getContactCycle() + 1;
            }else {
                contactCycle = lastContactLog.getContactCycle();
                contactCycleFirst = Constant.FLAG_FALSE;
            }
        }
        logger.info("建联周期:{},是否周期内首次:{}", contactCycle, contactCycleFirst);
        // 获取当前建联时间和上一次建联时间之间的跟进类型
        String followTypes = contactFollowMapper.getFollowTypes(enterpriseId, clerkId, memberId, lastContactTime, date);

        TabContactLog contactLog = new TabContactLog();
        contactLog.setFollowTypes(followTypes);
        contactLog.setClerkId(clerkId);
        contactLog.setStoreId(storeId);
        if (clerkDTO != null) {
            storeId = clerkDTO.getStoreId();
            contactLog.setClerkCode(clerkDTO.getClerkCode());
            contactLog.setClerkName(clerkDTO.getClerkName());
            contactLog.setStoreId(storeId);
        }
        if (StringUtils.isNotBlank(storeId)) {
            StoreDTO store = storeService.getStore(storeId);
            if (store != null) {
                contactLog.setStoreCode(store.getStoreCode());
            }
        }
        JSONObject jsonObject = esMemberInfoService.queryDataSingle(enterpriseId, memberId, "potentialScore");
        if (jsonObject != null && jsonObject.getInteger("potentialScore") != null) {
            contactLog.setPotentialScore(jsonObject.getInteger("potentialScore"));
        }
        Long logId = UniqueIdUtils.uniqueLong();
        Long bizId = qdto.getSourceLogId() != null ? qdto.getSourceLogId() : logId;
        contactLog.setLogId(logId);
        contactLog.setMemberId(memberId);
        contactLog.setContactStatus(Constant.FLAG_TRUE);
        contactLog.setContactTime(date);
        contactLog.setContactCycle(contactCycle);
        contactLog.setContactCycleFirst(contactCycleFirst);
        // 成为潜客时间 无用暂不写
        contactLog.setPotentialTime(null);

        contactLog.setSourceType(sourceType == null ? bizType : sourceType);
        contactLog.setBizType(bizType);
        contactLog.setEnterpriseId(enterpriseId);
        contactLog.setSourceLogId(sourceLogId);
        contactLogMapper.insert(contactLog);
        // 刷新es建联时间
        Long clerkContactTime = Long.parseLong(DateUtil.format(date, DatePattern.PURE_DATETIME_PATTERN));
        refreshContactTime(enterpriseId, memberId);
        // 建联跟进记录
        String followRemark = qdto.getFollowRemark();
        if (StringUtils.isNotBlank(followRemark)) {
            ContactFollowQDTO followQDTO = EntityUtil.changeEntityNew(ContactFollowQDTO.class, qdto);
            followQDTO.setFollowType(followType);
            followQDTO.setFollowTime(date);
            followQDTO.setBizId(String.valueOf(bizId));
            contactFollowService.saveFollow(followQDTO);
        }
        // 同步建联
        if (!Objects.equals(qdto.getSyncContactType(), Constant.FLAG_TRUE)) {
            syncContactSend(contactLog,followRemark);
        }
        // 冗余机会人群数据
        if (Objects.equals(bizType, ContactBizTypeEnum.OPPORTUNITY_CUSTOMER.getType())) {
            modifyBizData(memberId, clerkId, enterpriseId, logId);
        }
    }

    /**
     * 冗余机会人群数据
     * @param memberId
     * @param clerkId
     * @param enterpriseId
     * @param logId
     */
    private void modifyBizData(String memberId, String clerkId, String enterpriseId, Long logId) {
        try {
            ServiceResponse<List<String>> crowdTypeResponse = objectivesManageApiService.getMemberCrowdType(memberId, clerkId, enterpriseId);
            List<String> result = crowdTypeResponse.getResult();
            String jsonString = JSON.toJSONString(result);
            logger.info("机会人群数据:{}", jsonString);
            if (CollectionUtils.isNotEmpty(result)) {
                TabContactLog modifyContactLog = new TabContactLog();
                modifyContactLog.setLogId(logId);
                modifyContactLog.setBizData(jsonString);
                contactLogMapper.update(modifyContactLog);
            }
        } catch (Exception e) {
            logger.error("冗余人群数据错误！",e);
        }
    }

    private void syncContactSend(TabContactLog contactLog,String followRemark) {
        // 同步建联
        ContactLogQDTO contactLogQDTO = EntityUtil.changeEntityNew(ContactLogQDTO.class, contactLog);
        contactLogQDTO.setSyncContactType(Constant.FLAG_TRUE);
        contactLogQDTO.setSyncContactTime(contactLog.getContactTime());
        contactLogQDTO.setContactAutoType(null);
        contactLogQDTO.setFollowRemark(followRemark);
        contactLogQDTO.setSourceLogId(contactLog.getLogId());
        String message = JSON.toJSONString(contactLogQDTO);
        String routerName = "autoContactLogForMQ";
        try {
            GicMQClient clientInstance = GICMQClientUtil.getClientInstance();
            clientInstance.sendMessage(routerName, message);
        } catch (Exception e) {
            logger.error("发送错误！路由规则名称：" + routerName + ",message:" + message,e);
        }
    }

    /**
     * 历史数据超过14天建联未转化的按14天周期
     * @param contactTime
     * @return
     */
    private Integer getContactOrderLimitDay(Date contactTime) {
        Integer contactOrderLimitDay = Manage3Constants.CONTACT_ORDER_LIMIT_DAY;
        if (DateUtil.compare(Manage3Constants.CONTACT_FIX_RELEASE_DATE, contactTime) > 0 && DateUtil.between(Manage3Constants.CONTACT_FIX_RELEASE_DATE, contactTime, DateUnit.SECOND) > 14 * 24 * 60 * 60) {
            contactOrderLimitDay = 14;
        }
        logger.info("建联未转化计算天数:{}",contactOrderLimitDay);
        return contactOrderLimitDay;
    }

    @Override
    public void autoContactLog(ContactLogQDTO qdto) {
        if (qdto == null) {
            return;
        }
        String enterpriseId = qdto.getEnterpriseId();
        Integer contactAutoType = qdto.getContactAutoType();
        ContactConfigDTO contactConfig = contactConfigService.getContactConfig(enterpriseId);
        if (contactConfig == null) {
            return;
        }
        List<Integer> contactAutoList = contactConfig.getContactAutoList();
        if (CollectionUtils.isEmpty(contactAutoList) || !contactAutoList.contains(contactAutoType)) {
            logger.info("无法自动建联:{},{}", contactAutoType, contactAutoList);
            return;
        }
        logger.info("自动建联:{}", JSON.toJSONString(qdto));
        try {
            qdto.setFollowType(ContactFollowTypeEnum.AUTO_CONTACT.getCode());
            qdto.setFollowRemark("因" + ContactAutoTypeEnum.fromCode(contactAutoType).getDescription() + ",系统自动标记了建联");
            saveContactLog(qdto);
        } catch (BusinessException e) {
            logger.info("自动建联异常:{}", e.getMessage());
            return;
        }
    }

    @Override
    public void syncContactLog(ContactLogQDTO qdto) {
        if (qdto == null) {
            return;
        }
        Integer sourceType = qdto.getSourceType();
        if (Objects.isNull(sourceType)) {
            return;
        }
        logger.info("同步建联:{}", JSON.toJSONString(qdto));
        Integer bizType = qdto.getBizType();
        for (ContactBizTypeEnum bizTypeEnum : ContactBizTypeEnum.values()) {
            Integer syncBizType = bizTypeEnum.getType();
            if (Objects.equals(bizType, syncBizType)) {
                continue;
            }
            ContactLogQDTO syncQdto = EntityUtil.changeEntityNew(ContactLogQDTO.class, qdto);
            syncQdto.setSyncContactType(Constant.FLAG_TRUE);
            syncQdto.setBizType(syncBizType);
            syncQdto.setSourceType(sourceType);
            try {
                saveContactLog(syncQdto);
            } catch (BusinessException e) {
                logger.info("同步建联异常:{}", e.getMessage());
            }
        }
    }

    @Override
    public void clearContactLog(String enterpriseId,String memberId,Integer clearType,String clerkId) {
        logger.info("清除建联状态:{},clearType:{},clerkId:{}", memberId, clearType,clerkId);
        Map<Integer, TabContactLog> contactLogMap = getLastByTime(memberId, null, null, null);
        if (contactLogMap == null || contactLogMap.isEmpty()) {
            return;
        }
        contactLogMap.forEach((k,v)->{
            // clearType 1 消费清除 2 换绑主导购（不清除表建联状态）
            if (Objects.equals(clearType, 1)) {
                TabContactLog update = new TabContactLog();
                update.setLogId(v.getLogId());
                update.setContactStatus(Constant.FLAG_FALSE);
                contactLogMapper.update(update);
            }else if (Objects.equals(clearType, 2)) {
                String lastClerkId = v.getClerkId();
                if (Objects.equals(lastClerkId, clerkId)) {
                    logger.info("最后一次建联和换绑导购一致则不清除建联");
                    return;
                }
            }
            // 清除es建联时间
            refreshContactTime(enterpriseId, memberId);
        });
    }

    private void refreshContactTime(String enterpriseId, String memberId) {
        JSONObject memberJO = esMemberInfoService.queryDataSingle(enterpriseId, memberId, "clerkChannelContactTime");
        if (memberJO == null) {
            return;
        }
        List<Long> clerkContactTimeList = memberJO.getObject("clerkChannelContactTime",new TypeReference<List<Long>>(){});
        if (clerkContactTimeList == null) {
            clerkContactTimeList = new ArrayList<>();
        }
        List<TabContactLog> list = getClerkContactTimeList(memberId);
        if (CollectionUtils.isNotEmpty(list)) {
            List<ContactLogDTO> dtos = EntityUtil.changeEntityListNew(ContactLogDTO.class, list);
            clerkContactTimeList = ContactBizTypeEnum.getEsClerkContactTimeList(dtos);
        }

        logger.info("刷新建联时间:{},memberId:{}", clerkContactTimeList,memberId);
        DynamicDocDTO dynamicDocDTO = new DynamicDocDTO();
        dynamicDocDTO.setEnterpriseId(enterpriseId);
        dynamicDocDTO.setColumnCategoryCode("member");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", memberId);
        jsonObject.put("memberId", memberId);
        jsonObject.put("clerkChannelContactTime", clerkContactTimeList);
        dynamicDocDTO.setDocJson(jsonObject);
        dynamicDocDTO.setRefresh(Constant.FLAG_TRUE);
        ESResponse res = esDataDynamicOperationApiService.updateDataSingle(dynamicDocDTO, false);
        logger.info("刷新建联时间返回:{}", res.getErrCode());
    }

    @Override
    public TabContactLog getClerkContactTime(String memberId) {
        Map<Integer, TabContactLog> contactMap = getLastByTime(memberId, null, null, null);
        if (contactMap == null || contactMap.isEmpty()) {
            return null;
        }
        TabContactLog lastContactLog = contactMap.get(ContactBizTypeEnum.POTENTIAL_CUSTOMER.getType());
        if (lastContactLog == null) {
            return null;
        }
        Integer contactStatus = lastContactLog.getContactStatus();
        if (Objects.equals(contactStatus, Constant.FLAG_FALSE)) {
            return null;
        }
        String clerkId = lastContactLog.getClerkId();
        Date contactTime = lastContactLog.getContactTime();
        MemberStoreClerkDTO memberStoreClerk = memberService.getMemberStoreClerk(memberId);
        if (memberStoreClerk == null) {
            return null;
        }
        logger.info("建联导购id:{},专属导购id:{}", clerkId, memberStoreClerk.getClerkId());
        if (!Objects.equals(clerkId, memberStoreClerk.getClerkId())) {
            return null;
        }
        Integer contactOrderLimitDay = getContactOrderLimitDay(contactTime);
        if (DateUtil.compare(contactTime, DateUtil.date().offset(DateField.DAY_OF_MONTH, -contactOrderLimitDay)) < 0) {
            return null;
        }
        return lastContactLog;
    }

    @Override
    public List<TabContactLog> getClerkContactTimeList(String memberId) {
        Map<Integer, TabContactLog> contactMap = getLastByTime(memberId, null, null, null);
        if (contactMap == null || contactMap.isEmpty()) {
            return null;
        }
        List<TabContactLog> list = new ArrayList<>();
        contactMap.forEach((k,lastContactLog)->{
            Integer contactStatus = lastContactLog.getContactStatus();
            if (Objects.equals(contactStatus, Constant.FLAG_FALSE)) {
                return;
            }
            String clerkId = lastContactLog.getClerkId();
            Date contactTime = lastContactLog.getContactTime();
            MemberStoreClerkDTO memberStoreClerk = memberService.getMemberStoreClerk(memberId);
            if (memberStoreClerk == null) {
                return;
            }
            logger.info("建联导购id:{},专属导购id:{}", clerkId, memberStoreClerk.getClerkId());
            if (!Objects.equals(clerkId, memberStoreClerk.getClerkId())) {
                return;
            }
            Integer contactOrderLimitDay = getContactOrderLimitDay(contactTime);
            if (DateUtil.compare(contactTime, DateUtil.date().offset(DateField.DAY_OF_MONTH, -contactOrderLimitDay)) < 0) {
                return;
            }
            list.add(lastContactLog);
        });
        return list;
    }

    @Override
    public Map<Integer, TabContactLog> getLastByTime(String memberId, String clerkId, Date beginTime, Date endTime) {
        List<TabContactLog> list = contactLogMapper.queryLastLog(memberId, clerkId, beginTime, endTime);
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.toMap(TabContactLog::getBizType, v -> v, (e, x) -> e));
    }
}
