package cn.quantgroup.xyqb.util;

import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.util.encrypt.Md5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.util.Calendar;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Miraculous on 15/7/6.
 * 所有validate为真返回true， 否则返回false
 */
@Slf4j
public class ValidationUtil {

    public static final String phoneRegExp = "^1[3456789][0-9]{9}$";
    private static final String chineseNameRegExp = "^[\u4e00-\u9fff]+((\\.|·)[\u4e00-\u9fff]+){0,2}$";
    private static final String chineseNameExtendRegExp = "^[\u4dae\u4e00-\u9fff]+((\\.|·)[\u4dae\u4e00-\u9fff]+){0,2}$";
    private static final String ipv4RegExp = "^((2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)\\.){3}(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)$";
    private static final String localIpv4RegExp = "^((172\\.(1[0-6]|2[0-9]|3[01]))|(192\\.168|169\\.254)|((127|10)\\.(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)))(\\.(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)){2}$";
    private static final String tokenRegExp = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
    public static final String numberRegExp = "^([0-9]+)((,|;)+[0-9]+)*$";
    private static final String pwdRegExp = "^(?![A-Za-z]+$)(?!\\d+$)(?![\\W_]+$)[\\x21-\\x7f]{8,20}$";

    public static final String numberFilterRegExp = "(\\s*(,|;))+";

    private static final Pattern phonePattern = Pattern.compile(phoneRegExp);
    private static final Pattern passwordPattern = Pattern.compile(pwdRegExp);
    private static final Pattern chinesePattern = Pattern.compile(chineseNameRegExp);
    private static final Pattern chineseExtendPattern = Pattern.compile(chineseNameExtendRegExp);
    private static final Pattern ipv4Pattern = Pattern.compile(ipv4RegExp);
    private static final Pattern localIpv4Pattern = Pattern.compile(localIpv4RegExp);
    private static final Pattern tokenPattern = Pattern.compile(tokenRegExp);
    public static final Pattern numberPattern = Pattern.compile(numberRegExp);

    /**
     * 是否是合法的中国大陆手机号
     *
     * @param phoneNo
     * @return
     */
    public static boolean validatePhoneNo(String phoneNo) {
        boolean lengthValid = StringUtils.isNotBlank(phoneNo) && phoneNo.length() == 11 && StringUtils.isNumeric(phoneNo);
        if (!lengthValid) {
            return false;
        }
        Matcher matcher = phonePattern.matcher(phoneNo);
        return matcher.find();
    }

    /**
     * 是否是合法的中文姓名
     *
     * @param chinese
     * @return
     */
    public static boolean validateChinese(String chinese) {
        if (StringUtils.isBlank(chinese)) {
            return false;
        }
        boolean valid = chinesePattern.matcher(chinese).find();
        if (!valid) {
            StringBuilder uniCodeTemp = new StringBuilder();
            for (int i = 0; i < chinese.length(); i++) {
                uniCodeTemp.append("\\u").append(Integer.toHexString((int) chinese.charAt(i)));
            }
            log.info("[ValidationUtil][validateChinese]:[chinese][length][unicode]:[{}][{}][{}]", chinese, chinese.length(), uniCodeTemp);
        }
        // 兼容扩展字集合
        valid = valid || chineseExtendPattern.matcher(chinese).find();
        return valid;
    }

    /**
     * 是否是合法的IPV4地址
     *
     * @param ipv4
     * @return
     */
    public static boolean validateIpv4(String ipv4) {
        if (StringUtils.isBlank(ipv4)) {
            return false;
        }
        Matcher matcher = ipv4Pattern.matcher(ipv4);
        return matcher.find();
    }

    /**
     * 是否是合法的私有IPV4地址
     *
     * @param localIpv4
     * @return
     */
    public static boolean validateLocalIpv4(String localIpv4) {
        if (StringUtils.isBlank(localIpv4)) {
            return false;
        }
        Matcher matcher = localIpv4Pattern.matcher(localIpv4);
        return matcher.find();
    }

    /**
     * 是否是合法的用户中心token
     *
     * @param token
     * @return
     */
    public static boolean validateToken(String token) {
        if (StringUtils.isBlank(token)) {
            return false;
        }
        Matcher matcher = tokenPattern.matcher(token);
        return matcher.find();
    }

    /**
     * 是否是合法的多个数值串
     *
     * @param numbers
     * @return
     */
    public static boolean validateNumbers(String numbers) {
        if (StringUtils.isBlank(numbers)) {
            return false;
        }
        Matcher matcher = numberPattern.matcher(numbers);
        return matcher.find();
    }

    /**
     * 是否是合法的密码字符串
     *
     * @param password
     * @return
     */
    public static boolean validatePassword(String password){
        if (StringUtils.isBlank(password)){
            return false;
        }
        Matcher matcher = passwordPattern.matcher(password);
        return matcher.find();
    }

    /**
     * 过滤掉合法的多个数值串间的空白值
     *
     * @param numbers
     * @return
     */
    public static String filterNumbers(String numbers) {
        if (StringUtils.isBlank(numbers)) {
            return null;
        }
        return numbers.replaceAll(numberFilterRegExp, ",");
    }

    /**
     * 验证密令
     * 私钥 + 操作 + 时
     *
     * @param key  - Md5密令
     * @param lock - true or false
     * @return
     */
    public static boolean isValid(String key, boolean lock) {
        return Objects.equals(key, getMd5Key(lock));
    }

    /**
     * 计算密令
     * 私钥 + 操作 + 时
     *
     * @param lock - true or false
     * @return 加密后的Md5
     */
    public static String getMd5Key(boolean lock) {
        Calendar today = Calendar.getInstance();
        int hour_24 = today.get(Calendar.HOUR_OF_DAY);
        return Md5Util.build(Constants.CLEAR_LOCK_FOR_IPV4_KEY + lock + hour_24);
    }

}
