package com.ruoyi.common.utils;

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

public class SensitiveInfoDetector {
    // 18位身份证正则表达式（更严格）
    private static final String ID_CARD_18_REGEX = "(?<![0-9])[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx](?![0-9])";
    // 15位身份证正则表达式
    private static final String ID_CARD_15_REGEX = "(?<![0-9])[1-9]\\d{7}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}(?![0-9])";
    // 手机号正则表达式（更严格）
    private static final String PHONE_REGEX = "(?<![0-9])1[3-9]\\d{9}(?![0-9])";
    // 银行卡号正则表达式（优化版）
    private static final String BANK_CARD_REGEX = "(?<![0-9])([3-6]\\d{15,18})(?![0-9])";
    // 统一社会信用代码正则表达式
    private static final String CREDIT_CODE_REGEX = "(?<![0-9A-Z])[0-9A-Z]{18}(?![0-9A-Z])";

    public static void main(String[] args) {
        String testText = "我的身份证是11010519491231002X中国211221198803141210 ，手机号是13800138000，" +
                "银行卡号是6225881012345678，6217000180004045123还有测试号码如15612341234，" +
                "身份证342623199001011234，4111111111111111卡号1234567812345670。信用代码12152826461250168C";

        // 检测测试
        System.out.println("=== 检测结果 ===");
        System.out.println("包含身份证: " + containsIdCard(testText));
        System.out.println("包含手机号: " + containsPhone(testText));
        System.out.println("包含银行卡: " + containsBankCard(testText));

        // 提取测试
        System.out.println("\n=== 提取结果 ===");
        System.out.println("身份证列表: " + extractIdCards(testText));
        System.out.println("手机号列表: " + extractPhones(testText));
        System.out.println("银行卡列表: " + extractBankCards(testText));
        System.out.println("信用代码列表: " + extractCreditCodes(testText));
    }

    // 检测方法
    public static boolean containsIdCard(String text) {
        if (text == null) return false;
        return Pattern.compile(ID_CARD_18_REGEX).matcher(text).find() ||
                Pattern.compile(ID_CARD_15_REGEX).matcher(text).find();
    }

    public static boolean containsPhone(String text) {
        if (text == null) return false;
        return Pattern.compile(PHONE_REGEX).matcher(text).find();
    }

    public static boolean containsBankCard(String text) {
        if (text == null) return false;
        Matcher matcher = Pattern.compile(BANK_CARD_REGEX).matcher(text);
        while (matcher.find()) {
            if (checkLuhn(matcher.group())) return true;
        }
        return false;
    }

    // 提取方法
    public static List<String> extractIdCards(String text) {
        List<String> results = new ArrayList<>();
        if (text == null) return results;

        // 匹配18位身份证
        Matcher m18 = Pattern.compile(ID_CARD_18_REGEX).matcher(text);
        while (m18.find()) {
            String id = m18.group();
            if (checkIdCard18Checksum(id)) results.add(id);
        }

        // 匹配15位身份证
        Matcher m15 = Pattern.compile(ID_CARD_15_REGEX).matcher(text);
        while (m15.find()) results.add(m15.group());

        return results;
    }

    public static List<String> extractPhones(String text) {
        List<String> results = new ArrayList<>();
        if (text == null) return results;

        Matcher matcher = Pattern.compile(PHONE_REGEX).matcher(text);
        while (matcher.find()) results.add(matcher.group());

        return results;
    }

    public static List<String> extractBankCards(String text) {
        List<String> results = new ArrayList<>();
        if (text == null) return results;

        Matcher matcher = Pattern.compile(BANK_CARD_REGEX).matcher(text);
        while (matcher.find()) {
            String card = matcher.group();
            // 排除信用代码和无效卡号
            if (!isCreditCode(card) && checkLuhn(card)) {
                results.add(card);
            }
        }
        return results;
    }

    public static List<String> extractCreditCodes(String text) {
        List<String> results = new ArrayList<>();
        if (text == null) return results;

        Matcher matcher = Pattern.compile(CREDIT_CODE_REGEX).matcher(text);
        while (matcher.find()) {
            String code = matcher.group();
            if (!isIdCard(code) && !isBankCard(code)) {
                results.add(code);
            }
        }
        return results;
    }

    // 验证方法
    private static boolean checkIdCard18Checksum(String idCard) {
        if (idCard == null || idCard.length() != 18) return false;

        int[] weights = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
        char[] checks = {'1','0','X','9','8','7','6','5','4','3','2'};

        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (idCard.charAt(i) - '0') * weights[i];
        }

        return Character.toUpperCase(idCard.charAt(17)) == checks[sum % 11];
    }

    private static boolean checkLuhn(String cardNumber) {
        if (cardNumber == null || cardNumber.length() < 16 || cardNumber.length() > 19) {
            return false;
        }

        int sum = 0;
        boolean alternate = false;
        for (int i = cardNumber.length() - 1; i >= 0; i--) {
            int digit = cardNumber.charAt(i) - '0';
            if (alternate) {
                digit *= 2;
                if (digit > 9) digit = digit - 9;
            }
            sum += digit;
            alternate = !alternate;
        }
        return sum % 10 == 0;
    }

    // 辅助方法
    private static boolean isCreditCode(String code) {
        return code != null && code.matches(CREDIT_CODE_REGEX);
    }

    private static boolean isIdCard(String id) {
        if (id == null) return false;
        if (id.length() == 18) {
            return Pattern.compile(ID_CARD_18_REGEX).matcher(id).matches() &&
                    checkIdCard18Checksum(id);
        }
        return id.length() == 15 && Pattern.compile(ID_CARD_15_REGEX).matcher(id).matches();
    }

    private static boolean isBankCard(String card) {
        return card != null && card.matches(BANK_CARD_REGEX) && checkLuhn(card);
    }

    /**
     * 截取指定位置的上下文
     */
    public static String extractContext(String content, String word) {
        int start = content.indexOf(word);
        if (start == -1) return "";

        int end = start + word.length();
        int contextSize = 20;
        int contextStart = Math.max(0, start - contextSize);
        int contextEnd = Math.min(content.length(), end + contextSize);
        return content.substring(contextStart, contextEnd);
    }

    public static String extractContext2(String content, String word) {
        int start = content.indexOf(word);
        if (start == -1) return "";

        int end = start + word.length();
        int contextSize = 5;
        int contextStart = Math.max(0, start - contextSize);
        int contextEnd = Math.min(content.length(), end + contextSize);
        return content.substring(contextStart, contextEnd);
    }
}