package com.hai.common.utils;

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

/**
 * @ClassName IdCardUtil
 * @Description
 * @Author 杜江
 * @Date 2020/8/11 11:38
 * @Version 1.0
 */
public class IdCardUtil {
    public static boolean isIdCard(String card){
        card = replaceBlank(card);
        if(card == null || "".equals(card)){
            return false;
        }
        //定义 叛别用户 身份证号的正则表达式 （15位 或 18位，最后一位可以为字母）
        String requal = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|(10|20|30|31))\\d{3}[0-9Xx]$)|"
                +"(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";

        //  假设18位 身份证号码：
        //   ^ 表示开头
        //  [1-9]         第一位1-9 中的一个     4    注意！！ 前六位代表地址，此处是 拆分 讲解 对正则 的注释
        //  \\d{5}        五位数字               10001（前六位省市县地区）
        //  (18|19|20)    19   （现阶段可能取值范围18xx-20xx年）
        //  \\d{2}        91   （年份）
        //  ((0[1-9])|(10|11|12))         01（月份）
        //  (([0-2][1-9])|10|20|30|31)    01（日期）    也可写成(([0-2][1-9])|(10|20|30|31))
        //  \\d{3}        三位数字        123（第十七位奇数表示男，偶数表示女）
        //  [0-9Xx]       0123456789Xx 其中的一个   X（第十八位为校验值）
        //  $结尾

        //  假设15位身份证号码： 410001910101123
        //  ^ 开头
        //  [1-9]          第一位1-9中的一个      4
        //  \\d{5}         五位数字               10001（前六位省市县地区）
        //  \\d{2}         91（年份）             表示 91年
        //  ((0[1-9])|(10|11|12))        01（月份）
        //  (([0-2][1-9])|10|20|30|31)   01（日期）
        //  \\d{3}         123（第十五位奇数代表男，偶数代表女），15位身份证不含X
        //  $结尾
        boolean matches = card.matches(requal);

        //判断 第 18位 校验值 ，校验算法涉及两次mod 11的过程
        // 二代身份证中的 号码第十八位的计算方法为：
        if(matches){
            if (card.length() == 18){
                try {
                    char[] charArray = card.toCharArray();
                    //1，将前面的身份证号码17位数分别乘以不同的系数，系数为此处的 加权因子
                    //前十七位加权因子
                    int[] idCardWi = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
                    int sum =  0;
                    // 2，将这17位数字 和系数相乘 的结果相加
                    for (int i = 0;i < idCardWi.length;i++){
                        int current = Integer.parseInt(String.valueOf(charArray[i]));
                        // 相乘对应的 加权因子系数
                        int count = current * idCardWi[i];
                        // 结果相加
                        sum += count;
                    }
                    char idCardLast = charArray[17];
                    // 3，结果和 除以11，查看余数
                    int idCardMod = sum % 11;
                    // 4，这是除以 11后，可能产生的 11位余数对应的验证码(--对应下标)，其中 X 代表罗马数字 10
                    String[] idCardY = {"1","0","X","9","8","7","6","5","4","3","2"};
                    if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())){
                        return true;
                    }else {
                        System.out.println("身份证最后一位："+String.valueOf(idCardLast).toUpperCase()+
                                "错误，正确的应该是："+idCardY[idCardMod].toUpperCase());
                        return false;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    System.out.println("异常："+card);
                    return false;
                }
            }
        }
        return matches;
    }

    public static String replaceBlank(String str) {
        String dest = "";
        if (str!=null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }

    public static void main(String[] args) {
        System.out.println(isIdCard("5113221999409035038"));
    }
}
