package com.bonus.gs.sub.evaluate.manager.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName: RegularCheckUtils
 * @author: tqzhang
 * @Date: 2025/1/7 11:17
 * @version: 1.0
 * @description: 正则校验工具类
 */
public class RegularCheckUtils {
    // 省份代码表
    private static final Map<Integer, String> PROVINCE_CODES = new HashMap<>();

    static {
        // 初始化省份代码
        PROVINCE_CODES.put(11, "北京");
        PROVINCE_CODES.put(12, "天津");
        PROVINCE_CODES.put(13, "河北");
        PROVINCE_CODES.put(14, "山西");
        PROVINCE_CODES.put(15, "内蒙古");
        PROVINCE_CODES.put(21, "辽宁");
        PROVINCE_CODES.put(22, "吉林");
        PROVINCE_CODES.put(23, "黑龙江");
        PROVINCE_CODES.put(31, "上海");
        PROVINCE_CODES.put(32, "江苏");
        PROVINCE_CODES.put(33, "浙江");
        PROVINCE_CODES.put(34, "安徽");
        PROVINCE_CODES.put(35, "福建");
        PROVINCE_CODES.put(36, "江西");
        PROVINCE_CODES.put(37, "山东");
        PROVINCE_CODES.put(41, "河南");
        PROVINCE_CODES.put(42, "湖北");
        PROVINCE_CODES.put(43, "湖南");
        PROVINCE_CODES.put(44, "广东");
        PROVINCE_CODES.put(45, "广西");
        PROVINCE_CODES.put(46, "海南");
        PROVINCE_CODES.put(50, "重庆");
        PROVINCE_CODES.put(51, "四川");
        PROVINCE_CODES.put(52, "贵州");
        PROVINCE_CODES.put(53, "云南");
        PROVINCE_CODES.put(54, "西藏");
        PROVINCE_CODES.put(61, "陕西");
        PROVINCE_CODES.put(62, "甘肃");
        PROVINCE_CODES.put(63, "青海");
        PROVINCE_CODES.put(64, "宁夏");
        PROVINCE_CODES.put(65, "新疆");
        PROVINCE_CODES.put(71, "台湾");
        PROVINCE_CODES.put(81, "香港");
        PROVINCE_CODES.put(82, "澳门");
        PROVINCE_CODES.put(91, "国外");
    }

    /**
     * 校验身份证号码
     *
     * @param value 身份证号码
     * @return 是否有效
     */
    public static boolean verificationIdCard(String value) {
        String idCard = String.valueOf(value);

        // 1. 校验身份证号格式和长度
        String regPsidno = "^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[X])$)$";
        if (!Pattern.matches(regPsidno, idCard)) {
            return false;
        }

        // 2. 校验前两位的省份编码是否正确
        int provinceCode = Integer.parseInt(idCard.substring(0, 2));
        if (!PROVINCE_CODES.containsKey(provinceCode)) {
            return false;
        }

        // 3. 校验出生日期
        if (idCard.length() == 15) {
            // 15位号码：省（2位）市（2位）县（2位）年（2位）月（2位）日（2位）校验码（3位）
            String year = idCard.substring(6, 8);
            String month = idCard.substring(8, 10);
            String day = idCard.substring(10, 12);
            // 15位号码在年份前补 19 或 20
            year = (Integer.parseInt(year.charAt(0) + "") > 0) ? "19" + year : "20" + year;
            if (!validateBirthDay(year, month, day)) {
                return false;
            }
        } else if (idCard.length() == 18) {
            // 18位号码：省（2位）市（2位）县（2位）年（4位）月（2位）日（2位）校验码（4位）
            String year = idCard.substring(6, 10);
            String month = idCard.substring(10, 12);
            String day = idCard.substring(12, 14);
            if (!validateBirthDay(year, month, day)) {
                return false;
            }
        } else {
            return false;
        }

        // 4. 18位号码校验生成的校验码
        if (idCard.length() == 18) {
            // 加权因子
            int[] Wi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
            // 校验码
            char[] parity = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
            int sum = 0;
            for (int i = 0; i < 17; i++) {
                sum += Integer.parseInt(idCard.charAt(i) + "") * Wi[i];
            }
            char expectedCheckCode = parity[sum % 11];
            char actualCheckCode = idCard.charAt(17);
            if (expectedCheckCode != actualCheckCode) {
                return false;
            }
        }

        return true;
    }

    /**
     * 校验出生日期是否合理
     *
     * @param year  年
     * @param month 月
     * @param day   日
     * @return 是否有效
     */
    private static boolean validateBirthDay(String year, String month, String day) {
        int y = Integer.parseInt(year);
        int m = Integer.parseInt(month);
        int d = Integer.parseInt(day);

        // 获取当前时间
        long nowTime = System.currentTimeMillis();
        // 获取出生日期的时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 严格模式
        sdf.setLenient(false);
        try {
            Date birthDate = sdf.parse(year + "-" + month + "-" + day);
            long birthTime = birthDate.getTime();

            // 不能是明天出生的吧
            if (birthTime > nowTime) {
                return false;
            }

            // 一般人活不到150岁吧
            int nowYear = new Date().getYear() + 1900;
            if ((nowYear - y) > 150) {
                return false;
            }

            // 不能是13月出生的吧
            if (m < 1 || m > 12) {
                return false;
            }

            // 不能是2月30号、4月31号、5月32号出生的吧
            // 获取当月的最后一天
            int maxDay = new Date(y, m, 0).getDate();
            if (d < 1 || d > maxDay) {
                return false;
            }

            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    /**
     * 校验手机号码
     *
     * @param value 手机号码
     * @return 是否有效
     */
    public static boolean verificationPhone(String value){
        String regex = "^13[0-9]{1}[0-9]{8}$|15[0-9]{1}[0-9]{8}$|16[0-9]{1}[0-9]{8}$|18[0-9]{1}[0-9]{8}$|17[0-9]{1}[0-9]{8}$|19[0-9]{1}[0-9]{8}$|14[0-9]{1}[0-9]{8}$";

        // 编译正则表达式
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(value);

        // 返回匹配结果
        return matcher.matches();
    }

}
