package com.yifu.cloud.plus.v1.check.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.check.entity.TCheckApiNum;
import com.yifu.cloud.plus.v1.check.entity.TCheckIdCard;
import com.yifu.cloud.plus.v1.check.entity.TCheckLock;
import com.yifu.cloud.plus.v1.check.mapper.TCheckIdCardMapper;
import com.yifu.cloud.plus.v1.check.service.TCanCheckService;
import com.yifu.cloud.plus.v1.check.service.TCheckApiNumService;
import com.yifu.cloud.plus.v1.check.service.TCheckIdCardService;
import com.yifu.cloud.plus.v1.check.service.TCheckLockService;
import com.yifu.cloud.plus.v1.check.utils.ChecksUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 身份证实名校验自留库
 *
 * @author hgw
 * @date 2022-05-11 16:12:18
 */
@AllArgsConstructor
@Service
public class TCheckIdCardServiceImpl extends ServiceImpl<TCheckIdCardMapper, TCheckIdCard> implements TCheckIdCardService {

     private final TCheckLockService tCheckLockService;
     private final TCheckApiNumService tCheckApiNumService;

	 private final TCanCheckService canCheckService;

     /**
      * 身份证实名校验自留库简单分页查询
      *
      * @param tCheckIdCard 身份证实名校验自留库
      * @return
      */
     @Override
     public IPage<TCheckIdCard> getTCheckIdCardPage(Page<TCheckIdCard> page, TCheckIdCard tCheckIdCard) {
          return baseMapper.getTCheckIdCardPage(page, tCheckIdCard);
     }

     @Override
     public List<TCheckIdCard> getAllList(TCheckIdCard tCheckIdCard) {
          return baseMapper.getAllList(tCheckIdCard);
     }

     @Override
     public Map<String, TCheckIdCard> getAllMap(TCheckIdCard tCheckIdCard) {
          List<TCheckIdCard> list = baseMapper.getAllList(tCheckIdCard);
          Map<String, TCheckIdCard> returnMap = new HashMap<>();
          if (list != null && !list.isEmpty()) {
               for (TCheckIdCard c : list) {
                    returnMap.put(c.getIdCard() + CommonConstants.DOWN_LINE_STRING + c.getName(), c);
               }
          }
          return returnMap;
     }

     /**
      * @param checkList
      * @Description: 校验
      * @Author: hgw
      * @Date: 2022/5/12 15:47
      * @return: com.yifu.cloud.v1.common.core.util.R<java.util.List < com.yifu.cloud.v1.checks.api.entity.TCheckIdCard>>
      **/
     @Override
     public synchronized R<List<TCheckIdCard>> checkIdCard(List<TCheckIdCard> checkList) {
          YifuUser user = SecurityUtils.getUser();
          if (user == null || Common.isEmpty(user.getId())) {
               return R.failed("请登录！");
          }
          List<TCheckLock> lockList = tCheckLockService.getAllList();
          if (lockList != null && !lockList.isEmpty()) {
               return R.failed("当前有用户在导入中，请稍后！或联系管理员处理表TCheckLock数据和重启校验服务");
          }
          String nowMonth = DateUtil.addMonth(0);
          TCheckApiNum nowMonthNum = tCheckApiNumService.getById(nowMonth);
          if (nowMonthNum == null) {
               TCheckApiNum lastMonth = tCheckApiNumService.getById(DateUtil.addMonth(-1));
               int canApiNum = 10000;
               if (lastMonth != null && lastMonth.getCanApiNum() != null) {
                    canApiNum = lastMonth.getCanApiNum();
               }
               nowMonthNum = new TCheckApiNum();
               nowMonthNum.setId(nowMonth);
               nowMonthNum.setCanApiNum(canApiNum);
               nowMonthNum.setApiNum(0);
               tCheckApiNumService.save(nowMonthNum);
          } else if (nowMonthNum.getApiNum() >= nowMonthNum.getCanApiNum()) {
               return R.failed("当月总条数：" + nowMonthNum.getCanApiNum() + "已到达上限!");
          }
          if (checkList != null && !checkList.isEmpty()) {
               TCheckLock lock = new TCheckLock();
               lock.setImportNum(checkList.size());
               lock.setApiNum(0);
               lock.setCreateMonth(nowMonth);
               lock.setCreateTime(LocalDateTime.now());
               lock.setCreateUser(String.valueOf(user.getId()));
               lock.setDeleteFlag(0);
               lock.setCreateUserName(user.getNickname());
               tCheckLockService.save(lock);
               int nowApiNum = 0;
               int canApiNum = nowMonthNum.getCanApiNum();

               Map<String, TCheckIdCard> returnMap = this.getAllMap(null);
               TCheckIdCard nowIdCard;
               TCheckIdCard lastCard;
               Map<String, TCheckIdCard> idCardMap = new HashMap<>();
               String userId = String.valueOf(user.getId());
               TCheckLock lockUpdate;
               try {
                    for (TCheckIdCard c : checkList) {
                         if (Common.isNotNull(c.getIdCard()) && Common.isNotNull(c.getName())) {
                              lastCard = idCardMap.get(c.getIdCard());
                              if (lastCard != null) {
                                   c.setIsTrue(lastCard.getIsTrue());
                                   c.setReason(lastCard.getReason());
                              } else {
                                   // 校验姓名身份证规则
                                   if (!regIdCard(c.getIdCard())) {
                                        c.setIsTrue(0);
                                        c.setReason("身份证格式有误");
                                   } else if (regEmpName(c.getName())) {
                                        c.setIsTrue(0);
                                        c.setReason("姓名含数字或空格，无法校验");
                                   } else {
                                        nowIdCard = returnMap.get(c.getIdCard() + CommonConstants.DOWN_LINE_STRING + c.getName());
                                        if (nowIdCard != null) {
                                             c.setIsTrue(nowIdCard.getIsTrue());
                                             c.setReason(nowIdCard.getReason());
                                        } else {
                                             // 调用API校验
                                             if (nowApiNum < canApiNum) {
                                                  nowApiNum++;
                                                  ChecksUtil.checkIdCard(c,canCheckService.getCanCheck());
                                                  c.setCreateUser(userId);
                                                  c.setCreateTime(LocalDateTime.now());
                                                  c.setType(CommonConstants.ONE_INT);
                                                  returnMap.put(c.getIdCard() + CommonConstants.DOWN_LINE_STRING + c.getName(), c);
                                                  this.save(c);
                                                  nowMonthNum.setApiNum(nowMonthNum.getApiNum() + 1);
                                                  tCheckApiNumService.updateById(nowMonthNum);
                                             } else {
                                                  c.setIsTrue(0);
                                                  c.setReason("调用花钱的Api的条数已达上限：" + nowMonthNum.getCanApiNum() + "，请联系管理员处理！");
                                             }
                                        }
                                   }
                                   // 将同身份证的结果存储下来备用，防止撞库
                                   idCardMap.put(c.getIdCard(), c);
                              }
                         } else {
                              c.setIsTrue(0);
                              c.setReason("姓名身份证不可为空");
                         }
                    }
               } catch (Exception e) {
                    lockUpdate = new TCheckLock();
                    lockUpdate.setId(lock.getId());
                    lockUpdate.setDeleteFlag(CommonConstants.ONE_INT);
                    lockUpdate.setApiNum(nowApiNum);
                    tCheckLockService.updateById(lockUpdate);
                    throw new RuntimeException(e.getMessage() == null ? "校验身份证导入失败！" : "校验身份证导入失败：" + e.getMessage());
               } finally {
                    lockUpdate = new TCheckLock();
                    lockUpdate.setId(lock.getId());
                    lockUpdate.setDeleteFlag(CommonConstants.ONE_INT);
                    lockUpdate.setDeleteFlag(CommonConstants.ONE_INT);
                    lockUpdate.setApiNum(nowApiNum);
                    tCheckLockService.updateById(lockUpdate);
               }
               return new R<>(checkList);
          }
          return R.failed("数据为空！");
     }

	/**
      * @param content
      * @Description: 判断身份证格式：18位数字，17位数字+X，15位数字，14位数字+X
      * 格式正确返回true
      * @Author: hgw
      * @Date: 2022/5/13 11:53
      * @return: boolean
      **/
     private static boolean regIdCard(String content) {
          boolean flag = false;
          Pattern p = Pattern.compile("\\d{18}|\\d{17}X|\\d{15}|\\d{14}X");
          Matcher m = p.matcher(content);
          if (m.matches()) {
               flag = true;
          }
          return flag;
     }

     /**
      * @param content
      * @Description: 含数字，返回true
      * @Author: hgw
      * @Date: 2022/5/13 11:54
      * @return: boolean
      **/
     private static boolean regEmpName(String content) {
          boolean flag = false;
          Pattern p = Pattern.compile(".*\\d+.*|.*\\s+.*");
          Matcher m = p.matcher(content);
          if (m.matches()) {
               flag = true;
          }
          return flag;
     }

	@Override
	public TCheckIdCard checkIdCardSingle(TCheckIdCard tCheckIdCard) {
		String idCard = tCheckIdCard.getIdCard();
		String name = tCheckIdCard.getName();
		if (Common.isEmpty(idCard) || Common.isEmpty(name)){
			tCheckIdCard.setIsTrue(CommonConstants.ZERO_INT);
			tCheckIdCard.setReason(CommonConstants.PARAM_IS_NOT_EMPTY);
			return tCheckIdCard;
		}
		// 校验姓名身份证规则
		if (!regIdCard(idCard)) {
			tCheckIdCard.setIsTrue(0);
			tCheckIdCard.setReason("身份证格式有误");
			return tCheckIdCard;
		} else if (regEmpName(name)) {
			tCheckIdCard.setIsTrue(0);
			tCheckIdCard.setReason("姓名含数字或空格，无法校验");
			return tCheckIdCard;
		}
		synchronized (this){
			TCheckIdCard checkIdCard = baseMapper.selectOne(Wrappers.<TCheckIdCard>query().lambda()
					.eq(TCheckIdCard::getIdCard,idCard)
					.eq(TCheckIdCard::getIsTrue,CommonConstants.ONE_STRING)
					.last(CommonConstants.LAST_ONE_SQL));
			if (Common.isNotNull(checkIdCard)){
				if (name.equals(checkIdCard.getName())) {
					tCheckIdCard.setIsTrue(CommonConstants.ONE_INT);
				} else {
					tCheckIdCard.setIsTrue(CommonConstants.ZERO_INT);
					tCheckIdCard.setReason("【" + name + "】错误，正确的姓名：" + checkIdCard.getName());
				}
				return tCheckIdCard;
			} else {
				// 没找到正确的，再去找有没有错误的，如果还没有，再查
				List<TCheckIdCard> checkList = baseMapper.selectList(Wrappers.<TCheckIdCard>query().lambda()
						.eq(TCheckIdCard::getIdCard,idCard));
				if (checkList != null && !checkList.isEmpty()) {
					for (TCheckIdCard  c : checkList) {
						if (idCard.equals(c.getIdCard()) && name.equals(c.getName())) {
							tCheckIdCard.setIsTrue(0);
							tCheckIdCard.setReason(c.getReason());
							return tCheckIdCard;
						}
					}
				}
				TCheckIdCard  c = new TCheckIdCard();
				c.setIdCard(idCard);
				c.setName(name);
				ChecksUtil.checkIdCard(c,canCheckService.getCanCheck());
				baseMapper.insert(c);
				tCheckIdCard.setIsTrue(c.getIsTrue());
				tCheckIdCard.setReason(c.getReason());
				return tCheckIdCard;
			}
		}
	}

}
