package com.sckw.core.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author system
 * @description 车牌号工具类
 * @date 2025-06-24
 */
public class TruckNoUtils {

    /**
     * 车牌号正则表达式（7位标准车牌）
     * 格式：省份简称(1位) + 字母(1位) + 数字/字母(5位)
     */
    private static final String TRUCK_NO_PATTERN_7 = "^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使]{1}[A-Z]{1}[0-9A-Z]{5}$";

    /**
     * 车牌号正则表达式（8位新能源车牌）
     * 格式：省份简称(1位) + 字母(1位) + 数字/字母(6位)
     */
    private static final String TRUCK_NO_PATTERN_8 = "^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使]{1}[A-Z]{1}[0-9A-Z]{6}$";

    /**
     * 省份简称（用于智能拆分车牌号）
     */
    private static final String PROVINCES = "京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使";

    /**
     * 支持的分隔符：中文逗号、英文逗号、空格、换行符、制表符
     */
    private static final String DELIMITER_PATTERN = "[,，\\s\\n\\r\\t]+";

    /**
     * 校验单个车牌号格式是否正确
     *
     * @param truckNo 车牌号
     * @return true-格式正确，false-格式错误
     */
    public static boolean isValidTruckNo(String truckNo) {
        if (StringUtils.isBlank(truckNo)) {
            return false;
        }

        String formatted = formatTruckNo(truckNo);
        return Pattern.matches(TRUCK_NO_PATTERN_7, formatted) 
                || Pattern.matches(TRUCK_NO_PATTERN_8, formatted);
    }

    /**
     * 格式化车牌号（去除空格、转大写）
     *
     * @param truckNo 原始车牌号
     * @return 格式化后的车牌号
     */
    public static String formatTruckNo(String truckNo) {
        if (StringUtils.isBlank(truckNo)) {
            return "";
        }
        // 去除所有空格并转大写
        return truckNo.trim().replaceAll("\\s+", "").toUpperCase();
    }

    /**
     * 批量格式化车牌号
     *
     * @param truckNos 车牌号列表
     * @return 格式化后的车牌号列表
     */
    public static List<String> formatTruckNos(List<String> truckNos) {
        if (CollectionUtils.isEmpty(truckNos)) {
            return new ArrayList<>();
        }
        return truckNos.stream()
                .map(TruckNoUtils::formatTruckNo)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 从字符串中拆分车牌号
     * 支持两种模式：
     * 1. 分隔符模式：中文逗号、英文逗号、空格、换行符等分隔符
     * 2. 智能识别模式：无分隔符，通过识别省份简称自动拆分（如：川A12345京B67890）
     *
     * @param truckNoStr 车牌号字符串，如："川A12345,京B67890" 或 "川A12345京B67890"
     * @return 车牌号列表
     */
    public static List<String> splitTruckNos(String truckNoStr) {
        if (StringUtils.isBlank(truckNoStr)) {
            return new ArrayList<>();
        }

        List<String> result = new ArrayList<>();
        
        // 先尝试按分隔符拆分
        String[] parts = truckNoStr.split(DELIMITER_PATTERN);
        
        for (String part : parts) {
            if (StringUtils.isBlank(part)) {
                continue;
            }
            
            // 去除空格并转大写
            String cleaned = part.trim().replaceAll("\\s+", "").toUpperCase();
            
            // 检查是否包含多个车牌号（通过识别省份简称）
            List<String> subParts = splitByProvince(cleaned);
            result.addAll(subParts);
        }
        
        return result.stream()
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 通过识别省份简称智能拆分车牌号
     * 例如："川A12345京B67890" -> ["川A12345", "京B67890"]
     *
     * @param str 待拆分的字符串
     * @return 拆分后的车牌号列表
     */
    private static List<String> splitByProvince(String str) {
        List<String> result = new ArrayList<>();
        
        if (StringUtils.isBlank(str)) {
            return result;
        }
        
        int i = 0;
        while (i < str.length()) {
            char c = str.charAt(i);
            
            // 检查是否为省份简称
            if (PROVINCES.indexOf(c) != -1) {
                // 找到省份简称，尝试提取完整车牌号
                String truckNo = extractTruckNo(str, i);
                if (StringUtils.isNotBlank(truckNo)) {
                    result.add(truckNo);
                    i += truckNo.length();
                } else {
                    i++;
                }
            } else {
                i++;
            }
        }
        
        // 如果没有识别到省份简称，说明可能是完整的单个车牌号
        if (result.isEmpty() && StringUtils.isNotBlank(str)) {
            result.add(str);
        }
        
        return result;
    }

    /**
     * 从指定位置提取车牌号
     * 车牌号格式：省份简称(1位) + 字母(1位) + 数字/字母(5-6位)
     *
     * @param str 源字符串
     * @param startIndex 起始位置（省份简称的位置）
     * @return 提取的车牌号，如果格式不正确返回空字符串
     */
    private static String extractTruckNo(String str, int startIndex) {
        // 最短7位（标准车牌），最长8位（新能源车牌）
        int minLength = 7;
        int maxLength = 8;
        
        // 先尝试提取8位（新能源车牌）
        if (startIndex + maxLength <= str.length()) {
            String candidate = str.substring(startIndex, startIndex + maxLength);
            if (isValidTruckNo(candidate)) {
                return candidate;
            }
        }
        
        // 再尝试提取7位（标准车牌）
        if (startIndex + minLength <= str.length()) {
            String candidate = str.substring(startIndex, startIndex + minLength);
            if (isValidTruckNo(candidate)) {
                return candidate;
            }
        }
        
        return "";
    }

    /**
     * 获取车牌号校验失败的原因
     *
     * @param truckNo 车牌号
     * @return 失败原因
     */
    public static String getValidateErrorMsg(String truckNo) {
        if (StringUtils.isBlank(truckNo)) {
            return "车牌号不能为空";
        }

        String formatted = formatTruckNo(truckNo);
        int length = formatted.length();

        if (length < 7) {
            return "车牌号长度不足（标准车牌7位，新能源车牌8位）";
        }

        if (length > 8) {
            return "车牌号长度超出（标准车牌7位，新能源车牌8位）";
        }

        // 检查省份简称
        char province = formatted.charAt(0);
        if (PROVINCES.indexOf(province) == -1) {
            return "省份简称不正确：" + province;
        }

        // 检查第二位是否为字母
        char second = formatted.charAt(1);
        if (!Character.isLetter(second) || !Character.isUpperCase(second)) {
            return "第二位必须为大写字母：" + second;
        }

        // 检查后续位是否为数字或字母
        String suffix = formatted.substring(2);
        if (!suffix.matches("[0-9A-Z]+")) {
            return "车牌号包含非法字符，只能包含数字和大写字母";
        }

        return "车牌号格式不正确";
    }

    /**
     * 提取车牌号中的省份简称
     *
     * @param truckNo 车牌号
     * @return 省份简称
     */
    public static String getProvince(String truckNo) {
        if (StringUtils.isBlank(truckNo)) {
            return "";
        }
        String formatted = formatTruckNo(truckNo);
        return formatted.length() > 0 ? String.valueOf(formatted.charAt(0)) : "";
    }

    /**
     * 提取车牌号中的城市代码（第二位字母）
     *
     * @param truckNo 车牌号
     * @return 城市代码
     */
    public static String getCityCode(String truckNo) {
        if (StringUtils.isBlank(truckNo)) {
            return "";
        }
        String formatted = formatTruckNo(truckNo);
        return formatted.length() > 1 ? String.valueOf(formatted.charAt(1)) : "";
    }
}
