package com.cyksj.service.corp.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
import com.cyksj.common.util.IoKit;
import com.cyksj.common.util.J11HttpC;
import com.cyksj.common.util.Jsons;
import com.cyksj.common.util.StringUtil;
import com.cyksj.config.corp.WeChatCorpFactory;
import com.cyksj.mapper.GroupsRelationExpiryRecordMapper;
import com.cyksj.mapper.OrderDonMapper;
import com.cyksj.mapper.UserMapper;
import com.cyksj.mapper.corp.*;
import com.cyksj.mapper.manage.coupon.CouponMapper;
import com.cyksj.mapper.market.task.UserBindDetailMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.request.corp.Attachments;
import com.cyksj.model.request.corp.CorpWelcomeMsg;
import com.cyksj.model.request.corp.CorpXmlMessage;
import com.cyksj.model.request.corp.CorpXmlOutMessage;
import com.cyksj.model.response.ExternalContact;
import com.cyksj.model.response.FollowedUser;
import com.cyksj.model.response.corp.*;
import com.cyksj.model.views.CorpUserSearchView;
import com.cyksj.model.views.RenewalView;
import com.cyksj.redis.RedisService;
import com.cyksj.service.corp.CorpService;
import com.cyksj.service.corp.WxCorpOps;
import com.cyksj.service.corp.msg.CorpEventActionService;
import com.cyksj.service.mange.coupon.CouponCommonService;
import com.cyksj.service.market.MarketFrontService;
import com.cyksj.service.oceanengine.OceanengineService;
import com.cyksj.service.order.OrderDonPostService;
import com.cyksj.service.relation.GroupRelationFrontService;
import com.cyksj.service.sys.SysConfigService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapUtils;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/*
 *项目名: netflix
 *文件名: CorpEventActionServiceImpl
 *创建者: JavaZou
 *创建时间:2022/10/13 16:11
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CorpEventActionServiceImpl implements CorpEventActionService {

	private final WxCorpOps wxCorpOps;

	private final CorpUserMapper corpUserMapper;

	private final CorpUserTagMapper corpUserTagMapper;

	private final CorpUserFollowRelationMapper relationMapper;

	private final UserMapper userMapper;

	private final CorpTagGroupMapper corpTagGroupMapper;

	private final CorpTagMapper corpTagMapper;

	private final CorpUserAuthMapper corpUserAuthMapper;

	private final GroupRelationFrontService groupRelationFrontService;

	private final SysConfigService sysConfigService;

	private final OrderDonMapper orderDonMapper;

	private final MarketFrontService marketFrontService;

	private final CorpNewUserWelcomeMsgMapper corpNewUserWelcomeMsgMapper;

	private final GlobalThreadPoolTaskExecutor THREAD_POOL;

	private final CouponCommonService couponCommonService;

	private final OceanengineService oceanengineService;

	private final CorpFollowActiveCodeMapper corpFollowActiveCodeMapper;

	private final CorpService corpService;

	private final WxCorpAppMapper wxCorpAppMapper;

	private final CorpGroupChatMapper corpGroupChatMapper;

	private final RedisService redisService;

	private final CorpGroupChatMemberMapper corpGroupChatMemberMapper;

	private final BeanSearcher beanSearcher;

	private final CouponMapper couponMapper;

	private final GroupsRelationExpiryRecordMapper groupsRelationExpiryRecordMapper;

	private final CorpUserRelateMapper corpUserRelateMapper;

	private final UserBindDetailMapper userBindDetailMapper;

	private final CorpCustomerAcquisitionLinkMapper corpCustomerAcquisitionLinkMapper;

	private final CorpCustomerAcquisitionLinkPopularizeMapper corpCustomerAcquisitionLinkPopularizeMapper;

	private final OrderDonPostService orderDonPostService;

	private final CorpWelcomeTemplateMapper corpWelcomeTemplateMapper;

	private final CorpCustomerAcquistionCallbackMapper corpCustomerAcquistionCallbackMapper;

	private final CorpFollowMapper corpFollowMapper;

	private static final String DEFAULT_MSG = "您好，欢迎加入银河录像局";

	/**
	 * 客户添加成员
	 */
	@Override
	public CorpXmlOutMessage addExternalContact(CorpXmlMessage message, Map<String, Object> context) throws Exception {
		String corpId = message.getToUserName();
		String userId = message.getUserId();
		String externalUserId = message.getExternalUserId();
		String welcomeCode = message.getWelcomeCode();
		//客服动态二维码配置state
		String state = message.getState();
		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
		//1.从企业微信获取客户信息
		CorpExternalContactInfo externalContact = wxCorpOps.getExternalContact(corpId, externalUserId);
		ExternalContact corpUserInfo = externalContact.getExternalContact();
		if (corpUserInfo == null) {
			throw BusinessRuntimeException.getInstance("暂无客服成员关系");
		}


		THREAD_POOL.execute(() -> {
			//2.客户添加成员信息
			List<FollowedUser> followedUsers = externalContact.getFollowedUsers();
			//保存企微用户
			CorpUser corpUser = saveOrUpdateCorpUser(message, corpUserInfo, followedUsers);
			if (StrUtil.isNotBlank(state)) {
				try {
					followedUsers = wxCorpOps.getExternalContact(message.getToUserName(), message.getExternalUserId()).getFollowedUsers();
				} catch (Exception e) {
				}
			}

			CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(Wrappers.lambdaQuery(CorpUserAuth.class).eq(CorpUserAuth::getExternalUserid, corpUserInfo.getExternalUserId()).eq(CorpUserAuth::getWxCorpId, wxCorpApp.getId()));
			if (corpUserAuth == null) {
				corpUserAuth = new CorpUserAuth();
				corpUserAuth.setWxCorpId(wxCorpApp.getId());
				corpUserAuth.setCorpUserId(corpUser.getId());
				corpUserAuth.setExternalUserid(corpUserInfo.getExternalUserId());
				corpUserAuthMapper.insert(corpUserAuth);
			}


//			Set<String> relationFollowUserIds = relationMapper.selectList(Wrappers.lambdaQuery(CorpUserFollowRelation.class)
//					.select(CorpUserFollowRelation::getFollowId)
//					.eq(CorpUserFollowRelation::getWxCorpId, wxCorpApp.getCorpId())
//					.eq(CorpUserFollowRelation::getCorpUserId, corpUserInfo.getExternalUserId())).stream().map(CorpUserFollowRelation::getFollowId).collect(Collectors.toSet());

			followedUsers.stream()
//					.filter((followedUser) -> !relationFollowUserIds.contains(followedUser.getUserId()))
					.forEach(followedUser -> updateUserFollowRelation(followedUser, corpUserInfo.getExternalUserId(), wxCorpApp.getId()));
		});

		//如果是该客服添加用户，代表通过巨量平台 添加用户.执行广告回传.
		if (userId != null && userId.equals("yami")) {
			THREAD_POOL.execute(() -> {
				oceanengineService.monitorAddCorpPost();
			});
		}


		//发送自定义欢迎语
		//sendDesignWelcomeMsg(corpId, welcomeCode, userId, corpUserInfo.getCorpName());
		return null;
	}

	private void isJoinFixedCustomer(Long userId, String followId) {
		SysConfig corpConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
				.eq(SysConfig::getSysKey, Constant.CORP_FIXED_CUSTOMER)
				.last("limit 1"));
		if (corpConfig != null) {
			Optional.ofNullable(corpConfig.getSysValue()).ifPresent(value -> {
				try {
					if (StrUtil.isNotBlank(value)) {
						List<String> followIds = Jsons.parseList(value, String.class);
						if (followIds.contains(followId)) {
							//发放添加固定客服优惠券
							couponCommonService.sendCouponToUser(userId, 38l, 0l, 0l, 0l, CouponUser.Channel.wxCorp);
						}
					}
				} catch (Exception e) {
				}
			});
		}
	}

	private void sendSpecificChanceNum(Long userId) throws Exception {
		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
		if (lottery_specific_goods == null) {
			return;
		}
		String sysValue = lottery_specific_goods.getSysValue();
		if (StrUtil.isEmpty(sysValue)) {
			return;
		}
		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);
		if (goodsIdList.isEmpty() || goodsIdList.contains(null)) {
			return;
		}
		SysConfig timeSys = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_ORDER_EFFECTIVE_TIME).last("limit 1"));
		Integer effectiveTime = timeSys == null ? 1 : Integer.parseInt(Optional.ofNullable(timeSys.getSysValue()).orElse("1"));
		List<OrderDon> orderDons = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
				.eq(OrderDon::getUserId, userId)
				.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
				.ge(OrderDon::getCreatedTime, DateUtil.offsetDay(DateTime.now(), -effectiveTime))
				.select(OrderDon::getId, OrderDon::getGoodsId, OrderDon::getSkuId, OrderDon::getUserId));
		orderDons.forEach(order -> {
			if (goodsIdList.contains(order.getGoodsId())) {
				try {
					marketFrontService.addSpecificChanceNumNoWxCorp(order.getUserId(), order.getId(), order.getGoodsId(), order.getSkuId());
				} catch (Exception e) {
					log.error("加入企业微信发放特定抽奖机会错误,orderId:{},e:{}", order.getId(), e);
				}
			}
		});
	}

	/**
	 * 修改外部联系人的备注、手机号或标签
	 */
	@Override
	public CorpXmlOutMessage editExternalContact(CorpXmlMessage message, Map<String, Object> context) throws Exception {
		String corpId = message.getToUserName();
		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
		//客户id
		String externalUserId = message.getExternalUserId();
		//成员id
		String userId = message.getUserId();
		CorpExternalContactInfo externalContact = wxCorpOps.getExternalContact(corpId, externalUserId);
		Map<String, List<FollowedUser>> followedUserMap = externalContact.getFollowedUsers().stream().collect(Collectors.groupingBy(FollowedUser::getUserId));
		FollowedUser followedUser = followedUserMap.get(userId).get(0);
		//修改客户关系
		updateUserFollowRelation(followedUser, externalUserId, wxCorpApp.getId());

		//保存企微用户
		if (externalContact.getExternalContact() != null) {
			saveOrUpdateCorpUser(message, externalContact.getExternalContact(), null);
		}
		return null;
	}

	/**
	 * 删除企业客户事件
	 */
	@Override
	public CorpXmlOutMessage delExternalContact(CorpXmlMessage message, Map<String, Object> context) {
		//客户id
		String externalUserId = message.getExternalUserId();
		//成员id
		String userId = message.getUserId();
		corpUnfriend(externalUserId, userId, userId);
		return null;
	}

	/**
	 * 删除跟进成员事件
	 */
	@Override
	public CorpXmlOutMessage delFollowUser(CorpXmlMessage message, Map<String, Object> context) {
		//客户id
		String externalUserId = message.getExternalUserId();
		//成员id
		String userId = message.getUserId();
		corpUnfriend(externalUserId, userId, externalUserId);
		return null;
	}

	/**
	 * 企业微信客户标签创建事件
	 */
	@Override
	public CorpXmlOutMessage saveCorpTag(CorpXmlMessage message, Map<String, Object> context) throws Exception {
		CorpUserExternalTagGroupList tagInfo = null;
		if (message.getTagType().equals("tag")) {
			tagInfo = wxCorpOps.getCorpTagList(message.getToUserName(), List.of(message.getId()), Collections.emptyList());
		} else if (message.getTagType().equals("tag_group")) {
			tagInfo = wxCorpOps.getCorpTagList(message.getToUserName(), Collections.emptyList(), List.of(message.getId()));
		}
		//落库
		if (tagInfo != null) {
			updateCorpTagGroup(tagInfo);
		}
		return null;
	}

	/**
	 * 企业微信客户标签删除事件
	 */
	@Override
	public CorpXmlOutMessage delCorpTag(CorpXmlMessage message, Map<String, Object> context) {
		if (message.getTagType().equals("tag")) {
			CorpTag corpTag = corpTagMapper.selectOne(Wrappers.lambdaQuery(CorpTag.class)
					.eq(CorpTag::getTagId, message.getId()).last("limit 1"));
			if (corpTag != null) {
				corpTagMapper.deleteById(corpTag.getId());

				Integer count = corpTagMapper.selectCount(Wrappers.lambdaQuery(CorpTag.class)
						.eq(CorpTag::getGroupId, corpTag.getGroupId()));
				if (count == 0) {
					corpTagGroupMapper.delete(Wrappers.lambdaQuery(CorpTagGroup.class)
							.eq(CorpTagGroup::getGroupId, corpTag.getGroupId()));
				}
			}
		} else if (message.getTagType().equals("tag_group")) {
			CorpTagGroup corpTagGroup = corpTagGroupMapper.selectOne(Wrappers.lambdaQuery(CorpTagGroup.class)
					.eq(CorpTagGroup::getGroupId, message.getId()).last("limit 1"));
			if (corpTagGroup != null) {
				corpTagGroupMapper.deleteById(corpTagGroup.getId());

				corpTagMapper.delete(Wrappers.lambdaQuery(CorpTag.class)
						.eq(CorpTag::getGroupId, corpTagGroup.getGroupId()));
			}
		}
		return null;
	}

	@Override
	public CorpXmlOutMessage saveCorpGroupChat(CorpXmlMessage message, Map<String, Object> context) throws Exception {
		String corpId = message.getToUserName();
		WxCorpApp wxCorpApp = wxCorpAppMapper.selectOne(Wrappers.lambdaQuery(WxCorpApp.class)
				.eq(WxCorpApp::getCorpId, corpId).last("limit 1"));
		if (wxCorpApp == null) {
			log.error("企业微信:{}配置不存在", corpId);
			return null;
		}
		if (initCorpGroupsChat(wxCorpApp)) {
			return null;
		}
		saveCorpGroupChatDetail(wxCorpApp, message);
		return null;
	}

	/**
	 * 初始化企业微信客户群
	 */
	public Boolean initCorpGroupsChat(WxCorpApp wxCorpApp) {
		List<CorpGroupChat> corpGroupChats = corpGroupChatMapper.selectList(null);
		if (corpGroupChats.isEmpty()) {
			String key = RedisService.key.CORP_GROUP_CHAT_LIST.getNameFormat(wxCorpApp.getCorpId());
			if (redisService.setNx(key, wxCorpApp.getCorpId(), 60 * 60 * 24l)) {
				THREAD_POOL.execute(() -> {
					try {
						getChatGroupChatListDetail(wxCorpApp, "", 100);
					} catch (Exception e) {
					}
					redisService.del(key);
				});
			}
			return true;
		}
		return false;
	}

	/**
	 * 获取企业客户群列表信息
	 */
	private void getChatGroupChatListDetail(WxCorpApp wxCorpApp, String cursor, Integer limit) throws Exception {
		String corpId = wxCorpApp.getCorpId();
		CorpGroupChatListDetail list = wxCorpOps.getGroupChatList(corpId, cursor, limit);
		predicateOrSaveCorpGroupChat(wxCorpApp,list);
		if (StrUtil.isNotEmpty(list.getNextCursor())) {
			getChatGroupChatListDetail(wxCorpApp, list.getNextCursor(), limit);
		}
	}

	private void predicateOrSaveCorpGroupChat(WxCorpApp wxCorpApp, CorpGroupChatListDetail list) {
		list.getGroupChatList().stream().forEach(obj -> {
			CorpXmlMessage message = new CorpXmlMessage();
			message.setChatId(obj.getChatId());
			try {
				saveCorpGroupChatDetail(wxCorpApp, message);
			} catch (Exception e) {
			}
		});
	}

	private void saveCorpGroupChatDetail(WxCorpApp wxCorpApp, CorpXmlMessage message) throws Exception {
		String corpId = wxCorpApp.getCorpId();
		CorpGroupChatDetail detail = wxCorpOps.getCorpGroupChatDetail(corpId, message);
		//企业客户群信息
		CorpGroupChat corpGroupChat = CorpGroupChat.builder()
				.chatId(detail.getChatId())
				.chatName(detail.getName())
				.wxCorpId(wxCorpApp.getId())
				.corpId(corpId)
				.owner(detail.getOwner())
				.groupCreateTime(DateTime.of(detail.getCreateTime() * 1000))
				.build();
		try {
			//企业客户群
			corpGroupChatMapper.insert(corpGroupChat);
			final Long groupChatId =corpGroupChat.getId();
			//企业客户群成员信息
			List<CorpGroupChatMemberObj> memberList = detail.getMemberList();
			corpGroupSyncYhUserId(memberList, wxCorpApp.getId(), groupChatId);
		} catch (DuplicateKeyException e) {
		}
	}

	@Override
	public CorpXmlOutMessage updateCorpGroupChat(CorpXmlMessage message, Map<String, Object> context) throws Exception {
		String corpId = message.getToUserName();
		WxCorpApp wxCorpApp = wxCorpAppMapper.selectOne(Wrappers.lambdaQuery(WxCorpApp.class)
				.eq(WxCorpApp::getCorpId, corpId).last("limit 1"));
		if (wxCorpApp == null) {
			log.error("企业微信:{}配置不存在", corpId);
			return null;
		}
		if (initCorpGroupsChat(wxCorpApp)) {
			return null;
		}
		CorpGroupChatDetail detail = wxCorpOps.getCorpGroupChatDetail(corpId, message);

		THREAD_POOL.execute(()->{
			List<String> corpGroupEvent = List.of("change_owner", "change_name");
			if (corpGroupEvent.contains(message.getUpdateDetail())) {
				CorpGroupChat entity = corpGroupChatMapper.selectOne(Wrappers.lambdaQuery(CorpGroupChat.class)
						.eq(CorpGroupChat::getWxCorpId, wxCorpApp.getId())
						.eq(CorpGroupChat::getChatId, message.getChatId()).last("limit 1"));
				if ("change_owner".equals(message.getUpdateDetail())) {
					log.info("{}群主变更事件", message.getChatId());
					entity.setOwner(detail.getOwner());
				}
				if ("change_name".equals(message.getUpdateDetail())) {
					log.info("{}群名修改事件", message.getChatId());
					entity.setChatName(detail.getName());
				}
				corpGroupChatMapper.updateById(entity);
			}
			List<String> memberEvent = List.of("del_member", "add_member");
			if (memberEvent.contains(message.getUpdateDetail())) {
				CorpGroupChat corpGroupChat = corpGroupChatMapper.selectOne(Wrappers.lambdaQuery(CorpGroupChat.class)
						.eq(CorpGroupChat::getWxCorpId, wxCorpApp.getId())
						.eq(CorpGroupChat::getChatId, detail.getChatId()).last("limit 1"));
				if (corpGroupChat == null) {
					log.info("企业微信客户群:{} 库中不存在", detail.getChatId());
					return;
				}
				List<String> userList = corpGroupChatMemberMapper.getAllMemberByCorpIdAndChatId(corpGroupChat.getId());
				if ("del_member".equals(message.getUpdateDetail())) {
					log.info("客户退群{}事件", message.getChatId());
					//存在库里面没有群成员
					List<String> collect = detail.getMemberList().stream().map(CorpGroupChatMemberObj::getUserId).collect(Collectors.toList());
					userList.removeAll(collect);
					Lists.partition(userList, 100).stream().forEach(objs -> corpGroupChatMemberMapper.batchDeleteByChatIdAndUserId(corpGroupChat.getId(), objs));
				}
				if ("add_member".equals(message.getUpdateDetail())) {
					log.info("客户入群{}事件", message.getChatId());
					List<CorpGroupChatMemberObj> addCollect = detail.getMemberList().stream().filter(obj -> !userList.contains(obj.getUserId())).collect(Collectors.toList());
					corpGroupSyncYhUserId(addCollect, wxCorpApp.getId(), corpGroupChat.getId());
				}
			}
		});

		return null;
	}

	public void corpGroupSyncYhUserId(List<CorpGroupChatMemberObj> memberList, Long wxCorpId, Long groupChatId) {
		Lists.partition(memberList, 100).forEach(members -> {
			List<String> corpUserIds = members.stream().map(CorpGroupChatMemberObj::getUserId).collect(Collectors.toList());
			Map<String, List<CorpUserSearchView>> corpUserIdMap = beanSearcher.searchAll(CorpUserSearchView.class, MapUtils.builder()
					.field(CorpUserSearchView::getWxCorpId, wxCorpId)
					.field(CorpUserSearchView::getCorpUserId, corpUserIds).op(Operator.InList).build())
					.stream().collect(Collectors.groupingBy(CorpUserSearchView::getCorpUserId));
			members.forEach(data -> {
				List<CorpUserSearchView> corpUserSearchViews = corpUserIdMap.get(data.getUserId());
				Long yhUserId = null;
				if (CollUtil.isNotEmpty(corpUserSearchViews)) {
					yhUserId = corpUserSearchViews.get(0).getUserId();
				}
				if (yhUserId.intValue() == 0) {
					yhUserId = corpUserMapper.selectUserIdByCropUserId(wxCorpId, data.getUserId());
				}
				data.setYhUserId(yhUserId);
			});
			corpGroupChatMemberMapper.batchInsert(groupChatId, wxCorpId, members);
		});
	}

	@Override
	public CorpXmlOutMessage delCorpGroupChat(CorpXmlMessage message) {
		//删除企业客户群及关联关系
		String corpId = message.getToUserName();
		WxCorpApp wxCorpApp = wxCorpAppMapper.selectOne(Wrappers.lambdaQuery(WxCorpApp.class)
				.eq(WxCorpApp::getCorpId, corpId).last("limit 1"));
		if (wxCorpApp == null) {
			log.error("企业客服群删除,企业微信配置:{}不存在", corpId);
			return null;
		}
		corpGroupChatMapper.update(null, Wrappers.lambdaUpdate(CorpGroupChat.class)
				.set(CorpGroupChat::getDeleted, false)
				.eq(CorpGroupChat::getWxCorpId, wxCorpApp.getId())
				.eq(CorpGroupChat::getChatId, message.getChatId()));

		CorpGroupChat corpGroupChat = corpGroupChatMapper.selectOne(Wrappers.lambdaQuery(CorpGroupChat.class)
				.eq(CorpGroupChat::getChatId, message.getChatId())
				.eq(CorpGroupChat::getWxCorpId, wxCorpApp.getId()));
		if (corpGroupChat != null) {
			corpGroupChat.setDeleted(false);
			corpGroupChatMapper.updateById(corpGroupChat);

			corpGroupChatMemberMapper.update(null, Wrappers.lambdaUpdate(CorpGroupChatMember.class)
					.set(CorpGroupChatMember::getDeleted, false)
					.eq(CorpGroupChatMember::getGroupChatId, corpGroupChat.getId()));
		}
		return null;
	}

	@Override
	public CorpXmlOutMessage msgAuditApproved(CorpXmlMessage message, Map<String, Object> context) {
		//修改 会话存档同意状态
		String corpId = message.getToUserName();
		String userId = message.getUserId();
		String externalUserId = message.getExternalUserId();
		//客服动态二维码配置state
		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
		CorpUserFollowRelation relation = relationMapper
				.selectOne(Wrappers.lambdaQuery(CorpUserFollowRelation.class)
						.eq(CorpUserFollowRelation::getWxCorpId, wxCorpApp.getId())
						.eq(CorpUserFollowRelation::getCorpUserId, externalUserId)
						.eq(CorpUserFollowRelation::getFollowId, userId)
						.last("limit 1"));
		if(relation != null){
			relation.setAgreeStatus("Agree");
			relationMapper.updateById(relation);
		}else {
			throw  BusinessRuntimeException.getInstance("用户还未保存.");
		}
		return null;
	}

	@Override
	public CorpXmlOutMessage customerStartChat(CorpXmlMessage message, Map<String, Object> context) {
		//微信客户发起会话事件
		//外部联系人id
		String externalUserId = message.getExternalUserId();
		log.info("监听微信客户:{}发起会话事件", externalUserId);

		//获客链接id
		String linkId = message.getLinkId();
		CorpCustomerAcquisitionLink corpCustomerAcquisitionLink = corpCustomerAcquisitionLinkMapper.selectOne(Wrappers.lambdaQuery(CorpCustomerAcquisitionLink.class).eq(CorpCustomerAcquisitionLink::getLinkId, linkId));

		if(corpCustomerAcquisitionLink != null){
			//记录发起对话事件
			CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectOne(Wrappers.lambdaQuery(CorpCustomerAcquisitionLinkPopularize.class)
					.eq(CorpCustomerAcquisitionLinkPopularize::getIsChat, 1)
					.eq(CorpCustomerAcquisitionLinkPopularize::getCustomerAcquistionLinkId, corpCustomerAcquisitionLink.getId()).last("limit 1"));
			if (corpCustomerAcquisitionLinkPopularize != null) {
				redisService.sSet(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getName(), externalUserId);
			}
		}

		return null;
	}

	@Override
	public CorpXmlOutMessage creatOrUpdateFollowUser(CorpXmlMessage message) throws Exception {
		//corpId
		String corpId = message.getToUserName();
		//成员id
		String userId = message.getUserId();

		Long wxCorpId = WeChatCorpFactory.getCorpConfigStrategy(corpId).getId();
		CorpFollow corpFollow = corpFollowMapper.selectOne(Wrappers.lambdaQuery(CorpFollow.class).eq(CorpFollow::getWxCorpId, wxCorpId).eq(CorpFollow::getUserid, userId));
		CorpUserInfo userInfo = wxCorpOps.getFollowUser(corpId, userId);
		if (corpFollow == null) {
			corpFollow = new CorpFollow();
			BeanUtil.copyProperties(userInfo, corpFollow);
			corpFollow.setWxCorpId(wxCorpId);
			corpFollowMapper.insert(corpFollow);
			//同步客户列表
			getCorpUserInfo(corpId, corpFollow.getUserid());
		} else {
			BeanUtil.copyProperties(userInfo, corpFollow);
			corpFollowMapper.updateById(corpFollow);
		}
		return null;
	}

	/**
	 * 修改客户成员关系，客户标签
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void updateUserFollowRelation(FollowedUser followedUser, String externalUserid, Long wxCorpId) {
		CorpUserFollowRelation relation = Optional.ofNullable(relationMapper
				.selectOne(Wrappers.lambdaQuery(CorpUserFollowRelation.class)
						.eq(CorpUserFollowRelation::getWxCorpId, wxCorpId)
						.eq(CorpUserFollowRelation::getCorpUserId, externalUserid)
						.eq(CorpUserFollowRelation::getFollowId, followedUser.getUserId())
						.last("limit 1"))).orElse(new CorpUserFollowRelation().setFollowId(followedUser.getUserId()).setCorpUserId(externalUserid));
		//存储关系表
		relation.setRemark(followedUser.getRemark());
		relation.setDescription(followedUser.getDescription());
		relation.setAddCreatedTime(new Date(followedUser.getCreateTime() * 1000));
		relation.setRemarkMobiles(Arrays.toString(followedUser.getRemarkMobiles()));
		relation.setAddWay(CorpUserFollowRelation.Way.getDesc(followedUser.getAddWay()));
		relation.setOperUserid(followedUser.getOperatorUserId());
		relation.setStatus(1);
		relation.setWxCorpId(wxCorpId);
		if (relation.getId() == null) relationMapper.insert(relation);
		else relationMapper.updateById(relation);

		List<CorpUserTag> corpUserTags = Optional.ofNullable(corpUserTagMapper.selectList(Wrappers.lambdaQuery(CorpUserTag.class)
				.eq(CorpUserTag::getRelationId, relation.getId()))).orElse(new ArrayList<>());
		List<String> exists_tagIds = corpUserTags.stream().map(CorpUserTag::getTagId).collect(Collectors.toList());
		//存储用户标签
		Stream.of(followedUser.getTags()).forEach((tag) -> {
			//相同标签
			if (CollUtil.isNotEmpty(exists_tagIds) && exists_tagIds.contains(tag.getTagId())) {
				exists_tagIds.remove(tag.getTagId());
				return;
			}
			CorpUserTag corpUserTag = new CorpUserTag();
			corpUserTag.setRelationId(relation.getId());
			corpUserTag.setGroupName(tag.getGroupName());
			corpUserTag.setTagName(tag.getTagName());
			corpUserTag.setTagId(tag.getTagId());
			corpUserTag.setType(tag.getType());
			corpUserTagMapper.insert(corpUserTag);
		});

		//存在被删除的标签
		if (CollUtil.isNotEmpty(exists_tagIds)) {
			log.info("需删除用户:{}对应客服:{}关联已删除的标签:{}", externalUserid, relation.getFollowId(), exists_tagIds);
			corpUserTagMapper.delete(Wrappers.lambdaQuery(CorpUserTag.class)
					.in(CorpUserTag::getTagId, exists_tagIds)
					.eq(CorpUserTag::getRelationId, relation.getId()));
		}

		//同步企业微信 银河用户id
		Optional.ofNullable(corpUserMapper.setCorpUserUserId(relation.getCorpUserId()))
				.ifPresent(corpUser -> {
					if (corpUser.getUserId() == 0) {
						Optional.ofNullable(userMapper.selectOne(Wrappers.lambdaQuery(User.class)
										.eq(User::getUnionid, corpUser.getUnionid()).last("limit 1")))
								.ifPresent(user -> {
									corpUser.setUserId(user.getId());
									corpUserMapper.updateById(corpUser);
								});
					}
				});

	}

	/**
	 * 取消好友关系
	 */
	public void corpUnfriend(String externalUserId, String userId, String delUserId) {

		CorpUserFollowRelation relation = relationMapper
				.selectOne(Wrappers.lambdaQuery(CorpUserFollowRelation.class)
						.eq(CorpUserFollowRelation::getCorpUserId, externalUserId)
						.eq(CorpUserFollowRelation::getFollowId, userId)
						.last("limit 1"));
		if (relation == null) {
			return;
		}
		relation.setStatus(0);
		relation.setDelUserid(delUserId);
		relationMapper.updateById(relation);
	}

	public void updateCorpTagGroup(CorpUserExternalTagGroupList tagInfo) {
		tagInfo.getTagGroupList().forEach((tagGroup) -> {
			CorpTagGroup corpTagGroup = Optional.ofNullable(corpTagGroupMapper.selectOne(Wrappers.lambdaQuery(CorpTagGroup.class).eq(CorpTagGroup::getGroupId, tagGroup.getGroupId()))).orElseGet(() -> {
				CorpTagGroup cor = new CorpTagGroup();
				cor.setGroupId(tagGroup.getGroupId());
				return cor;
			});
			BeanUtil.copyProperties(tagGroup, corpTagGroup);
			if (corpTagGroup.getId() == null) corpTagGroupMapper.insert(corpTagGroup);
			else corpTagGroupMapper.updateById(corpTagGroup);
			List<CorpUserExternalTagGroupList.TagGroup.Tag> tagList = tagGroup.getTag();
			tagList.forEach((tag) -> {
				CorpTag corpTag = Optional.ofNullable(corpTagMapper.selectOne(Wrappers.lambdaQuery(CorpTag.class).eq(CorpTag::getTagId, tag.getId()))).orElseGet(() -> {
					CorpTag cTag = new CorpTag();
					cTag.setTagId(tag.getId());
					return cTag;
				});
				corpTag.setGroupId(corpTagGroup.getGroupId());
				corpTag.setGroupName(corpTagGroup.getGroupName());
				corpTag.setName(tag.getName());
				if (corpTag.getId() == null) corpTagMapper.insert(corpTag);
				else corpTagMapper.updateById(corpTag);
			});
		});
	}

	public void sendDesignWelcomeMsg(String corpId, String welcomeCode, String followId, String corpUserName) {
		//新用户欢迎语
		if (StrUtil.isNotEmpty(welcomeCode)) {
			THREAD_POOL.execute(() -> {
				SysConfig corpConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
						.eq(SysConfig::getSysKey, Constant.CORP_POPULARIZE_CUSTOMER)
						.eq(SysConfig::getSysValue, followId)
						.last("limit 1"));
				Optional.ofNullable(corpConfig).ifPresent(config -> {
					JSONObject params = new JSONObject();
					CorpNewUserWelcomeMsg corpNewUserWelcomeMsg = Optional.ofNullable(corpNewUserWelcomeMsgMapper.selectOne(Wrappers.lambdaQuery(CorpNewUserWelcomeMsg.class).eq(CorpNewUserWelcomeMsg::getIsDefault, true).eq(CorpNewUserWelcomeMsg::getCorpId, corpId).eq(CorpNewUserWelcomeMsg::getFollowId, followId).last("limit 1"))).orElseGet(() -> new CorpNewUserWelcomeMsg(DEFAULT_MSG));
					HashMap<String, Object> text = new HashMap<>(1);
					text.put("content", corpNewUserWelcomeMsg.getText());
					params.putOpt("welcome_code", welcomeCode);
					params.putOpt("text", text);
					Optional.ofNullable(corpNewUserWelcomeMsg.getIsLink()).ifPresent(linkUrl -> {
						List<Attachments> attachments = new ArrayList<>();
						Attachments link = new Attachments("link", new Attachments.Link(corpNewUserWelcomeMsg.getLinkTitle(), corpNewUserWelcomeMsg.getLinkPicUrl(), corpNewUserWelcomeMsg.getLinkDesc(), corpNewUserWelcomeMsg.getLinkUrl()));
						attachments.add(link);
						params.putOpt("attachments", attachments);
					});
					HttpResponse<byte[]> res = null;
					try {
						res = J11HttpC.custom()
								.ofPost()
								.url(String.format("https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=%s", wxCorpOps.getAccessToken(corpId)))
								.body(HttpRequest.BodyPublishers.ofString(params.toString(), IoKit.Charsets.UTF_8.getCharset()))
								.headers(J11HttpC.ReqType.raw_json)
								.send(HttpResponse.BodyHandlers.ofByteArray());
						JSONObject jsonObject = Jsons.parseObject(res.body(), JSONObject.class);
						if (jsonObject.getInt("errcode") != 0) {
							log.info("{}成员,发送欢迎语至客户{}失败,msg:{}", followId, corpUserName, jsonObject.get("errmsg"));
							return;
						}
						log.info("{}成员,发送欢迎语至客户{}成功", followId, corpUserName);
					} catch (Exception e) {
						log.info("发送欢迎语过程异常,{}", e);
					}
				});
			});
		}
	}


	public CorpUser saveOrUpdateCorpUser(CorpXmlMessage message, ExternalContact corpUserInfo, List<FollowedUser> followedUsers) {
		//查询客户是否存在
		CorpUser corpUser = Optional.ofNullable(
						corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class)
								.eq(CorpUser::getUnionid, corpUserInfo.getUnionId())))
				.orElseGet(() -> new CorpUser()
						.setUnionid(corpUserInfo.getUnionId()));

		corpUser.setName(corpUserInfo.getName());
		corpUser.setGender(corpUserInfo.getGender());
		corpUser.setAvatar(corpUserInfo.getAvatar());
		corpUser.setType(corpUserInfo.getType());
		String state = message.getState();
		CorpFollowActiveCode corpFollowActiveCode = null;
		AtomicBoolean isSendWelcomeMsg = new AtomicBoolean(false);
		CorpWelcomeTemplate corpWelcomeTemplate = null;
		if (StrUtil.isNotBlank(state) && state.contains(Constant.AC_CODE_KEY)) {
			//查找对应的活动活码 记录
			String acIdStr = StrUtil.subAfter(state, StrUtil.C_COLON, true);
			if (Validator.isNumber(acIdStr)) {
				Long acId = Long.parseLong(acIdStr);
				corpFollowActiveCode = corpFollowActiveCodeMapper.selectById(acId);
				if (corpFollowActiveCode != null) {
					if (corpUser.getId() == null) {
						corpUser.setAcId(acId);
					}
					//欢迎语模板id
					Long msgId = corpFollowActiveCode.getMsgId();
					corpWelcomeTemplate = sendWelcomeMsg(msgId, message);
					isSendWelcomeMsg.set(true);
					try {
						//对客户进行标记
						markAddUserTag(corpFollowActiveCode.getMarkTag(), message);
						state = corpFollowActiveCode.getMarkTag();
					} catch (Exception e) {
					}
				}
			}
		}

		//加粉深度回传逻辑.
		if(StrUtil.isNotBlank(message.getState()) && message.getState().contains(Constant.ACQUISTION_LINK_STATE_KEY)){
			String customer = message.getState().replaceAll("customer_", "");
			saveAcqusitionCallback(customer, corpUser, message);
			isSendWelcomeMsg.set(true);
		}

		//扫码来源
		if (corpUser.getId() == null) {
			corpUser.setState(state);
		}

		//打标签 抖音渠道活码 已有 兼容之前的临时
		if (StrUtil.isNotBlank(message.getState())) {
			//打标签
			SysConfig one = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
					.eq(SysConfig::getSysKey, Constant.ACTIVE_CODE_TEMP_KEY).last("limit 1"));
			if (one != null && StrUtil.isNotBlank(one.getSysValue()) && CollUtil.isNotEmpty(followedUsers)) {
				try {
					List<String> activeCodeList = Jsons.parseList(one.getSysValue(), String.class);
					if (activeCodeList.contains(message.getState())) {
						//查询对应标签是否存在
						CorpTag corpTag = corpTagMapper.selectOne(Wrappers.lambdaQuery(CorpTag.class)
								.eq(CorpTag::getName, message.getState()).last("limit 1"));
						if (corpTag == null) {
							try {
								corpTag = addCorpTag(message.getState(), message.getState(), message.getToUserName());
							} catch (Exception e) {
							}
						}
						if (corpTag != null) {
							List<String> tagId = List.of(corpTag.getTagId());
							wxCorpOps.markTag(corpUserInfo.getExternalUserId(), message.getUserId(), tagId.toArray(new String[tagId.size()]), null);
						}
					}
				} catch (Exception e) {
				}
			}
		}

		//新增修改客户信息
		if (corpUser.getId() == null) {
			//查询是否已微信授权，关联user表id
			User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getUnionid, corpUser.getUnionid()));
			if (user != null) {
				corpUser.setUserId(user.getId());
				//加入企业微信后发放优惠券
				groupRelationFrontService.isJoinCorpWx(user.getId(), true, false);
				//发放抽奖机会
				try {
					sendSpecificChanceNum(user.getId());
				} catch (Exception e) {
				}
				//添加固定客服发放优惠券
				isJoinFixedCustomer(user.getId(), message.getUserId());

				//活码 优惠券发送
				if (corpFollowActiveCode != null && corpFollowActiveCode.getMsgId() != 0) {
					Long msgId = corpFollowActiveCode.getMsgId();
					if (corpWelcomeTemplate == null) {
						corpWelcomeTemplate = corpWelcomeTemplateMapper.selectById(msgId);
					}
					String couponIdsStr = corpWelcomeTemplate != null ? corpWelcomeTemplate.getCouponIds() : null;
					try {
						if (StrUtil.isNotBlank(couponIdsStr)) {
							List<Long> couponIds = Jsons.parseList(couponIdsStr, Long.class);
							couponIds.forEach(couponId -> couponCommonService.sendCouponToUser(user.getId(), couponId, 0l, 0l, 0l, CouponUser.Channel.corp_active_code));
						}
					} catch (Exception e) {
					}
				}
			}
			corpUserMapper.insert(corpUser);
		} else {
			corpUserMapper.updateById(corpUser);
		}

		if (CollUtil.isNotEmpty(followedUsers)) {
			followedUsers.forEach(followedUser -> {
				//备注手机号  客服跟进用户年付续费
				String description = followedUser.getDescription();
				if (Validator.isMobile(description)) {
					THREAD_POOL.execute(() ->{
						CorpUserRelate corpUserRelate = corpUserRelateMapper.selectOne(Wrappers.lambdaQuery(CorpUserRelate.class)
								.eq(CorpUserRelate::getCorpUserId, corpUser.getId()).last("limit 1"));
						if (corpUserRelate != null) {
							corpUserRelate.setPhone(description);
							corpUserRelateMapper.updateById(corpUserRelate);
						} else {
							corpUserRelate = new CorpUserRelate();
							corpUserRelate.setCorpUserId(corpUser.getId());
							corpUserRelate.setPhone(description);
							corpUserRelateMapper.insert(corpUserRelate);
						}
						//客服续费跟进
						corpRenewFollowUser(description);
					});
				}
			});
		}

		//若没找到规则的欢迎语 发送默认欢迎语
		if (StrUtil.isNotEmpty(message.getWelcomeCode()) && !isSendWelcomeMsg.get()) {
			CorpWelcomeTemplate serviceWelcomeTemplate = corpWelcomeTemplateMapper.selectOne(Wrappers.lambdaQuery(CorpWelcomeTemplate.class)
					.eq(CorpWelcomeTemplate::getType, 0)
					.eq(CorpWelcomeTemplate::getDeleted, 1)
					.last("limit 1"));
			if (serviceWelcomeTemplate == null) {
				log.info("===========未找到自然流量默认欢迎语===========");
			}
			if (serviceWelcomeTemplate != null) {
				log.info("===========找到自然流量默认欢迎语记录===========");
				senCorpWelcomeMsg(message, serviceWelcomeTemplate.getText(), serviceWelcomeTemplate.getAttachmentsStr());
			}
		}
		return corpUser;
	}


	public CorpTag addCorpTag(String tagGroupName, String tagName, String corpId) throws Exception {
		CorpUserExternalTagGroupInfo tagGroupInfoReq = new CorpUserExternalTagGroupInfo();
		CorpUserExternalTagGroupInfo.TagGroup group = new CorpUserExternalTagGroupInfo.TagGroup();
		CorpUserExternalTagGroupInfo.Tag tag = new CorpUserExternalTagGroupInfo.Tag();
		tag.setName(tagName);
		group.setTag(List.of(tag));
		group.setGroupName(tagGroupName);
		tagGroupInfoReq.setTagGroup(group);
		CorpUserExternalTagGroupInfo corpUserExternalTagGroupInfo = wxCorpOps.addCorpTag(tagGroupInfoReq, corpId);
		CorpUserExternalTagGroupInfo.TagGroup tagGroup = corpUserExternalTagGroupInfo.getTagGroup();
		List<CorpUserExternalTagGroupInfo.Tag> tagList = tagGroup.getTag();
		for (CorpUserExternalTagGroupInfo.Tag save_tag : tagList) {
			if (StrUtil.equals(tagName, save_tag.getName())) {
				CorpTag corpTag = new CorpTag();
				corpTag.setGroupId(tagGroup.getGroupId());
				corpTag.setGroupName(tagGroup.getGroupName());
				corpTag.setType(1);

				CorpTagGroup corpTagGroup = new CorpTagGroup();
				corpTagGroup.setGroupId(tagGroup.getGroupId());
				corpTagGroup.setGroupName(tagGroup.getGroupName());
				corpTagGroupMapper.insert(corpTagGroup);

				corpTag.setTagId(save_tag.getId());
				corpTag.setName(save_tag.getName());
				corpTagMapper.insert(corpTag);
				return corpTag;
			}
		}
		return null;
	}

	/**
	 * 发送欢迎语
	 */
	public void senCorpWelcomeMsg(CorpXmlMessage message, String content, String attachmentsStr) {
		try {
			String welcomeCode = message.getWelcomeCode();
			String followId = message.getUserId();
			CorpWelcomeMsg corpWelcomeMsg = new CorpWelcomeMsg();
			//新用户欢迎语
			if (StrUtil.isNotBlank(content)) {
				CorpWelcomeMsg.Text text = new CorpWelcomeMsg.Text();
				text.setContent(content);
				corpWelcomeMsg.setText(text);
			}
			//附件
			LinkedList<Attachments> attachments;
			if (StrUtil.isNotBlank(attachmentsStr)) {
				List<Attachments> dbAttachments = Jsons.parseList(attachmentsStr, Attachments.class);
				attachments = new LinkedList<>();
				for (Attachments dbAttachment : dbAttachments) {
					attachments.add(corpService.updateMaterial(dbAttachment, message.getToUserName(), 1));
				}
				corpWelcomeMsg.setAttachments(attachments);
			}

			corpWelcomeMsg.setWelcomeCode(welcomeCode);
			HttpResponse<byte[]> res = null;
			res = J11HttpC.custom()
					.ofPost()
					.url(String.format("https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=%s", wxCorpOps.getAccessToken(message.getToUserName())))
					.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(corpWelcomeMsg), IoKit.Charsets.UTF_8.getCharset()))
					.headers(J11HttpC.ReqType.raw_json)
					.send(HttpResponse.BodyHandlers.ofByteArray());
			JSONObject jsonObject = Jsons.parseObject(res.body(), JSONObject.class);
			if (jsonObject.getInt("errcode") == 0) {
				log.info("{}成员,发送欢迎语至客户{}成功", followId, message.getExternalUserId());
				return;
			}
			log.info("{}成员,发送欢迎语至客户{}失败,msg:{}", followId, message.getExternalUserId(), jsonObject.get("errmsg"));
		} catch (Exception e) {
			log.info("发送欢迎语过程异常,{}", e);
		}
	}

	/**
	 * 创建标签 并标记客户
	 */
	public void markAddUserTag(String tagName, CorpXmlMessage message) {
		//对客户进行标记
		//查询对应标签是否存在
		String corpId = message.getToUserName();
		String externalUserId = message.getExternalUserId();
		String followId = message.getUserId();
		CorpTag corpTag = corpTagMapper.selectOne(Wrappers.lambdaQuery(CorpTag.class)
				.eq(CorpTag::getName, tagName).last("limit 1"));
		if (corpTag == null) {
			try {
				corpTag = addCorpTag(tagName, tagName, corpId);
			} catch (Exception e) {
			}
		}
		if (corpTag != null) {
			List<String> tag = List.of(corpTag.getTagId());
			try {
				wxCorpOps.markTag(externalUserId, followId, tag.toArray(new String[tag.size()]), null);
			} catch (Exception e) {
			}

		}
	}

	/**
	 * 客服备注手机号 跟进用户年付车票续费
	 */
	public void corpRenewFollowUser(String phone) {
		//是否是手机用户 或者 邮箱用户
		Set<Long> relationUserIds = getRelationUserIds(phone);
		if (CollUtil.isEmpty(relationUserIds)) {
			log.info("该备注手机号:{}暂无关联银河用户", phone);
			return;
		}
		List<RenewalView> list = beanSearcher.searchAll(RenewalView.class, MapUtils.builder()
				.field(RenewalView::getUserId, 0).op(Operator.NotEqual)
				.field(RenewalView::getUserId, relationUserIds).op(Operator.InList)
				.field(RenewalView::getYhsId, 0)
				//年付
				.field(RenewalView::getMonths, 12)
				.field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
				.onlySelect(RenewalView::getUserId, RenewalView::getExpiryTime, RenewalView::getSkuId)
				.build());
		Set<Long> couponIds = new HashSet<>();

		List<CouponUser> sendCouponUser = new ArrayList<>();

		list.forEach(renew->{
			Date expiryTime = renew.getExpiryTime();
			Long skuId = renew.getSkuId();
			Long userId = renew.getUserId();

			//一个月车票将过期
			if (expiryTime.before(DateUtil.offsetMonth(DateTime.now(), 1))) {
				//续费分类下
				//寻找对应续费的优惠券 发送
				Coupon coupon = couponMapper.getRenewCouponBySkuId(skuId, couponIds, userId);
				if (coupon != null) {
					CouponUser couponUser = new CouponUser();
					couponUser.setUserId(userId);
					couponUser.setCouponId(coupon.getId());
					sendCouponUser.add(couponUser);

					couponIds.add(coupon.getId());
				}
			}
		});
		//有几张过期的年付车票 发对应几张续费优惠券
		if (CollUtil.isNotEmpty(sendCouponUser)) {
			sendCouponUser.forEach(send -> {
				couponCommonService.sendCouponToUser(send.getUserId(), send.getCouponId(), null, null, null, CouponUser.Channel.wxCorp);
				//跟进用户续费
				groupsRelationExpiryRecordMapper.update(null, Wrappers.lambdaUpdate(GroupsRelationExpiryRecord.class)
						.set(GroupsRelationExpiryRecord::getIsFollow, true)
						.eq(GroupsRelationExpiryRecord::getUserId, send.getUserId())
						.eq(GroupsRelationExpiryRecord::getIsFollow, false));
			});
		}
	}

	private Set<Long> getRelationUserIds(String phone) {
		User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
				.eq(User::getLoginPhone, phone).last("limit 1")
				.select(User::getId));
		Set<Long> relationUserIds = new HashSet<>();
		if (user != null) {
			relationUserIds.add(user.getId());
		}
		UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
				.eq(UserBindDetail::getPhone, phone).last("limit 1"));
		if (userBindDetail != null) {
			Long userId = userBindDetail.getUserId();
			if (userId != null) {
				relationUserIds.add(userId);
			}
			Long emailUserId = userBindDetail.getEmailUserId();
			if (emailUserId != null) {
				relationUserIds.add(emailUserId);
			}
		}
		return relationUserIds;
	}


	private void saveAcqusitionCallback(String customer, CorpUser corpUser,CorpXmlMessage message) {
		String externalUserid = message.getExternalUserId() ;
		String userId = message.getUserId();
		//获客链接
		Long linkId = customerAcquisitionSaveClickId(customer, corpUser.getUnionid());
		CorpCustomerAcquisitionLink customerAcquisitionLink;
		if (linkId != null) {
			log.info("加粉链接linkid:{}", linkId);
			customerAcquisitionLink = corpCustomerAcquisitionLinkMapper.getByLinkPopularizeId(linkId);
		} else {
			//直接使用获客链接
			customerAcquisitionLink = corpCustomerAcquisitionLinkMapper.selectById(customer);
		}
		if (customerAcquisitionLink == null) {
			log.info("未找到对应获客链接:{}", customer);
			return;
		}
		corpUser.setCustomerAcquisitionLinkId(customerAcquisitionLink.getId());
		if (StringUtils.isNotBlank(customerAcquisitionLink.getTags())){
			try {
				log.info("处理获客链接客户标签,标签id:{}", customerAcquisitionLink.getTags());
				List<Long> tags = Jsons.parseList(customerAcquisitionLink.getTags(), Long.class);
				if (CollectionUtil.isEmpty(tags)) {
					log.info("获客链接id为：{},无标签处理", customerAcquisitionLink.getId());
				} else {
					// 处理标签
					List<CorpTag> tagList = corpTagMapper.selectBatchIds(tags);
					if (CollectionUtil.isNotEmpty(tagList)) {
						wxCorpOps.markTag(externalUserid, userId, tagList.stream().map(CorpTag::getTagId).toArray(String[]::new), null);
					}
				}
				//发送欢迎语
				Long msgId = customerAcquisitionLink.getMsgId();
				sendWelcomeMsg(msgId, message);
			} catch (Exception e) {
				log.error("处理获客链接解析标签id出错了,内容{},获客链接id: {}", customerAcquisitionLink.getTags(), customerAcquisitionLink.getId());
			}
		}
	}

	private Long customerAcquisitionSaveClickId(String state, String unionId){
		log.info("获客链接申请好友 state:{}",state);

		Long linkId = null;
		if (StringUtils.isNotBlank(state)){
			//根据state获取缓存数据.
			String json = redisService.getStr(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_CLICKID.getName(),state));

			if (StringUtils.isNotBlank(json)){
				JSONObject jsonObject = JSONUtil.parseObj(json);
				linkId = jsonObject.getLong("linkId");
				//1.2版本 clickId 为前版本内容，后续都用callback 可能存在clickId数据 兼容
				String callback = jsonObject.getStr("callback");

				CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectById(linkId);

				if (corpCustomerAcquisitionLinkPopularize != null) {
					//如果为加粉则直接回传
					if (corpCustomerAcquisitionLinkPopularize.getType() == 1) {
						//如果需要延后主动回传的做持久化.
						if(!corpCustomerAcquisitionLinkPopularize.getDelayedPost()){
							if (!corpCustomerAcquisitionLinkPopularize.getIsChat()) {
								postData(callback, corpCustomerAcquisitionLinkPopularize.getEvent());
							}
						}
					}else {
						//深度转化 前置加粉事件回传.
						if (StringUtils.isNotBlank(corpCustomerAcquisitionLinkPopularize.getAddEvent())) {
							//是否是监听客户发起会话事件 false
							if (!corpCustomerAcquisitionLinkPopularize.getIsChat()) {
								postData(callback, corpCustomerAcquisitionLinkPopularize.getAddEvent());
							}
						}

						//深度回传.
						redisService.set(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_UNIONID_CLICKID.getName(),unionId), json, corpCustomerAcquisitionLinkPopularize.getTime() * 60 * 60);
					}

					if(corpCustomerAcquisitionLinkPopularize.getDelayedPost()){
						CorpCustomerAcquistionCallback corpCustomerAcquistionCallback =
								corpCustomerAcquistionCallbackMapper.selectOne(Wrappers.lambdaQuery(CorpCustomerAcquistionCallback.class).eq(CorpCustomerAcquistionCallback::getCallback, callback).eq(CorpCustomerAcquistionCallback::getUnionId, unionId));
						if(corpCustomerAcquistionCallback == null){
							corpCustomerAcquistionCallback = new CorpCustomerAcquistionCallback();
						}
						corpCustomerAcquistionCallback.setCallback(callback);
						corpCustomerAcquistionCallback.setEvent(corpCustomerAcquisitionLinkPopularize.getEvent());
						corpCustomerAcquistionCallback.setUnionId(unionId);
						if(corpCustomerAcquistionCallback.getId() != null){
							corpCustomerAcquistionCallbackMapper.updateById(corpCustomerAcquistionCallback);
						}else {
							corpCustomerAcquistionCallbackMapper.insert(corpCustomerAcquistionCallback);
						}
					}

					//是否为对话 回传
					if (corpCustomerAcquisitionLinkPopularize.getIsChat()) {
						jsonObject.putOpt("event", corpCustomerAcquisitionLinkPopularize.getAddEvent());
						redisService.hset(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT.getName(), unionId, jsonObject.toString(), RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT.getTimeout());
					}
				}
			}
		}
		return linkId;
	}

	/**
	 *  加粉回传 目前 OE
	 */
	private void postData(String callback, String event) {
		try {
			orderDonPostService.post(OrderDonPost.Type.OE.getType(), callback, event);
		} catch (Exception e) {
			throw BusinessRuntimeException.getInstance("加粉回传出错. error:" + StringUtil.getErrorText(e));
		}
	}


	/**
	 * 发送欢迎语
	 * @param msgId 模板id
	 * @param message
	 */
	public CorpWelcomeTemplate sendWelcomeMsg(Long msgId, CorpXmlMessage message) {
		if (StrUtil.isEmpty(message.getWelcomeCode())) {
			return null;
		}
		CorpWelcomeTemplate corpWelcomeTemplate = corpWelcomeTemplateMapper.selectById(msgId);
		if (corpWelcomeTemplate != null) {
			String welcomeContent = corpWelcomeTemplate.getText();
			String attachmentsStr = corpWelcomeTemplate.getAttachmentsStr();
			//发送对应欢迎语
			if (StrUtil.isNotBlank(welcomeContent) || StrUtil.isNotBlank(attachmentsStr)) {
				THREAD_POOL.execute(() -> {
					senCorpWelcomeMsg(message, welcomeContent, attachmentsStr);
				});
			}
		}
		return corpWelcomeTemplate;
	}

	public void getCorpUserInfo(String corpId, String userId) {
		THREAD_POOL.execute(() -> {
			List<String> externalList = null;
			try {
				externalList = wxCorpOps.listExternalContacts(corpId, userId);
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (externalList.size() > 1000) {
				List<List<String>> lists = StringUtil.averageAssign(externalList, 5);
				for (List<String> list : lists) {
					THREAD_POOL.execute(() -> {
						for (String externalUserid : list) {
							try {
								log.info("同步客户数据 corpId:{},externalUserid:{}", corpId, externalUserid);
								//尝试添加客户
								CorpXmlMessage message = new CorpXmlMessage();
								message.setToUserName(corpId);
								message.setExternalUserId(externalUserid);
								addExternalContact(message, null);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					});
				}
			} else {
				for (String externalUserid : externalList) {
					try {
						//尝试添加客户
						CorpXmlMessage message = new CorpXmlMessage();
						message.setToUserName(corpId);
						message.setExternalUserId(externalUserid);
						addExternalContact(message, null);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
	}
}
