package com.qunzhixinxi.hnqz.admin.service.gig.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
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.dto.OladingCommonRequest;
import com.qunzhixinxi.hnqz.admin.entity.SysUserSub;
import com.qunzhixinxi.hnqz.admin.entity.WmScorePackage;
import com.qunzhixinxi.hnqz.admin.entity.WmScorePackageSettleNote;
import com.qunzhixinxi.hnqz.admin.entity.dto.UserSignCertDTO;
import com.qunzhixinxi.hnqz.admin.enums.GigCallBackStatus;
import com.qunzhixinxi.hnqz.admin.enums.GigTypeEnum;
import com.qunzhixinxi.hnqz.admin.enums.OladingCertStatus;
import com.qunzhixinxi.hnqz.admin.enums.SubjectLocation;
import com.qunzhixinxi.hnqz.admin.service.SysUserSubService;
import com.qunzhixinxi.hnqz.admin.service.WmScorePackageService;
import com.qunzhixinxi.hnqz.admin.service.WmScorePackageSettleNoteService;
import com.qunzhixinxi.hnqz.admin.service.gig.GigThirdApiService;
import com.qunzhixinxi.hnqz.admin.service.gig.SysUserSignCertService;
import com.qunzhixinxi.hnqz.common.core.exception.ValidateCodeException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author lixuesong
 * @date 2022年04月17日 11:55
 */
@Slf4j
@Service
@AllArgsConstructor
public class GigThirdApiServiceImpl implements GigThirdApiService {

	private final RedisTemplate redisTemplate;
	private final SysUserSubService sysUserSubService;
	private final SysUserSignCertService sysUserSignCertService;
	private final WmScorePackageSettleNoteService scorePackageSettleNoteService;
	private final WmScorePackageService scorePackageService;

	/**
	 * 自由职家回调业务处理
	 *
	 * @param requestId
	 * @param req
	 */
	@Override
	public void oladingNotify(String requestId, OladingCommonRequest.Req req) {
		// 请求接口名称
		String interfaceName = req.getName();
		// 请求data
		Map<String, Object> data = req.getData();
		// 接口名称enum
		OladingCommonRequest.InterfaceName interfaceNameEnum = Enum.valueOf(OladingCommonRequest.InterfaceName.class, interfaceName);
		// 状态
		String status = "CREATE_ORDER_DETAIL".equals(interfaceName) ? (String) data.get("remit_status")  : (String) data.get("status");
		// 截取前缀部分，从而获取到系统内部的requestId
		String requestIdPrefix = StrUtil.split(requestId, StrUtil.UNDERLINE).get(0);

		if (StrUtil.isBlank(status)) {
			throw new ValidateCodeException("status为空");
		}

		switch (interfaceNameEnum) {
			case SIGN_UP:
				// 签约
				OladingCommonRequest.SignUpStatus signUpCertStatus = Enum.valueOf(OladingCommonRequest.SignUpStatus.class, status);
				this.oladingSignUp(requestIdPrefix, signUpCertStatus, req);
				break;
			case UPLOAD_ID_CARD_IMAGE:
				// 证照上传
				OladingCommonRequest.UploadIdCardImageStatus uploadIdCertStatus =
						Enum.valueOf(OladingCommonRequest.UploadIdCardImageStatus.class, status);
				this.oladingUploadIdCardImage(requestIdPrefix, uploadIdCertStatus, req);
				break;
			case UPLOAD_TAXPAYER_AGREEMENT:
				// 上传企业纳税人协议
				OladingCommonRequest.UploadTaxpayerAgreementStatus agreementStatus =
						Enum.valueOf(OladingCommonRequest.UploadTaxpayerAgreementStatus.class, status);
				this.oladingUploadTaxpayerAgreement(requestIdPrefix, agreementStatus, req);
				break;
			case CREATE_ORDER_V2:
				// 创建代付订单结果
				this.oladingCreateOrderV2(requestId, Enum.valueOf(OladingCommonRequest.CreateOrderV2Status.class, status), data);
				break;
			case CREATE_ORDER_DETAIL:
				this.oladingCreateOrderDetail(requestId, Enum.valueOf(OladingCommonRequest.RemitStatusStatus.class, status));
				// 打款订单
				break;
			default:
				throw new ValidateCodeException("回调方法处理不存在");
		}
	}

	/**
	 * 创建代付订单回调处理
	 *
	 * @param requestId 流水号
	 * @param status    受理状态
	 */
	@Transactional(rollbackFor = Exception.class)
	public void oladingCreateOrderDetail(String requestId, OladingCommonRequest.RemitStatusStatus status) {

		int yaoyiStatus;
		switch (status){
			case REMIT:
				yaoyiStatus = 1;
				break;
			case FAIL:
				yaoyiStatus = 2;
				break;
			default:
				log.error("订单状态错误：{}", status);
				return;
		}

		List<WmScorePackageSettleNote> noteList = scorePackageSettleNoteService.list(Wrappers.<WmScorePackageSettleNote>lambdaQuery().eq(WmScorePackageSettleNote::getStreamId, requestId));

		if (CollectionUtils.isNotEmpty(noteList)) {

			log.warn("阿拉钉内部打款：{}", requestId);

			List<WmScorePackageSettleNote> updateList = noteList.stream().map(note -> {
				WmScorePackageSettleNote updateEntity = new WmScorePackageSettleNote();
				updateEntity.setId(note.getId());
				updateEntity.setSettleNoteStatus(yaoyiStatus);
				if (yaoyiStatus == 1){
					updateEntity.setNotifyTime(LocalDateTime.now());
				}
				updateEntity.setUpdateTime(LocalDateTime.now());
				return updateEntity;
			}).collect(Collectors.toList());

			scorePackageSettleNoteService.updateBatchById(updateList);

			WmScorePackageSettleNote tmp = noteList.get(0);
			WmScorePackage scorePackage = scorePackageService.getById(tmp.getPackageId());

			// 遥领不修改
			if (!"1611890566".equals(scorePackage.getSendPackageDeptId())) {
				// 更新积分包状态
				log.info("更新积分包状态:{}", tmp);
				WmScorePackage wmScorePackage = new WmScorePackage();
				wmScorePackage.setId(tmp.getPackageId());
				wmScorePackage.setSettleStatus(yaoyiStatus);
				wmScorePackage.setUpdateTime(LocalDateTime.now());
				scorePackageService.updateById(wmScorePackage);
			}
			redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + tmp.getId());
		}
	}

	/**
	 * 创建代付订单回调处理
	 *
	 * @param requestId 流水号
	 * @param status    受理状态
	 */
	@SuppressWarnings("unchecked")
	@Transactional(rollbackFor = Exception.class)
	public void oladingCreateOrderV2(String requestId, OladingCommonRequest.CreateOrderV2Status status, Map<String, Object> data) {

		boolean accept = OladingCommonRequest.CreateOrderV2Status.ACCEPT.equals(status);

		int yaoyiStatus;
		if (!accept) {
			yaoyiStatus = 2;
		} else {
			List<Map<String, Object>> orderList = (List<Map<String, Object>>) data.get("remit_order_list");
			Map<String, Object> o = orderList.get(0);
			String remitStatue = (String) o.get("remit_status");
			OladingCommonRequest.RemitStatusStatus remitStatusStatus = Enum.valueOf(OladingCommonRequest.RemitStatusStatus.class, remitStatue);
			switch (remitStatusStatus){
				case REMIT:
					yaoyiStatus = 1;
					break;
				case FAIL:
					yaoyiStatus = 2;
					break;
				default:
					return;
			}
		}


		List<WmScorePackageSettleNote> noteList = scorePackageSettleNoteService.list(Wrappers.<WmScorePackageSettleNote>lambdaQuery().eq(WmScorePackageSettleNote::getStreamId, requestId));

		if (CollectionUtils.isNotEmpty(noteList)) {

			log.warn("阿拉丁创建代付订单：{}", requestId);

			List<WmScorePackageSettleNote> updateList = noteList.stream().map(note -> {
				WmScorePackageSettleNote updateEntity = new WmScorePackageSettleNote();
				updateEntity.setId(note.getId());
				updateEntity.setSettleNoteStatus(yaoyiStatus);
				if (yaoyiStatus == 1){
					updateEntity.setNotifyTime(LocalDateTime.now());
				}
				updateEntity.setUpdateTime(LocalDateTime.now());
				return updateEntity;
			}).collect(Collectors.toList());

			scorePackageSettleNoteService.updateBatchById(updateList);

			WmScorePackageSettleNote tmp = noteList.get(0);
			WmScorePackage scorePackage = scorePackageService.getById(tmp.getPackageId());

			// 遥领不修改
			if (!"1611890566".equals(scorePackage.getSendPackageDeptId())) {
				// 更新积分包状态
				log.info("更新积分包状态:{}", tmp);
				WmScorePackage wmScorePackage = new WmScorePackage();
				wmScorePackage.setId(tmp.getPackageId());
				wmScorePackage.setSettleStatus(yaoyiStatus);
				wmScorePackage.setUpdateTime(LocalDateTime.now());
				scorePackageService.updateById(wmScorePackage);
			}

			redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + tmp.getId());
		}
	}


	/**
	 * 自由职家签约结果回调
	 *
	 * @param requestId
	 * @param signUpCertStatus
	 * @param req
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void oladingSignUp(String requestId, OladingCommonRequest.SignUpStatus signUpCertStatus, OladingCommonRequest.Req req) {
		// 先查询requestId是否存在
		SysUserSub userSub = sysUserSubService.getOne(Wrappers.<SysUserSub>lambdaQuery()
				.eq(SysUserSub::getRequestId, requestId));
		if (userSub == null) {
			log.error("{} requestId不存在", requestId);
			throw new ValidateCodeException("requestId不存在");
		}

		Map<String, String> subMap = new HashMap<>();
		SysUserSub updateUserSub = new SysUserSub();
		if (OladingCommonRequest.SignUpStatus.SIGN.equals(signUpCertStatus)) {
			subMap.put("certStatus", OladingCertStatus.SIGNED.name());
			updateUserSub.setCertStatus(Integer.valueOf(OladingCertStatus.SIGNED.getCode()));
		} else {
			subMap.put("certStatus", OladingCertStatus.UN_SIGNED.name());
			updateUserSub.setCertStatus(Integer.valueOf(OladingCertStatus.UN_SIGNED.getCode()));
		}
		updateUserSub.setId(userSub.getId());
		updateUserSub.setUpdateTime(LocalDateTime.now());
		updateUserSub.setUpdateUser(0);
		updateUserSub.setCallbackStatus(GigCallBackStatus.RETURNED);
		if ("0".equals(req.getCode())) {
			updateUserSub.setFailReason(String.valueOf(req.getData().get("failReason")));
		} else {
			updateUserSub.setFailReason(req.getMessage());
		}
		// 更新状态
		sysUserSubService.updateById(updateUserSub);

		// 结果放到redis
		String key = CacheConstants.USER_SIGN_CERT_RESPONSE_KEY + userSub.getUserId();
		Map<String, Object> result = MapUtil.newHashMap(2);
		result.put(userSub.getGigType().name(), new HashMap<>(subMap));

		// 查询redis是否有同时发起的标记，查询出对应的状态放到redis
		String oladingRedisKey = CacheConstants.OLADING_CERT_SEND_CHANNEL + userSub.getUserId();
		String subjectLocationJson = (String) redisTemplate.opsForValue().get(oladingRedisKey);
		if (JSONUtil.isJsonArray(subjectLocationJson)) {
			JSONArray subjectLocationArray = JSONUtil.parseArray(subjectLocationJson);
			List<SubjectLocation> subjectLocationList = subjectLocationArray.stream()
					.map(o -> Enum.valueOf(SubjectLocation.class, String.valueOf(o)))
					.collect(Collectors.toList());
			List<SysUserSub> subList = sysUserSubService.list(Wrappers.<SysUserSub>lambdaQuery()
					.eq(SysUserSub::getUserId, userSub.getUserId())
					.eq(SysUserSub::getDeptId, userSub.getDeptId())
					.in(SysUserSub::getSubjectLocation, subjectLocationList));
			Map<String, Map<String, String>> dbResultMap = subList.stream()
					.collect(Collectors.toMap(sysUserSub -> sysUserSub.getSubjectLocation().name(),
							sysUserSub -> MapUtil.builder("certStatus",
									OladingCertStatus.resolve(String.valueOf(sysUserSub.getCertStatus())).name()).build()));
			result.putAll(dbResultMap);
		}

		log.info("缓存认证结果到redis：{}", JSONUtil.toJsonStr(result));
		redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(result), 1, TimeUnit.MINUTES);

		// 如果成功，则发送证照上传MQ
//		if (OladingCommonRequest.SignUpStatus.SIGN.equals(signUpCertStatus)) {
//			log.info("=============================发送证照上传MQ==================================");
//			UserSignCertDTO userSignCertDTO = new UserSignCertDTO();
//			userSignCertDTO.setUserId(userSub.getUserId());
//			userSignCertDTO.setGigTypeList(Collections.singletonList(userSub.getGigType()));
//			sysUserSignCertService.batchChannelCert(userSignCertDTO);
//		}
	}

	/**
	 * 自由职家证照上传结果回调
	 *
	 * @param requestId
	 * @param uploadIdCertStatus
	 */
	@Override
	public void oladingUploadIdCardImage(String requestId, OladingCommonRequest.UploadIdCardImageStatus uploadIdCertStatus, OladingCommonRequest.Req req) {
		// 先查询requestId是否存在
		SysUserSub userSub = sysUserSubService.getOne(Wrappers.<SysUserSub>lambdaQuery()
				.eq(SysUserSub::getRequestId, requestId));
		if (userSub == null) {
			log.error("{} requestId不存在", requestId);
			throw new ValidateCodeException("requestId不存在");
		}

		Map<String, String> subMap = new HashMap<>();
		LambdaUpdateWrapper<SysUserSub> updateUserSubWrapper = Wrappers.lambdaUpdate();
		updateUserSubWrapper.eq(SysUserSub::getId, userSub.getId());
		if (OladingCommonRequest.UploadIdCardImageStatus.IDENTIFY_SUCCESS.equals(uploadIdCertStatus)) {
			subMap.put("certStatus", OladingCertStatus.SIGNED.name());
			updateUserSubWrapper.set(SysUserSub::getCertStatus, Integer.valueOf(OladingCertStatus.SIGNED.getCode()));
		} else {
			subMap.put("certStatus", OladingCertStatus.SIGNED.name());
			updateUserSubWrapper.set(SysUserSub::getCertStatus, Integer.valueOf(OladingCertStatus.SIGNED.getCode()));
			updateUserSubWrapper.set(SysUserSub::getIdCardFrontUrl, null);
			updateUserSubWrapper.set(SysUserSub::getIdCardBackUrl, null);
		}
		updateUserSubWrapper.set(SysUserSub::getUpdateTime, LocalDateTime.now());
		updateUserSubWrapper.set(SysUserSub::getUpdateUser, 0);
		updateUserSubWrapper.set(SysUserSub::getCallbackStatus, GigCallBackStatus.RETURNED);
		if ("0".equals(req.getCode())) {
			updateUserSubWrapper.set(SysUserSub::getFailReason, String.valueOf(req.getData().get("failReason")));
		} else {
			updateUserSubWrapper.set(SysUserSub::getFailReason, req.getMessage());
		}
		// 更新状态
		sysUserSubService.update(updateUserSubWrapper);

		// 结果放到redis
		String key = CacheConstants.USER_SIGN_CERT_RESPONSE_KEY + userSub.getUserId();
		Map<String, Object> result = MapUtil.newHashMap(2);
		result.put(userSub.getGigType().name(), new HashMap<>(subMap));

		// 查询redis是否有同时发起的标记，查询出对应的状态放到redis
		String oladingRedisKey = CacheConstants.OLADING_CERT_SEND_CHANNEL + userSub.getUserId();
		String subjectLocationJson = (String) redisTemplate.opsForValue().get(oladingRedisKey);
		if (JSONUtil.isJsonArray(subjectLocationJson)) {
			JSONArray subjectLocationArray = JSONUtil.parseArray(subjectLocationJson);
			List<SubjectLocation> subjectLocationList = subjectLocationArray.stream()
					.map(o -> Enum.valueOf(SubjectLocation.class, String.valueOf(o)))
					.collect(Collectors.toList());
			List<SysUserSub> subList = sysUserSubService.list(Wrappers.<SysUserSub>lambdaQuery()
					.eq(SysUserSub::getUserId, userSub.getUserId())
					.eq(SysUserSub::getDeptId, userSub.getDeptId())
					.in(SysUserSub::getSubjectLocation, subjectLocationList));
			Map<String, Map<String, String>> dbResultMap = subList.stream()
					.collect(Collectors.toMap(sysUserSub -> sysUserSub.getSubjectLocation().name(),
							sysUserSub -> MapUtil.builder("certStatus",
									OladingCertStatus.resolve(String.valueOf(sysUserSub.getCertStatus())).name()).build()));
			result.putAll(dbResultMap);
		}

		log.info("缓存认证结果到redis：{}", JSONUtil.toJsonStr(result));
		redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(result), 1, TimeUnit.MINUTES);


		// 如果成功，则发送协议上传MQ
		if (OladingCommonRequest.UploadIdCardImageStatus.IDENTIFY_SUCCESS.equals(uploadIdCertStatus)) {
			log.info("=============================发送协议上传MQ==================================");
			UserSignCertDTO userSignCertDTO = new UserSignCertDTO();
			userSignCertDTO.setUserId(userSub.getUserId());
			userSignCertDTO.setSubjectLocation(userSub.getSubjectLocation());
			sysUserSignCertService.batchChannelCert(userSignCertDTO);
		}
	}

	/**
	 * 自由职家上传企业纳税人协议回调
	 *
	 * @param requestId
	 * @param agreementStatus
	 */
	@Override
	public void oladingUploadTaxpayerAgreement(String requestId, OladingCommonRequest.UploadTaxpayerAgreementStatus agreementStatus, OladingCommonRequest.Req req) {
		// 先查询requestId是否存在
		SysUserSub userSub = sysUserSubService.getOne(Wrappers.<SysUserSub>lambdaQuery()
				.eq(SysUserSub::getRequestId, requestId));
		if (userSub == null) {
			log.error("{} requestId不存在", requestId);
			throw new ValidateCodeException("requestId不存在");
		}

		Map<String, String> subMap = new HashMap<>();
		LambdaUpdateWrapper<SysUserSub> updateUserSubWrapper = Wrappers.lambdaUpdate();
		updateUserSubWrapper.eq(SysUserSub::getId, userSub.getId());
		if (OladingCommonRequest.UploadTaxpayerAgreementStatus.SUCCESS.equals(agreementStatus)) {
			subMap.put("certStatus", OladingCertStatus.CERT.name());
			updateUserSubWrapper.set(SysUserSub::getCertStatus, Integer.valueOf(OladingCertStatus.CERT.getCode()));
		} else {
			subMap.put("certStatus", OladingCertStatus.SIGNED.name());
			updateUserSubWrapper.set(SysUserSub::getCertStatus, Integer.valueOf(OladingCertStatus.SIGNED.getCode()));
		}
		updateUserSubWrapper.set(SysUserSub::getUpdateTime, LocalDateTime.now());
		updateUserSubWrapper.set(SysUserSub::getUpdateUser, 0);
		updateUserSubWrapper.set(SysUserSub::getCallbackStatus, GigCallBackStatus.RETURNED);
		if ("0".equals(req.getCode())) {
			updateUserSubWrapper.set(SysUserSub::getFailReason, String.valueOf(req.getData().get("failReason")));
		} else {
			updateUserSubWrapper.set(SysUserSub::getFailReason, req.getMessage());
		}
		// 更新状态
		sysUserSubService.update(updateUserSubWrapper);

		// 结果放到redis
		String key = CacheConstants.USER_SIGN_CERT_RESPONSE_KEY + userSub.getUserId();
		Map<String, Object> result = MapUtil.newHashMap(2);
		result.put(userSub.getGigType().name(), new HashMap<>(subMap));

		// 查询redis是否有同时发起的标记，查询出对应的状态放到redis
		String oladingRedisKey = CacheConstants.OLADING_CERT_SEND_CHANNEL + userSub.getUserId();
		String subjectLocationJson = (String) redisTemplate.opsForValue().get(oladingRedisKey);
		if (JSONUtil.isJsonArray(subjectLocationJson)) {
			JSONArray subjectLocationArray = JSONUtil.parseArray(subjectLocationJson);
			List<SubjectLocation> subjectLocationList = subjectLocationArray.stream()
					.map(o -> Enum.valueOf(SubjectLocation.class, String.valueOf(o)))
					.collect(Collectors.toList());
			List<SysUserSub> subList = sysUserSubService.list(Wrappers.<SysUserSub>lambdaQuery()
					.eq(SysUserSub::getUserId, userSub.getUserId())
					.eq(SysUserSub::getDeptId, userSub.getDeptId())
					.in(SysUserSub::getSubjectLocation, subjectLocationList));
			Map<String, Map<String, String>> dbResultMap = subList.stream()
					.collect(Collectors.toMap(sysUserSub -> sysUserSub.getSubjectLocation().name(),
							sysUserSub -> MapUtil.builder("certStatus",
									OladingCertStatus.resolve(String.valueOf(sysUserSub.getCertStatus())).name()).build()));
			result.putAll(dbResultMap);
		}

		log.info("缓存认证结果到redis：{}", JSONUtil.toJsonStr(result));
		redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(result), 1, TimeUnit.MINUTES);

		if (OladingCommonRequest.UploadTaxpayerAgreementStatus.SUCCESS.equals(agreementStatus)) {
			// 如果成功，则发送核身视频上传MQ
			log.info("=============================发送核身视频上传MQ==================================");
			UserSignCertDTO userSignCertDTO = new UserSignCertDTO();
			userSignCertDTO.setUserId(userSub.getUserId());
			userSignCertDTO.setSubjectLocation(userSub.getSubjectLocation());
			userSignCertDTO.setUploadFaceID(true);
			sysUserSignCertService.batchChannelCert(userSignCertDTO);
		}
	}
}
