package com.qunzhixinxi.hnqz.admin.mq;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qunzhixinxi.hnqz.admin.api.constant.CacheConstants;
import com.qunzhixinxi.hnqz.admin.api.constant.MqConstants;
import com.qunzhixinxi.hnqz.admin.api.entity.SysDept;
import com.qunzhixinxi.hnqz.admin.api.entity.SysUser;
import com.qunzhixinxi.hnqz.admin.entity.SysUserSub;
import com.qunzhixinxi.hnqz.admin.entity.dto.UserSignCertDTO;
import com.qunzhixinxi.hnqz.admin.enums.DelEnum;
import com.qunzhixinxi.hnqz.admin.enums.GigCallBackStatus;
import com.qunzhixinxi.hnqz.admin.enums.GigTypeEnum;
import com.qunzhixinxi.hnqz.admin.enums.LockEnum;
import com.qunzhixinxi.hnqz.admin.enums.YeeCertStatus;
import com.qunzhixinxi.hnqz.admin.service.SysDeptService;
import com.qunzhixinxi.hnqz.admin.service.SysUserService;
import com.qunzhixinxi.hnqz.admin.service.SysUserSubService;
import com.qunzhixinxi.hnqz.common.rabbitmq.annotation.RabbitMqComponent;
import com.qunzhixinxi.hnqz.common.rabbitmq.core.BaseRabbiMqHandler;
import com.qunzhixinxi.hnqz.common.rabbitmq.listenter.MqListener;
import com.qunzhixinxi.hnqz.common.taxhelper.enums.TaxHelperCertStatus;
import com.rabbitmq.client.Channel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.handler.annotation.Header;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 接收用户签约认证的结果对列监听器
 */
@Slf4j
@AllArgsConstructor
@RabbitListener(queues = MqConstants.DIRECT_MODE_GIG_SIGN_CERT_RES_QUEUE)
@RabbitMqComponent(value = "gigSignCertReceiver")
public class GigSignCertReceiver extends BaseRabbiMqHandler<String> {

	private final SysDeptService sysDeptService;

	private final SysUserService sysUserService;

	private final SysUserSubService sysUserSubService;

	private final RedisTemplate redisTemplate;

	/**
	 * 税邦云成功code
	 */
	private static final String TAXHELPER_SUCCESS_CODE = "2000";

	/**
	 * 易联成功code
	 */
	private static final String YEE_SUCCESS_CODE = "200";

    @RabbitHandler
    public void onMessage(String jsonStr, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        super.onMessageAck(jsonStr, deliveryTag, channel, (MqListener<String>) (String result, Channel channel1) -> {

			log.info("直接队列：接收用户签约认证的结果，手动ACK，接收消息TAG:{},消息内容：{}", deliveryTag, result);

			Map<String, String> resMap = MapUtil.newHashMap(2);

			JSONObject jsonResult = JSONUtil.parseObj(result);
			String username = jsonResult.getStr("username");
			String entpriseCode = jsonResult.getStr("enterpriseCode");
			JSONObject subjectTypes = jsonResult.getJSONObject("subjectTypes");

			if (StrUtil.isBlank(username) || StrUtil.isBlank(entpriseCode) || subjectTypes.isEmpty()) {
				log.error("必传参数空！");
				resMap.put("key", String.format("%s_%s_%s", CacheConstants.USER_SIGN_CERT_RESPONSE_MQ_KEY, username, entpriseCode));
				resMap.put("res", JSONUtil.toJsonStr(subjectTypes));
				return resMap;
			}
				// 加redis锁 TODO
//				redisTemplate.opsForValue().setIfAbsent()

			List<SysDept> deptList = sysDeptService.list(Wrappers.<SysDept>lambdaQuery()
					.eq(SysDept::getTaxCode, entpriseCode)
					.eq(SysDept::getDelFlag, DelEnum.NOT_DEL.val())
					.orderByDesc(SysDept::getCreateTime));
			if (CollUtil.isNotEmpty(deptList)) {
				SysDept dept = deptList.get(0);
				SysUser user = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery()
						.eq(SysUser::getDeptId, dept.getDeptId())
						.eq(SysUser::getUsername, username)
						.eq(SysUser::getDelFlag, DelEnum.NOT_DEL.val())
						.eq(SysUser::getLockFlag, LockEnum.UN_LOCK.val()));
				if (user == null) {
					log.error("用户不存在！");
					return null;
				}
				// 根据不同渠道，更新对应的签约认证状态
				subjectTypes.forEach((s, o) -> {
					GigTypeEnum gigTypeEnum = Enum.valueOf(GigTypeEnum.class, s);
					JSONObject subjectResult = (JSONObject) o;

					switch (gigTypeEnum) {
						case TAX_HELPOR:
							taxHelperHandler(user, dept, subjectResult);
							// 本次结果存入redis
							redisTemplate.opsForValue().set(CacheConstants.USER_SIGN_CERT_RESPONSE_KEY + user.getUserId(),
									JSONUtil.toJsonStr(subjectTypes), 1, TimeUnit.MINUTES);
							break;
						case REN_LI_JIA:
							// TODO
							break;
						case OLADING:
							oladingHandler(user, dept, subjectResult);
							break;
						case YEE:
							yeeHandler(user, dept, subjectResult);
							// 本次结果存入redis
							redisTemplate.opsForValue().set(CacheConstants.USER_SIGN_CERT_RESPONSE_KEY + user.getUserId(),
									JSONUtil.toJsonStr(subjectTypes), 1, TimeUnit.MINUTES);
							break;
						default:
					}
				});

			}

			resMap.put("key", String.format("%s_%s_%s", CacheConstants.USER_SIGN_CERT_RESPONSE_MQ_KEY, username, entpriseCode));
			resMap.put("res", JSONUtil.toJsonStr(subjectTypes));

			return resMap;
        });
    }

	/**
	 * 税邦云数据处理
	 *
	 * @param user
	 * @param dept
	 * @param subjectResult
	 */
    private void taxHelperHandler(SysUser user, SysDept dept, JSONObject subjectResult) {
		String code = subjectResult.getStr("code");
		String certStatus = subjectResult.getStr("certStatus");
		LocalDateTime now = LocalDateTime.now();
		TaxHelperCertStatus taxHelperCertStatus = Enum.valueOf(TaxHelperCertStatus.class, certStatus);
		// 拼接更新条件
		LambdaUpdateWrapper<SysUserSub> updateWrapper = Wrappers.<SysUserSub>lambdaUpdate()
				.eq(SysUserSub::getUserId, user.getUserId())
				.eq(SysUserSub::getDeptId, dept.getDeptId())
				.set(SysUserSub::getCallbackStatus, GigCallBackStatus.RETURNED)
				.set(SysUserSub::getUpdateTime, now)
				.set(SysUserSub::getUpdateUser, 0)
				.set(SysUserSub::getCertRemark, JSONUtil.toJsonStr(subjectResult));
		updateWrapper.eq(SysUserSub::getGigType, GigTypeEnum.TAX_HELPOR);
		updateWrapper.set(SysUserSub::getCertStatus, taxHelperCertStatus.getCode());

		// 如果认证失败了， 置空身份证和合身视频
		if (TaxHelperCertStatus.UNCHECKED_BIND.equals(taxHelperCertStatus)){
			updateWrapper.set(SysUserSub::getCertVideo1Url, null);
			updateWrapper.set(SysUserSub::getCertVideo2Url, null);
			updateWrapper.set(SysUserSub::getIdCardFrontUrl, null);
			updateWrapper.set(SysUserSub::getIdCardBackUrl, null);
		}


		if (TAXHELPER_SUCCESS_CODE.equals(code)) {
			// 成功并且是换绑卡的情况，则更新银行卡号
			String cacheKeyPrefix = String.format("%s_%s_%s", CacheConstants.BIND_CARD_CONFIRM_NEW_BANK_CARD,
					user.getUserId(), GigTypeEnum.TAX_HELPOR.name());
			UserSignCertDTO userSignCertDTO = (UserSignCertDTO) redisTemplate.opsForValue().get(cacheKeyPrefix);
			if (userSignCertDTO != null) {
				if (StrUtil.isNotBlank(userSignCertDTO.getBankCardNumber())) {
					updateWrapper.set(SysUserSub::getBankCardNumber, userSignCertDTO.getBankCardNumber());
					updateWrapper.set(SysUserSub::getBankPhone, userSignCertDTO.getBankPhone());
					// 更新user表银行卡
					SysUser sysUser = new SysUser();
					sysUser.setUserId(user.getUserId());
					sysUser.setBankCardNumber(userSignCertDTO.getBankCardNumber());
					sysUser.setBankPhone(userSignCertDTO.getBankPhone());
					sysUserService.updateById(sysUser);
				}
				// redis删除银行卡号
				redisTemplate.delete(cacheKeyPrefix);
			}
		}
		sysUserSubService.update(updateWrapper);
	}

	/**
	 * 易联数据处理
	 *
	 * @param user
	 * @param dept
	 * @param subjectResult
	 */
	private void yeeHandler(SysUser user, SysDept dept, JSONObject subjectResult) {
		String code = subjectResult.getStr("code");
		String certStatus = subjectResult.getStr("certStatus");
		LocalDateTime now = LocalDateTime.now();
		YeeCertStatus yeeCertStatus = Enum.valueOf(YeeCertStatus.class, certStatus);

		// 拼接更新条件
		LambdaUpdateWrapper<SysUserSub> updateWrapper = Wrappers.<SysUserSub>lambdaUpdate()
				.eq(SysUserSub::getUserId, user.getUserId())
				.eq(SysUserSub::getDeptId, dept.getDeptId())
				.set(SysUserSub::getCallbackStatus, GigCallBackStatus.RETURNED)
				.set(SysUserSub::getUpdateTime, now)
				.set(SysUserSub::getUpdateUser, 0)
				.set(SysUserSub::getCertRemark, JSONUtil.toJsonStr(subjectResult));
		updateWrapper.eq(SysUserSub::getGigType, GigTypeEnum.YEE);
		updateWrapper.set(SysUserSub::getCertStatus, yeeCertStatus.getCode());
		if (YEE_SUCCESS_CODE.equals(code)) {
			// 成功并且是换绑卡的情况，则更新银行卡号
			String cacheKeyPrefix = String.format("%s_%s_%s", CacheConstants.BIND_CARD_CONFIRM_NEW_BANK_CARD,
					user.getUserId(), GigTypeEnum.YEE.name());
			UserSignCertDTO userSignCertDTO = (UserSignCertDTO) redisTemplate.opsForValue().get(cacheKeyPrefix);
			if (userSignCertDTO != null) {
				if (StrUtil.isNotBlank(userSignCertDTO.getBankCardNumber())) {
					updateWrapper.set(SysUserSub::getBankCardNumber, userSignCertDTO.getBankCardNumber());
				}
				// redis删除银行卡号
				redisTemplate.delete(cacheKeyPrefix);
			}
		}
		sysUserSubService.update(updateWrapper);
	}

	private void renlijiaHandler(SysUser user, SysDept dept, JSONObject subjectResult) {
		// TODO
	}

	/**
	 * 自由职家数据处理(这里只保存mq回调结果，实际业务处理放到阿拉丁直接回调接口里了)
	 *
	 * @param user
	 * @param dept
	 * @param subjectResult
	 */
	private void oladingHandler(SysUser user, SysDept dept, JSONObject subjectResult) {
		LocalDateTime now = LocalDateTime.now();
		// 拼接更新条件
		LambdaUpdateWrapper<SysUserSub> updateWrapper = Wrappers.<SysUserSub>lambdaUpdate()
				.eq(SysUserSub::getUserId, user.getUserId())
				.eq(SysUserSub::getDeptId, dept.getDeptId())
				.eq(SysUserSub::getGigType, GigTypeEnum.OLADING)
				.set(SysUserSub::getUpdateTime, now)
				.set(SysUserSub::getUpdateUser, 0)
				.set(SysUserSub::getCertRemark, JSONUtil.toJsonStr(subjectResult));
		sysUserSubService.update(updateWrapper);
	}

}