package com.zjrs.appcomm.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;

public class IdcardUtil {
    /**
     * 身份证-加权因子
     */
    static final int[] SFZ_JIAQUANYINZI = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7,
            9, 10, 5, 8, 4, 2};
    /**
     * 身份证-校验码
     */
    static final char[] SFZ_JIAOYANGMA = {'1', '0', 'X', '9', '8', '7', '6',
            '5', '4', '3', '2'};
    /**
     * 日期YYYYMMDD格式的规则校验类
     */
    static final Pattern DATE_PATTERN = Pattern.compile("\\d{8}?");
    /**
     * 日期YYYYMM格式的格式化类（兼校验）
     */
    static final SimpleDateFormat CSRQ_FORMAT = new SimpleDateFormat("yyyyMMdd");

    static ThreadLocal<SimpleDateFormat> LOCAL_FORMAT = new ThreadLocal<SimpleDateFormat>();

    /**
     * 校验身份证
     *
     * @param idcard 身份证
     * @return {
     * code  0校验通过，1校验不通过
     * msg   校验信息
     * sex   性别 （校验通过）
     * birthday 出生日期 （校验通过）
     * }
     */
    public static final Map<String, String> checkIdcard(String idcard) {
        Map<String, String> resultMap = new HashMap<>();
        StringBuilder t_gmsfz = new StringBuilder();
        StringBuilder msg = new StringBuilder();
        String sex = null;
        String birthday = null;

        t_gmsfz.append(idcard);
        if (t_gmsfz.length() != 15 && t_gmsfz.length() != 18) {
            msg.append("身份证").append(idcard).append("的长度有误，只能是15位或者18位。");
        } else {
            // 15位转18位
            if (t_gmsfz.length() == 15) {
                t_gmsfz.insert(6, "19");
            }
            // 1. 对前17位数字本体码加权求和
            int li_sum = 0;
            for (int i = 0; i < 17; i++) {
                li_sum += Integer.parseInt(t_gmsfz.substring(i, i + 1))
                        * SFZ_JIAQUANYINZI[i];
            }
            // 2. 以11对计算结果取模
            int li_mod = li_sum % 11;
            // 3. 根据模的值得到对应的校验码
            char jiaoyangma = SFZ_JIAOYANGMA[li_mod];

            // 如果17位身份证，那么拼接校验码即可
            if (t_gmsfz.length() == 17) {
                t_gmsfz.append(jiaoyangma);
            } else if (t_gmsfz.charAt(17) != jiaoyangma) {// 比对校验位，看是否相符
                msg.append("身份证").append(idcard).append("的校验码有误。");
            }
            // 获取出生日期
            birthday = t_gmsfz.substring(6, 14);
            // 获取性别，顺序码，奇数是男性，偶数是女性
            sex = (Integer.parseInt(t_gmsfz.substring(16, 17)) & 1) == 0 ? "2"
                    : "1";

            // 校验出生日期
            if (!checkDate(birthday)) {
                msg.append("身份证").append(idcard).append("中的出生日期不合法。");
            }
            // 校验年龄，一出生日期不能是未来时间，二、年龄不能大于150岁
            // /获取当前时间
            if (CSRQ_FORMAT.format(new Date()).compareTo(birthday) < 0) {
                msg.append("身份证").append(idcard).append("中的出生日期不合法。");
            }
        }
        if (msg.length() > 0) {
            //校验不通过
            resultMap.put("code", "1");
            resultMap.put("msg", msg.toString());
            return resultMap;
        }
        //校验通过
        resultMap.put("code", "0");
        resultMap.put("msg", "校验通过");
        resultMap.put("birthday", birthday);
        resultMap.put("sex", sex);
        return resultMap;
    }

    /**
     * 校验社会统一信用代码
     *
     * @param str 社会统一信用代码
     * @return
     */
    public static boolean checkTyshxydm(String str) {
        Pattern zzjgdmR = Pattern.compile("[0-9A-Z]{18}");
        Matcher zzjgdmM = zzjgdmR.matcher(str);
        if (zzjgdmM.matches()) {
            return true;
        }
        return false;

    }

    /**
     * 检查日期字符串（格式YYYYMMDD）是否合法日期
     *
     * @param date 日期字符串（格式YYYYMMDD）
     * @return true 表示合法，false表示不合法
     */
    public static boolean checkDate(String date) {
        // 空或者空串一律返回false
        if (date == null || date.length() == 0) {
            return false;
        }
        // 日期类型必须全部是数字
        if (!DATE_PATTERN.matcher(date).matches()) {
            return false;
        } else {
            try {
                SimpleDateFormat CSRQ_FORMAT = LOCAL_FORMAT.get();
                if (CSRQ_FORMAT == null) {
                    CSRQ_FORMAT = new SimpleDateFormat("yyyyMMdd");
                    LOCAL_FORMAT.set(CSRQ_FORMAT);
                }
                CSRQ_FORMAT.parse(date);
            } catch (ParseException e) {
                return false;
            }
            return true;
        }
    }
}
