package com.cyksj.service.gzh.factory;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
import com.cyksj.common.util.Codec;
import com.cyksj.common.util.Jsons;
import com.cyksj.common.util.StringUtil;
import com.cyksj.config.WeChatConfig;
import com.cyksj.mapper.UserMapper;
import com.cyksj.mapper.WxAppMapper;
import com.cyksj.mapper.gzh.UserGzhRelationMapper;
import com.cyksj.mapper.manage.cps.UserDistributePopularizeMapper;
import com.cyksj.model.dto.GzhBodyDto;
import com.cyksj.model.dto.GzhUnionidUserinfo;
import com.cyksj.model.dto.MsgEvent;
import com.cyksj.model.entity.User;
import com.cyksj.model.entity.UserDistributePopularize;
import com.cyksj.model.entity.UserGzhRelation;
import com.cyksj.model.entity.WxApp;
import com.cyksj.redis.RedisService;
import com.cyksj.service.distribute.DistributeService;
import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
import com.cyksj.service.market.task.BindTaskService;
import com.cyksj.service.user.UserService;
import com.cyksj.service.wechat.WeChatService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.Optional;

/*
 *项目名: netflix
 *文件名: EventMsgService
 *创建者: JavaZou
 *创建时间:2023/1/13 18:16
 */
@Service("event")
@RequiredArgsConstructor
@Slf4j
public class EventMsgService implements GzhMsgService {
	private final UserMapper userMapper;

	private final UserGzhRelationMapper userGzhRelationMapper;

	private final WeChatService weChatService;

	private final WxAppMapper wxAppMapper;

	private final RedisService redisService;

	private final DistributeService distributeService;

	private final EquipmentDistributeService equipDistributeService;

	private final UserService userService;

	private final WeChatConfig weChatConfig;

	private final UserDistributePopularizeMapper distributePopularizeMapper;

	private final BindTaskService bindTaskService;

	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();

	@Override
	public String handleNotify(MsgEvent msgEvent) {
		try {
			if (msgEvent.getEvent() == MsgEvent.Event.subscribe) {
				String eventKey = msgEvent.getEventKey();
				if (StrUtil.isNotEmpty(eventKey) && eventKey.contains("qrscene")) {
					msgEvent.setEventKey(eventKey.substring(eventKey.indexOf("qrscene_") + 8));
				}
				if (!saveOrGetUser(msgEvent)) {
					return "";
				}
			} else if (msgEvent.getEvent() == MsgEvent.Event.unsubscribe) {
				UserGzhRelation userGzhRelation = userGzhRelationMapper.selectOne(Wrappers.lambdaQuery(UserGzhRelation.class)
						.eq(UserGzhRelation::getOpenId, msgEvent.getFromUserName()).last("limit 1"));
				if (userGzhRelation == null) {
					return "";
				}
				userGzhRelation.setIsSubscribe(false);
				userGzhRelationMapper.updateById(userGzhRelation);
			} else if (msgEvent.getEvent() == MsgEvent.Event.SCAN) {
				if (!saveOrGetUser(msgEvent)) {
					return "";
				}
			}
			return "";
		} catch (Exception e) {
			log.error("接收微信公众:{},报错:{}", msgEvent.getToUserName(), e == null ? "" : e.getMessage());
			return "";
		}
	}

	public Boolean saveOrGetUser(MsgEvent msgEvent) throws Exception {
		//扫描带参数二维码 场景值
		String sceneKey = msgEvent.getEventKey();

		String openId = msgEvent.getFromUserName();
		if (StrUtil.isEmpty(openId)) {
			return false;
		}
		//迁移公众号之后同步授权后信息
		//是否是迁移用户
//		WxSyncLog wxSyncLog = wxSyncLogMapper.selectOne(Wrappers.lambdaQuery(WxSyncLog.class)
//				.eq(WxSyncLog::getToAppid, weChatConfig.getAppid())
//				.eq(WxSyncLog::getNewOpenid, openId).last("limit 1"));

		WxApp wxApp = wxAppMapper.selectOne(Wrappers.lambdaQuery(WxApp.class)
				.eq(WxApp::getGzhOriginalId, msgEvent.getToUserName()).last("limit 1"));
		if (wxApp == null) {
			return false;
		}
		GzhUnionidUserinfo info = weChatService.getUserInfo2(weChatService.getAccessToken(wxApp.getAppId()), openId);
		User user = userService.getSyncUser(info.getOpenid(), info.getUnionid(), null);

		String state = redisService.getStr(RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getNameFormat(sceneKey));
		GzhBodyDto gzhDto = null;
		if (StrUtil.isNotEmpty(state)) {
			// 转跳参数
			String json = Codec.DoBase64.custom().setData(state).decodeAsText();
			if (StrUtil.isNotEmpty(json)) {
				try {
					gzhDto = Jsons.parseObject(json, GzhBodyDto.class);
				} catch (Exception e) {
				}
			}
		}
		Boolean isNewUser = false;
		if (user == null) {
			isNewUser = true;
			user = new User();
			user.setNickname(String.format("%s%s", Constant.DEFAULT_NAME, Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.MD5).setStringData(RandomUtil.randomString(10)).toHexString().substring(0, 6)))
					.setSex(info.getSex())
					.setCountry(info.getCountry())
					.setProvince(info.getProvince())
					.setCity(info.getCity())
					.setHeadimgurl(Constant.DEFAULT_HEAD_IMG);
			user.setOpenId(openId);
			user.setUnionid(info.getUnionid());
			//重复插入
			if (!redisService.setNx(RedisService.key.REPEAT_USER_KEY.getNameFormat(user.getUnionid()), user.getUnionid(), RedisService.key.REPEAT_USER_KEY.getTimeout())) {
				return false;
			}
			userMapper.insert(user);
			Long userId = user.getId();
			Long dsPopularizeId = null;
			if (gzhDto != null) {
				Long sharedId = gzhDto.getSharedId();
				String dsCode = gzhDto.getDsCode();
				if (StrUtil.isNotBlank(dsCode)) {
					dsCode = dsCode.trim();
					User sharedUser = userService.getOne(Wrappers.lambdaQuery(User.class)
							.eq(User::getShowId, dsCode).last("limit 1"));
					if (sharedUser != null) {
						sharedId = sharedUser.getId();
					} else {
						UserDistributePopularize distributePopularize = distributePopularizeMapper.selectOne(Wrappers.lambdaQuery(UserDistributePopularize.class)
								.eq(UserDistributePopularize::getCode, dsCode)
								.select(UserDistributePopularize::getUserId, UserDistributePopularize::getId).last("limit 1"));
						if (distributePopularize != null) {
							log.info("渠道sharedId:{}设置固定推广链接PC扫码用户分销", distributePopularize.getUserId());
							sharedId = distributePopularize.getUserId();
							dsPopularizeId = distributePopularize.getId();
						}
					}
				}
				if (sharedId != null) {
					distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId);
				}
				Long popularizeId = gzhDto.getPopularizeId();
				if (popularizeId != null) {
					userMapper.update(null, Wrappers.lambdaUpdate(User.class)
							.eq(User::getId, user.getId())
							.set(User::getPopularizeId, popularizeId));
					TASK_POOL.execute(() -> {
						userService.sendFixedCustomerCoupon(popularizeId, userId, info.getUnionid());
					});
				}
				userBind(user, sceneKey, gzhDto.getLoginPhone(), gzhDto.getLoginEmail());
			}

			saveGzhUserRelation(msgEvent, user.getId(), openId, info.getUnionid(), sceneKey, wxApp.getId());
		} else {
			//之前关注过
			if (user.getUnionid() == null || !user.getUnionid().equals(info.getUnionid())) {
				user.setUnionid(info.getUnionid());
				userMapper.updateById(user);
			}
			saveGzhUserRelation(msgEvent, user.getId(), openId, info.getUnionid(), sceneKey, wxApp.getId());
			if (gzhDto != null) {
				userBind(user, sceneKey, gzhDto.getLoginPhone(), gzhDto.getLoginEmail());
			}
		}
		//场景值扫描公众号二维码 登录
		if (StrUtil.isNotEmpty(sceneKey)) {
			redisService.set(RedisService.key.WX_GZH_QRCODE_LOGIN.getNameFormat(sceneKey), user.getId(), RedisService.key.WX_GZH_QRCODE_LOGIN.getTimeout());
		}
		if (gzhDto != null) {
			Long sharedId = gzhDto.getSharedId();
			Integer dsType = gzhDto.getDsType();
			//新旧用户都可实物分销
			if (dsType != null && dsType == 2) {
				equipDistributeService.saveDistributionInvitation(sharedId, isNewUser, user.getId());
			}
		}
		return true;
	}

	private void saveGzhUserRelation(MsgEvent msgEvent, Long userId, String openId, String unionid, String sceneKey, Long wxAppId) {
		UserGzhRelation userGzhRelation = userGzhRelationMapper.selectOne(Wrappers.lambdaQuery(UserGzhRelation.class)
				.eq(UserGzhRelation::getWxAppId, wxAppId)
				.eq(UserGzhRelation::getOpenId, msgEvent.getFromUserName()).last("limit 1"));
		userGzhRelation = Optional.ofNullable(userGzhRelation).orElseGet(() -> new UserGzhRelation());

		userGzhRelation.setUserId(userId);
		userGzhRelation.setWxAppId(wxAppId);
		userGzhRelation.setIsSubscribe(true);
		userGzhRelation.setEvent(msgEvent.getEvent());
		userGzhRelation.setOpenId(openId);
		userGzhRelation.setUnionid(unionid);
		if (StrUtil.isNotEmpty(msgEvent.getEventKey())) {
			userGzhRelation.setIsQrScene(true);
		}
		try {
			if (userGzhRelation.getId() == null) {
				//记录首次关注公众号的场景值
				userGzhRelation.setSceneKey(sceneKey);
				userGzhRelationMapper.insert(userGzhRelation);
				return;
			}
			userGzhRelationMapper.updateById(userGzhRelation);
		} catch (DuplicateKeyException e) {

		}
	}

	public void userBind(User user, String sceneKey, String loginPhone, String loginEmail) {
		if (StrUtil.isNotBlank(loginPhone)) {
			log.info("手机号phone:{}登录用户,微信扫描公众号二维码进行用户信息绑定", loginPhone);
			try {
				bindTaskService.bindPhone(user, loginPhone, null);
				redisService.set(RedisService.key.WX_GZH_QRCODE_BIND.getNameFormat(sceneKey), user.getId(), RedisService.key.WX_GZH_QRCODE_BIND.getTimeout());
			} catch (Exception e) {
				log.info(StringUtil.getErrorText(e));
			}
		}

		if (StrUtil.isNotBlank(loginEmail)) {
			log.info("邮箱email:{}登录用户,微信扫描公众号二维码进行用户信息绑定", loginEmail);
			try {
				bindTaskService.bindEmail(user, loginEmail, null);
				redisService.set(RedisService.key.WX_GZH_QRCODE_BIND.getNameFormat(sceneKey), user.getId(), RedisService.key.WX_GZH_QRCODE_BIND.getTimeout());
			} catch (Exception e) {
				log.info(StringUtil.getErrorText(e));
			}
		}
	}
}
