package org.jeecg.modules.stm.utils;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.Set;

/**
 * 目录工具类 - 提供目录检查、创建、管理等功能
 * @author System
 * @version 1.0
 */
public class DirectoryUtil {

    /**
     * 私有构造方法，防止实例化
     */
    private DirectoryUtil() {
        throw new IllegalStateException("工具类，无需实例化");
    }

    // 系统属性常量
    private static final String OS_NAME = System.getProperty("os.name").toLowerCase();
    private static final boolean IS_WINDOWS = OS_NAME.contains("win");
    private static final String TEMP_DIR = System.getProperty("java.io.tmpdir");
    private static final String USER_HOME = System.getProperty("user.home");

    /**
     * 检查目录是否存在，不存在则创建（基础方法）
     * @param directoryPath 目录路径
     * @return 如果目录存在或创建成功返回true，否则返回false
     */
    public static boolean ensureDirectoryExists(String directoryPath) {
        if (directoryPath == null || directoryPath.trim().isEmpty()) {
            System.err.println("[DirectoryUtil] 目录路径为空！");
            return false;
        }

        try {
            // 规范化路径
            String normalizedPath = normalizePath(directoryPath);

            // 创建File对象
            File directory = new File(normalizedPath);

            // 检查是否是文件而不是目录
            if (directory.exists() && !directory.isDirectory()) {
                System.err.println("[DirectoryUtil] 路径已存在但不是目录：" + normalizedPath);
                return false;
            }

            // 如果目录不存在，尝试创建
            if (!directory.exists()) {
                System.out.println("[DirectoryUtil] 目录不存在，尝试创建：" + normalizedPath);

                // 使用mkdirs()创建所有不存在的父目录
                boolean created = directory.mkdirs();

                if (created) {
                    System.out.println("[DirectoryUtil] 目录创建成功：" + normalizedPath);

                    // 设置目录权限（非Windows系统）
                    if (!IS_WINDOWS) {
                        setDirectoryPermissions(Paths.get(normalizedPath));
                    }

                    return true;
                } else {
                    System.err.println("[DirectoryUtil] 目录创建失败：" + normalizedPath);
                    return false;
                }
            } else {
                // 目录已存在
                System.out.println("[DirectoryUtil] 目录已存在：" + normalizedPath);
                return true;
            }

        } catch (SecurityException e) {
            System.err.println("[DirectoryUtil] 安全异常：没有创建目录的权限 - " + directoryPath);
            e.printStackTrace();
            return false;
        } catch (Exception e) {
            System.err.println("[DirectoryUtil] 创建目录时发生异常：" + directoryPath);
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 检查文件所在的目录是否存在，不存在则创建
     * @param filePath 文件完整路径
     * @return 如果目录存在或创建成功返回true，否则返回false
     */
    public static boolean ensureFileDirectoryExists(String filePath) {
        if (filePath == null || filePath.trim().isEmpty()) {
            System.err.println("[DirectoryUtil] 文件路径为空！");
            return false;
        }

        try {
            File file = new File(filePath);
            File parentDir = file.getParentFile();

            if (parentDir == null) {
                System.err.println("[DirectoryUtil] 无法获取文件的父目录：" + filePath);
                return false;
            }

            return ensureDirectoryExists(parentDir.getAbsolutePath());

        } catch (Exception e) {
            System.err.println("[DirectoryUtil] 检查文件目录时发生异常：" + filePath);
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 创建目录（使用NIO API，支持更好的错误处理）
     * @param path 目录路径
     * @return 如果目录存在或创建成功返回true，否则返回false
     */
    public static boolean createDirectory(String path) {
        if (path == null || path.trim().isEmpty()) {
            return false;
        }

        try {
            // 规范化路径
            String normalizedPath = normalizePath(path);
            Path dirPath = Paths.get(normalizedPath);

            // 如果目录已存在，直接返回true
            if (Files.exists(dirPath)) {
                if (Files.isDirectory(dirPath)) {
                    return true;
                } else {
                    System.err.println("[DirectoryUtil] 路径已存在但不是目录：" + normalizedPath);
                    return false;
                }
            }

            // 创建目录（包含所有父目录）
            Files.createDirectories(dirPath);

            // 在非Windows系统上设置目录权限
            if (!IS_WINDOWS) {
                setDirectoryPermissions(dirPath);
            }

            System.out.println("[DirectoryUtil] 目录创建成功：" + dirPath.toAbsolutePath());
            return true;

        } catch (Exception e) {
            System.err.println("[DirectoryUtil] 创建目录失败：" + path + " - " + e.getMessage());
            return false;
        }
    }

    /**
     * 设置目录权限（Unix/Linux系统）
     * @param path 目录路径
     * @throws Exception 设置权限异常
     */
    private static void setDirectoryPermissions(Path path) throws Exception {
        if (IS_WINDOWS) {
            return; // Windows系统不需要设置POSIX权限
        }

        Set<PosixFilePermission> perms = new HashSet<>();
        // 所有者权限
        perms.add(PosixFilePermission.OWNER_READ);
        perms.add(PosixFilePermission.OWNER_WRITE);
        perms.add(PosixFilePermission.OWNER_EXECUTE);
        // 组权限
        perms.add(PosixFilePermission.GROUP_READ);
        perms.add(PosixFilePermission.GROUP_EXECUTE);
        // 其他用户权限
        perms.add(PosixFilePermission.OTHERS_READ);
        perms.add(PosixFilePermission.OTHERS_EXECUTE);

        Files.setPosixFilePermissions(path, perms);
    }

    /**
     * 规范化路径（处理不同操作系统的路径分隔符）
     * @param path 原始路径
     * @return 规范化后的路径
     */
    public static String normalizePath(String path) {
        if (path == null) {
            return "";
        }

        String normalized = path.trim();

        // 统一使用正斜杠
        normalized = normalized.replace("\\", "/");

        // 移除多余的分隔符
        normalized = normalized.replaceAll("/+", "/");

        return normalized;
    }

    /**
     * 获取有效的目录路径（确保以分隔符结尾）
     * @param path 目录路径
     * @return 有效的目录路径
     */
    public static String getValidDirectoryPath(String path) {
        if (path == null || path.trim().isEmpty()) {
            return "";
        }

        String normalized = normalizePath(path);

        // 确保以分隔符结尾
        if (!normalized.endsWith("/")) {
            normalized += "/";
        }

        return normalized;
    }

    /**
     * 清理目录名称中的非法字符
     * @param name 目录名称
     * @return 清理后的目录名称
     */
    public static String sanitizeDirectoryName(String name) {
        if (name == null) {
            return "";
        }

        // 移除Windows和Unix中的非法字符
        String sanitized = name.replaceAll("[\\\\/:*?\"<>|]", "_");

        // 移除首尾空格和点号
        sanitized = sanitized.trim();
        while (sanitized.endsWith(".")) {
            sanitized = sanitized.substring(0, sanitized.length() - 1);
        }

        return sanitized;
    }

    /**
     * 获取临时目录路径
     * @return 临时目录路径
     */
    public static String getTempDirectory() {
        return getValidDirectoryPath(TEMP_DIR);
    }

    /**
     * 获取用户主目录路径
     * @return 用户主目录路径
     */
    public static String getUserHomeDirectory() {
        return getValidDirectoryPath(USER_HOME);
    }

    /**
     * 检查并创建多个目录
     * @param paths 目录路径数组
     * @return 所有目录都创建成功返回true，否则返回false
     */
    public static boolean ensureDirectoriesExist(String... paths) {
        boolean allSuccess = true;
        for (String path : paths) {
            if (!ensureDirectoryExists(path)) {
                allSuccess = false;
                System.err.println("[DirectoryUtil] 目录创建失败：" + path);
            }
        }
        return allSuccess;
    }

    /**
     * 检查目录是否可写
     * @param directoryPath 目录路径
     * @return 如果目录可写返回true，否则返回false
     */
    public static boolean isDirectoryWritable(String directoryPath) {
        if (directoryPath == null || directoryPath.trim().isEmpty()) {
            return false;
        }

        try {
            File dir = new File(normalizePath(directoryPath));

            if (!dir.exists() || !dir.isDirectory()) {
                return false;
            }

            // 创建一个临时文件测试写入权限
            File testFile = new File(dir, ".write_test_" + System.currentTimeMillis());

            if (testFile.createNewFile()) {
                testFile.delete();
                return true;
            }

            return false;

        } catch (Exception e) {
            System.err.println("[DirectoryUtil] 检查目录可写性时发生异常：" + directoryPath);
            return false;
        }
    }

    /**
     * 获取目录大小（递归计算）
     * @param directoryPath 目录路径
     * @return 目录大小（字节）
     */
    public static long getDirectorySize(String directoryPath) {
        long size = 0;

        try {
            File dir = new File(normalizePath(directoryPath));

            if (!dir.exists() || !dir.isDirectory()) {
                return 0;
            }

            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isFile()) {
                        size += file.length();
                    } else if (file.isDirectory()) {
                        size += getDirectorySize(file.getAbsolutePath());
                    }
                }
            }

        } catch (SecurityException e) {
            System.err.println("[DirectoryUtil] 没有访问目录的权限：" + directoryPath);
        } catch (Exception e) {
            System.err.println("[DirectoryUtil] 计算目录大小时发生异常：" + directoryPath);
        }

        return size;
    }

    /**
     * 格式化目录大小
     * @param size 字节数
     * @return 格式化后的字符串
     */
    public static String formatSize(long size) {
        if (size < 1024) {
            return size + " B";
        } else if (size < 1024 * 1024) {
            return String.format("%.2f KB", size / 1024.0);
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", size / (1024.0 * 1024));
        } else {
            return String.format("%.2f GB", size / (1024.0 * 1024 * 1024));
        }
    }

    /**
     * 检查目录是否为空
     * @param directoryPath 目录路径
     * @return 如果目录为空或不存在返回true，否则返回false
     */
    public static boolean isDirectoryEmpty(String directoryPath) {
        try {
            File dir = new File(normalizePath(directoryPath));

            if (!dir.exists() || !dir.isDirectory()) {
                return true;
            }

            String[] files = dir.list();
            return files == null || files.length == 0;

        } catch (SecurityException e) {
            System.err.println("[DirectoryUtil] 没有访问目录的权限：" + directoryPath);
            return true;
        } catch (Exception e) {
            System.err.println("[DirectoryUtil] 检查目录是否为空时发生异常：" + directoryPath);
            return true;
        }
    }
}