package com.qunzhixinxi.hnqz.admin.controller;

import cn.hutool.core.collection.CollUtil;
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.qunzhixinxi.hnqz.admin.api.constant.CacheConstants;
import com.qunzhixinxi.hnqz.admin.api.entity.SysUser;
import com.qunzhixinxi.hnqz.admin.entity.SysUserExtRecord;
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.GigTypeEnum;
import com.qunzhixinxi.hnqz.admin.enums.SubjectLocation;
import com.qunzhixinxi.hnqz.admin.service.SysUserExtRecordService;
import com.qunzhixinxi.hnqz.admin.service.SysUserService;
import com.qunzhixinxi.hnqz.admin.service.SysUserSubService;
import com.qunzhixinxi.hnqz.admin.service.gig.SysUserSignCertService;
import com.qunzhixinxi.hnqz.common.core.util.R;
import com.qunzhixinxi.hnqz.common.log.annotation.SysLog;
import com.qunzhixinxi.hnqz.common.security.service.HnqzUser;
import com.qunzhixinxi.hnqz.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户签约认证
 *
 * @author lixuesong
 * @date 2022年03月03日 14:34
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/user-sign-cert")
public class SysUserSignCertController {

	private final SysUserSignCertService sysUserSignCertService;

	private final SysUserService sysUserService;

	private final SysUserSubService sysUserSubService;

	private final RedisTemplate<String, Object> redisTemplate;

	/**
	 * 保存银行卡信息
	 *
	 * @param userSignCertDTO
	 * @return
	 */
	@SysLog("保存银行卡信息")
	@PostMapping("/save-bank-info")
	public R<?> saveBankInfo(@RequestBody UserSignCertDTO userSignCertDTO) {
		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (StrUtil.isNotBlank(userSignCertDTO.getBankPhone()) && !Validator.isMobile(userSignCertDTO.getBankPhone())) {
			return R.failed("银行预留手机号不正确");
		}
		if (StrUtil.length(userSignCertDTO.getBankCardNumber()) < 16 || StrUtil.length(userSignCertDTO.getBankCardNumber()) > 19) {
			return R.failed("银行卡号不正确");
		}
		SysUser sysUser = new SysUser();
		sysUser.setUserId(userSignCertDTO.getUserId());
		sysUser.setBankCardNumber(userSignCertDTO.getBankCardNumber());
		sysUser.setBankPhone(userSignCertDTO.getBankPhone());

		return R.ok(sysUserService.updateById(sysUser));
	}

	/**
	 * 保存用户基础信息
	 *
	 * @param userSignCertDTO
	 * @return
	 */
	@SysLog("保存用户基础信息")
	@PostMapping("/save-base-info")
	public R<?> saveBaseInfo(@RequestBody UserSignCertDTO userSignCertDTO) {
		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (userSignCertDTO.getSubjectLocation() == null) {
			return R.failed("税源地不能为空");
		}
		if (StrUtil.isNotBlank(userSignCertDTO.getBankPhone()) && !Validator.isMobile(userSignCertDTO.getBankPhone())) {
			return R.failed("银行预留手机号不正确");
		}
		if (StrUtil.length(userSignCertDTO.getBankCardNumber()) < 16 || StrUtil.length(userSignCertDTO.getBankCardNumber()) > 19) {
			return R.failed("银行卡号不正确");
		}
		if (StrUtil.isNotBlank(userSignCertDTO.getIdCardNumber()) && !Validator.isCitizenId(userSignCertDTO.getIdCardNumber())) {
			return R.failed("身份证号不正确");
		}

		sysUserSignCertService.saveBaseInfo(userSignCertDTO);

		return R.ok();
	}

	/**
	 * 签约/增员
	 *
	 * @param userSignCertDTO
	 * @return
	 */
	@SysLog("签约/增员")
	@PostMapping("/sign")
	public R<?> toSign(@RequestBody UserSignCertDTO userSignCertDTO) {
		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (userSignCertDTO.getSubjectLocation() == null) {
			return R.failed("税源地不能为空");
		}
		return sysUserSignCertService.toSign(userSignCertDTO);
	}

	/**
	 * 签协议
	 *
	 * @param userSignCertDTO
	 * @return
	 */
	@SysLog("签协议")
	@PostMapping("/sign-agreement")
	public R<?> signAgreement(@RequestBody UserSignCertDTO userSignCertDTO) {
		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (StrUtil.isBlank(userSignCertDTO.getAgreementUrl())) {
			return R.failed("协议不能为空");
		}
		if (userSignCertDTO.getSubjectLocation() == null) {
			return R.failed("税源地不能为空");
		}

		sysUserSignCertService.signAgreement(userSignCertDTO);

		return R.ok();
	}

	/**
	 * 人身验证
	 *
	 * @param userSignCertDTO
	 * @return
	 */
	@Deprecated
	@SysLog("人身验证")
	@PostMapping("/personal-identity-verification")
	public R<?> personalIdentityVerification(@RequestBody UserSignCertDTO userSignCertDTO) {
		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (userSignCertDTO.getSubjectLocation() == null) {
			return R.failed("税源地不能为空");
		}
		if (!StrUtil.isAllNotBlank(userSignCertDTO.getIdCardFrontUrl(), userSignCertDTO.getIdCardBackUrl(),
				userSignCertDTO.getCertVideo1Url(), userSignCertDTO.getCertVideo2Url())) {
			return R.failed("身份证或视频信息不能为空");
		}

		sysUserSignCertService.personalIdentityVerification(userSignCertDTO);

		return R.ok();
	}

	/**
	 * 批量发起用户签约认证
	 *
	 * @param userSignCertDTO
	 * @return R
	 */
	@SysLog("用户签约认证")
	@PostMapping("/batch-channel-cert")
	public R<?> batchChannelCert(@RequestBody UserSignCertDTO userSignCertDTO) {

		//1、验证令牌是否合法【令牌的对比和删除必须保证原子性】
		HnqzUser finaAdmin = SecurityUtils.getUser();
		final String REDIS_DEL_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
		Long execute = redisTemplate.execute(new DefaultRedisScript<>(REDIS_DEL_SCRIPT, Long.class),
				Collections.singletonList(String.format("%d:batch_channel_cert:%d:token", finaAdmin.getTenantId(), finaAdmin.getId())), userSignCertDTO.getToken());
		// 通过EVAL脚本原子验证令牌和删除令牌
		boolean oops = (execute != null && execute == 0);

		// 令牌验证失败
		if (oops) {
			log.error(String.format("提交 TOKEN 不正确：%s", userSignCertDTO.getToken()));
			return R.failed("提交 TOKEN 不正确，请刷新页面重试");
		}

		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (userSignCertDTO.getSubjectLocation() == null) {
			return R.failed("税源地不能为空");
		}

		SysUser sysUser = sysUserService.getById(userSignCertDTO.getUserId());
		if (sysUser == null) {
			return R.failed("用户不存在");
		}
		SysUserSub userSub = sysUserSubService.getOne(Wrappers.<SysUserSub>lambdaQuery()
				.eq(SysUserSub::getDeptId, sysUser.getDeptId())
				.eq(SysUserSub::getUserId, sysUser.getUserId())
				.eq(SysUserSub::getSubjectLocation, userSignCertDTO.getSubjectLocation()));
		if (userSub == null) {
			return R.failed("用户userSub不存在");
		}
		if (!userSignCertDTO.getSubjectLocation().equals(SubjectLocation.REN_LI_JIA)) {
			if (StrUtil.isBlank(userSub.getAgreementUrl())) {
				return R.failed("协议不能为空");
			}
//			if (!StrUtil.isAllNotBlank(userSub.getIdCardBackUrl(), userSub.getIdCardFrontUrl(),
//					userSub.getCertVideo1Url(), userSub.getCertVideo2Url())) {
//				return R.failed("身份证或视频信息不能为空");
//			}
		}

		// 过滤出阿拉钉的渠道
		Collection<SubjectLocation> oladingList =
				CollUtil.intersection(CollUtil.toList(userSignCertDTO.getSubjectLocation()), SubjectLocation.getByGigType(GigTypeEnum.OLADING));
		if (!oladingList.isEmpty()) {
			List<SubjectLocation> sortedList = oladingList.stream()
					.sorted(Comparator.comparing(SubjectLocation::getSort))
					.collect(Collectors.toList());
			// 选择的渠道的阿拉钉的部分记录到redis
			String redisKey = CacheConstants.OLADING_CERT_SEND_CHANNEL + userSignCertDTO.getUserId();
			redisTemplate.opsForValue().set(redisKey, JSONUtil.toJsonStr(sortedList), 24, TimeUnit.HOURS);
		}

		sysUserSignCertService.batchChannelCert(userSignCertDTO);

		return R.ok();
	}

	/**
	 * 税邦云发送绑卡验证码
	 *
	 * @param userSignCertDTO
	 * @return
	 */
	@SysLog("税邦云发送绑卡验证码")
	@PostMapping("/bind-card-verification")
	public R<?> bindCardVerification(@RequestBody UserSignCertDTO userSignCertDTO) {
		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (StrUtil.isBlank(userSignCertDTO.getBankPhone())) {
			return R.failed("银行预留手机号不能为空");
		}
		if (StrUtil.isBlank(userSignCertDTO.getBankCardNumber())) {
			return R.failed("银行卡号不能为空");
		}
		return sysUserSignCertService.bindCardVerification(userSignCertDTO);
	}

	/**
	 * 税邦云绑卡确认
	 *
	 * @param userSignCertDTO
	 * @return
	 */
	@SysLog("税邦云绑卡确认")
	@PostMapping("/bind-card-confirm")
	public R<?> bindCardConfirm(@RequestBody UserSignCertDTO userSignCertDTO) {
		if (userSignCertDTO.getUserId() == null) {
			return R.failed("userId不能为空");
		}
		if (StrUtil.isBlank(userSignCertDTO.getBankPhone())) {
			return R.failed("银行预留手机号不能为空");
		}
		if (StrUtil.isBlank(userSignCertDTO.getBankCardNumber())) {
			return R.failed("银行卡号不能为空");
		}
		return sysUserSignCertService.bindCardConfirm(userSignCertDTO);
	}

	/**
	 * 查询签约认证结果
	 *
	 * @param userId
	 * @return
	 */
	@GetMapping("/sign-cert-result/{userId}")
	public R<?> getSignCertResult(@PathVariable("userId") Integer userId) {
		String key = CacheConstants.USER_SIGN_CERT_RESPONSE_KEY + userId;
		String response = (String) redisTemplate.opsForValue().get(key);

		log.info("查询签约认证结果:key={}, value={}", key,  response);

		if (response == null) {
			return R.failed("没有结果");
		}
		JSONObject jsonResult = JSONUtil.parseObj(response, true);
		return R.ok(jsonResult);
	}
}
