/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the yifu4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.yifu.cloud.plus.v1.check.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.check.entity.TCanCheck;
import com.yifu.cloud.plus.v1.check.entity.TCheckMobile;
import com.yifu.cloud.plus.v1.check.entity.TPreEmpCheckNum;
import com.yifu.cloud.plus.v1.check.mapper.TCheckMobileMapper;
import com.yifu.cloud.plus.v1.check.service.TCanCheckService;
import com.yifu.cloud.plus.v1.check.service.TCheckMobileService;
import com.yifu.cloud.plus.v1.check.service.TPreEmpCheckNumService;
import com.yifu.cloud.plus.v1.check.utils.ChecksUtil;
import com.yifu.cloud.plus.v1.check.vo.CheckBatchVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.exception.ErrorCodes;
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.MsgUtils;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 手机号码校验
 *
 * @author fxj
 * @date 2022-06-20 17:29:03
 */
@RequiredArgsConstructor
@Service
public class TCheckMobileServiceImpl extends ServiceImpl<TCheckMobileMapper, TCheckMobile> implements TCheckMobileService {

	private final TCanCheckService canCheckService;
	private final TPreEmpCheckNumService tPreEmpCheckNumService;

	/**
	 * @Author fxj   待完善
	 * @Description 号码状态校验，单次请求上限100  多一个号码请以逗号分割
	 * @Date 19:18 2022/6/20
	 **/
	@Override
	public synchronized R<Map<String, TCheckMobile>> checkMobiles(String mobiles) {
		R<Map<String, TCheckMobile>> mobileMapR = null;
		Map<String, TCheckMobile> checkMobileMap = null;
		Map<String, TCheckMobile> existMap = new HashMap<>();
		if (Common.isNotNull(mobiles)) {
			List<String> mobileList = Common.initStrToList(mobiles, CommonConstants.COMMA_STRING);
			if (Common.isNotEmpty(mobileList) && mobileList.size() > CommonConstants.INTEGER_HUNDRED) {
				return R.failed(MsgUtils.getMessage(ErrorCodes.CHECKS_MOBILE_REQUEST_LIMIT_HUNDRED));
			}
			//1.先从本地库获取正常数据
			List<TCheckMobile> checkMobiles = baseMapper.selectList(Wrappers.<TCheckMobile>query().lambda()
					.in(TCheckMobile::getMobile, mobileList)
					.eq(TCheckMobile::getStatus, CommonConstants.ONE_STRING));
			if (Common.isNotNull(checkMobiles)) {
				existMap = checkMobiles.stream().collect(Collectors.toMap(TCheckMobile::getMobile, TCheckMobile -> TCheckMobile));
			}
			mobileList.removeAll(existMap.keySet());
			//2.从远处端获取数据
			if (Common.isNotNull(mobileList)) {
				mobileMapR = ChecksUtil.checkMobile(Common.ListToStr(mobileList, CommonConstants.COMMA_STRING), canCheckService.getCanCheck());
				if (Common.isEmpty(mobileMapR) || Common.isEmpty(mobileMapR.getData())) {
					return R.failed(MsgUtils.getMessage(ErrorCodes.CHECKS_MOBILE_REQUEST_ERROR)
							+ (Common.isNotNull(mobileMapR) ? mobileMapR.getMsg() : CommonConstants.EMPTY_STRING));
				}
				checkMobileMap = mobileMapR.getData();
				if (Common.isNotNull(mobileList) && Common.isNotNull(checkMobileMap)) {
					TCheckMobile checkMobile = null;
					for (String mobile : mobileList) {
						if (Common.isEmpty(checkMobileMap.get(mobile))) {
							checkMobile = new TCheckMobile();
							checkMobile.setType(CommonConstants.ONE_STRING);
							checkMobile.setMobile(mobile);
							checkMobile.setStatus(CommonConstants.TEN_STRING);
							checkMobile.setMessage(Common.isEmpty(mobileMapR) ? MsgUtils.getMessage(ErrorCodes.CHECKS_MOBILE_REQUEST_ERROR) : mobileMapR.getMsg());
							checkMobile.setChargesstatus(CommonConstants.ZERO_STRING);
							checkMobile.setNumbertype(CommonConstants.EMPTY_STRING);
							checkMobile.setArea(CommonConstants.EMPTY_STRING);
							checkMobileMap.put(mobile, checkMobile);
						}
					}
				}
			}
		} else {
			return R.failed(MsgUtils.getMessage(ErrorCodes.PARAM_NOT_EMPTY));
		}
		if (Common.isNotNull(checkMobileMap)) {
			this.saveBatch(checkMobileMap.values());
		} else {
			checkMobileMap = new HashMap<>();
		}
		checkMobileMap.putAll(existMap);
		if (Common.isEmpty(mobileMapR)) {
			mobileMapR = new R<>();
		}
		mobileMapR.setData(checkMobileMap);
		return mobileMapR;
	}

	@Override
	public synchronized TCheckMobile checkOneMobile(String mobile) {
		TCheckMobile returnMobile = new TCheckMobile();
		returnMobile.setMobile(mobile);
		returnMobile.setMessage("手机号不可用！");
		returnMobile.setStatus(CommonConstants.ZERO_STRING);
		if (Common.isNotNull(mobile)) {
			//1.先从本地库获取正常数据
			List<TCheckMobile> checkMobiles = baseMapper.selectList(Wrappers.<TCheckMobile>query().lambda()
					.eq(TCheckMobile::getMobile, mobile));
			if (Common.isNotNull(checkMobiles)) {
				for (TCheckMobile c : checkMobiles) {
					if (CommonConstants.ONE_STRING.equals(c.getStatus())
							|| CommonConstants.FOUR_STRING.equals(c.getStatus())
							|| CommonConstants.FIVE_STRING.equals(c.getStatus())) {
						returnMobile.setStatus(CommonConstants.ONE_STRING);
						returnMobile.setMessage(c.getMessage());
						return returnMobile;
					}
				}
				return returnMobile;
			} else {
				//2.从远处端获取数据
				R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobile(mobile, canCheckService.getCanCheck());
				if (Common.isEmpty(mobileMapR) || Common.isEmpty(mobileMapR.getData())) {
					if (mobileMapR != null) {
						returnMobile.setMessage(mobileMapR.getMsg());
					}
					return returnMobile;
				}
				Map<String, TCheckMobile> checkMobileMap = mobileMapR.getData();
				if (Common.isNotNull(checkMobileMap) && checkMobileMap.get(mobile) != null) {
					TCheckMobile checkMobile = checkMobileMap.get(mobile);
					this.save(checkMobile);
					if (checkMobile != null
							&& (CommonConstants.ONE_STRING.equals(checkMobile.getStatus())
							|| CommonConstants.FOUR_STRING.equals(checkMobile.getStatus())
							|| CommonConstants.FIVE_STRING.equals(checkMobile.getStatus()))) {
						returnMobile.setStatus(CommonConstants.ONE_STRING);
						return returnMobile;
					} else {
						return returnMobile;
					}
				}
			}
		}
		return returnMobile;
	}

	@Override
	public CheckBatchVo checkMobileBatch(List<String> list) {
		CheckBatchVo vo = new CheckBatchVo();
		Map<String, Boolean> noMap = new HashMap<>();
		if (!list.isEmpty()) {
			List<TCheckMobile> checkMobileList = baseMapper.getListByNoList(list);
			if (checkMobileList != null && !checkMobileList.isEmpty()) {
				for (TCheckMobile no : checkMobileList) {
					noMap.put(no.getMobile(), CommonConstants.ONE_STRING.equals(no.getStatus())
							|| CommonConstants.FOUR_STRING.equals(no.getStatus())
							|| CommonConstants.FIVE_STRING.equals(no.getStatus()));
				}
			}
		}
		List<String> noCurlist = new ArrayList<>();
		Map<String, Boolean> backMap = new HashMap<>();
		List<String> tempList = new ArrayList<>();
		// 因手机号码最多50个所以这里 要特殊处理下
		if (Common.isNotNull(list)){
			//计数器
			int count =1;
			for (String phone:list){
				tempList.add(phone);
				if (count == 50){
					checkMobiles(tempList, vo, noMap, noCurlist, backMap);
					tempList.clear();
					// 重置
					count =1;
				}else {
					count ++;
				}
			}
		}
		checkMobiles(tempList, vo, noMap, noCurlist, backMap);
		return vo;
	}
	@Override
	public R<String> checkPrePhone(String phone, String deptId) {
		TCanCheck tCanCheck= canCheckService.getById(1);
		boolean canCheck = false;
		String nowDay = DateUtil.getThisDay();
		if (tCanCheck != null && tCanCheck.getCanCheck() == 1) {
			canCheck  = true;
			TPreEmpCheckNum nowDayNum = tPreEmpCheckNumService.getTPreEmpCheckNum(deptId, nowDay);
			if (nowDayNum == null) {
				nowDayNum = new TPreEmpCheckNum();
				nowDayNum.setCreateDay(nowDay);
				nowDayNum.setDeptId(deptId);
				nowDayNum.setCanApiNum(1000);
				nowDayNum.setApiNum(1);
				tPreEmpCheckNumService.save(nowDayNum);
			} else {
				if (nowDayNum.getApiNum() >= nowDayNum.getCanApiNum()) {
					return R.failed("该项目当日总条数：" + nowDayNum.getCanApiNum() + "已到达上限!");
				} else {
					nowDayNum.setApiNum(nowDayNum.getApiNum() + 1);
					tPreEmpCheckNumService.updateById(nowDayNum);
				}
			}
		}
		synchronized (this) {
			R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobile(phone, canCheck);
			if (Common.isNotNull(mobileMapR) && Common.isNotNull(mobileMapR.getData())) {
				Map<String, TCheckMobile> result = mobileMapR.getData();
				TCheckMobile mo = result.get(phone);
				if (mo != null) {
					this.saveOrUpdate(mo);
					if (Common.isNotNull(mo.getStatus()) &&
							(CommonConstants.ONE_STRING.equals(mo.getStatus())
							|| CommonConstants.FOUR_STRING.equals(mo.getStatus())
							|| CommonConstants.FIVE_STRING.equals(mo.getStatus()))) {
						return R.ok();
					} else {
						return R.failed(Common.isNotNull(mo.getMessage()) ? mo.getMessage() : "校验错误！");
					}
				} else {
					return R.failed("校验失败");
				}
			}
		}
		return R.failed("校验失败!");
	}

	private void checkMobiles(List<String> list,
							  CheckBatchVo vo,
							  Map<String, Boolean> noMap,
							  List<String> noCurlist,
							  Map<String, Boolean> backMap) {
		StringBuilder phones = new StringBuilder();
		Boolean cur;
		for (String check : list) {
			cur = noMap.get(check);
			if (cur != null) {
				backMap.put(check, cur);
			} else {
				phones.append(check).append(CommonConstants.COMMA_STRING);
				noCurlist.add(check);
			}
		}
		if (phones.length() > 0) {
			phones.deleteCharAt(phones.length()-1);
		}
		List<TCheckMobile> saveList = new ArrayList<>();
		if (!noCurlist.isEmpty() && Common.isNotNull(phones)) {
			synchronized (this) {
					R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobile(phones.toString(), canCheckService.getCanCheck());
					if (Common.isNotNull(mobileMapR) && Common.isNotNull(mobileMapR.getData())) {
						Map<String, TCheckMobile> result = mobileMapR.getData();
						TCheckMobile mo;
						for (String no : noCurlist) {
							mo = result.get(no);
							backMap.put(no, mo == null || (CommonConstants.ONE_STRING.equals(mo.getStatus())
									|| CommonConstants.FOUR_STRING.equals(mo.getStatus())
									|| CommonConstants.FIVE_STRING.equals(mo.getStatus())));
							if (mo != null) {
								saveList.add(mo);
							}
						}
					}
				if (!saveList.isEmpty()) {
					this.saveOrUpdateBatch(saveList);
				}
				saveList.clear();
			}
		}
		vo.setCheckMap(backMap);
	}
}
