package org.example.Utils;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;

public class PathUtil {
    /**
     * 拼接两个路径片段
     * @param path1 第一个路径
     * @param path2 第二个路径
     * @return 拼接后的路径
     * @throws NullPointerException 若任一参数为 null
     * @throws IllegalArgumentException 若路径包含无效字符
     */
    public static String combine(String path1, String path2) {
        // 校验参数非空
        if (path1 == null) {
            throw new NullPointerException("path1");
        }
        if (path2 == null) {
            throw new NullPointerException("path2");
        }

        // 校验无效字符
        checkInvalidPathChars(path1);
        checkInvalidPathChars(path2);

        // 执行拼接（无校验逻辑，依赖前置校验）
        return combineNoChecks(path1, path2);
    }

    /**
     * 拼接三个路径片段
     * @param path1 第一个路径
     * @param path2 第二个路径
     * @param path3 第三个路径
     * @return 拼接后的路径
     * @throws NullPointerException 若任一参数为 null
     * @throws IllegalArgumentException 若路径包含无效字符
     */
    public static String combine(String path1, String path2, String path3) {
        // 校验参数非空
        if (path1 == null) {
            throw new NullPointerException("path1");
        }
        if (path2 == null) {
            throw new NullPointerException("path2");
        }
        if (path3 == null) {
            throw new NullPointerException("path3");
        }

        // 校验无效字符
        checkInvalidPathChars(path1);
        checkInvalidPathChars(path2);
        checkInvalidPathChars(path3);

        // 嵌套调用双参数拼接
        return combineNoChecks(combineNoChecks(path1, path2), path3);
    }

    /**
     * 拼接四个路径片段
     * @param path1 第一个路径
     * @param path2 第二个路径
     * @param path3 第三个路径
     * @param path4 第四个路径
     * @return 拼接后的路径
     * @throws NullPointerException 若任一参数为 null
     * @throws IllegalArgumentException 若路径包含无效字符
     */
    public static String combine(String path1, String path2, String path3, String path4) {
        // 校验参数非空
        if (path1 == null) {
            throw new NullPointerException("path1");
        }
        if (path2 == null) {
            throw new NullPointerException("path2");
        }
        if (path3 == null) {
            throw new NullPointerException("path3");
        }
        if (path4 == null) {
            throw new NullPointerException("path4");
        }

        // 校验无效字符
        checkInvalidPathChars(path1);
        checkInvalidPathChars(path2);
        checkInvalidPathChars(path3);
        checkInvalidPathChars(path4);

        // 嵌套调用双参数拼接
        return combineNoChecks(combineNoChecks(combineNoChecks(path1, path2), path3), path4);
    }

    /**
     * 无校验的路径拼接（依赖外部前置校验）
     * @param path1 第一个路径
     * @param path2 第二个路径
     * @return 拼接后的路径字符串
     */
    private static String combineNoChecks(String path1, String path2) {
        Path combinedPath = Paths.get(path1, path2);
        return combinedPath.toString();
    }

    /**
     * 检查路径中是否包含无效字符
     * @param path 待检查的路径
     * @throws IllegalArgumentException 若包含无效字符
     */
// 基础无效字符集（根据操作系统动态初始化）
    private static final Set<Character> BASE_INVALID_CHARS;
    // 额外无效字符集（用于严格检查模式）
    private static final Set<Character> ADDITIONAL_INVALID_CHARS;
    // 异常信息（对应C#的本地化资源字符串）
    private static final String INVALID_PATH_CHARS_MSG = "路径中包含无效字符";

    static {
        // 判断当前操作系统类型
        boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");

        // 初始化基础无效字符集
        BASE_INVALID_CHARS = new HashSet<>();

        if (isWindows) {
            // Windows系统基础无效字符：* ? : " < > |
            String winBaseInvalid = "*?:\"<>|";
            for (char c : winBaseInvalid.toCharArray()) {
                BASE_INVALID_CHARS.add(c);
            }
        } else {
            // Unix/Linux/macOS系统基础无效字符：/
            BASE_INVALID_CHARS.add('/');
        }

        // 所有系统都禁止ASCII控制字符（0-31）
        for (char c = 0; c <= 31; c++) {
            BASE_INVALID_CHARS.add(c);
        }

        // 初始化额外无效字符集（主要用于Windows系统）
        ADDITIONAL_INVALID_CHARS = new HashSet<>();
        if (isWindows) {
            // Windows系统额外检查的字符（例如管道符的特殊场景限制）
            ADDITIONAL_INVALID_CHARS.add('|');
        }
    }

    /**
     * 检查路径是否包含无效字符（与C# CheckInvalidPathChars逻辑一致）
     * @param path 待检查的路径
     * @param checkAdditional 是否启用额外检查
     * @throws NullPointerException 如果path为null
     * @throws IllegalArgumentException 如果路径包含无效字符
     */
    public static void checkInvalidPathChars(String path, boolean checkAdditional) {
        // 检查path是否为null
        if (path == null) {
            throw new NullPointerException("path");
        }

        // 检查是否包含非法字符
        if (hasIllegalCharacters(path, checkAdditional)) {
            throw new IllegalArgumentException(INVALID_PATH_CHARS_MSG);
        }
    }

    /**
     * 重载方法，默认不启用额外检查（对应C#的默认参数）
     */
    public static void checkInvalidPathChars(String path) {
        checkInvalidPathChars(path, false);
    }

    /**
     * 判断路径是否包含非法字符（模拟C# PathInternal.HasIllegalCharacters）
     */
    private static boolean hasIllegalCharacters(String path, boolean checkAdditional) {
        for (int i = 0; i < path.length(); i++) {
            char c = path.charAt(i);

            // 检查基础无效字符
            if (BASE_INVALID_CHARS.contains(c)) {
                return true;
            }

            // 检查额外无效字符（如果启用）
            if (checkAdditional && ADDITIONAL_INVALID_CHARS.contains(c)) {
                return true;
            }
        }
        return false;
    }
}
