package com.example.sjkbf.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.json.JSONObject;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;

import java.io.*;
import java.nio.file.*;
import java.util.Arrays;
import java.util.zip.*;

public class SimpleNutZipCompatible {
    
    // 字节级别的加密解密
    public static byte[] encryptDecryptBytes(byte[] data, String key) {
        byte[] result = new byte[data.length];
        byte[] keyBytes = key.getBytes();
        
        for (int i = 0; i < data.length; i++) {
            result[i] = (byte) (data[i] ^ keyBytes[i % keyBytes.length]);
        }
        return result;
    }
    
    public static void main(String[] args) {
        String operation = "encrypt"; // 或 "decrypt"
        String sourcePath = "C:\\Users\\12134\\Desktop\\fsdownload\\DPS_Script";
        String targetPath = "C:\\Users\\12134\\Desktop\\fsdownload\\DPS_Script\\sut.tar.gz";
        String key = "Rindro-Aurora";
        
        if ("encrypt".equals(operation)) {
            // 加密并压缩
            encryptAndZip(sourcePath, targetPath, key);
        } else {
            // 解压并解密
            decryptFromZip(sourcePath, targetPath, key);
        }
    }



    /**
     * 检查文件是否在_Core子目录下
     */
    private static boolean isInRootOrCore(Path filePath, Path sourcePath) {
        Path relativePath = sourcePath.relativize(filePath);
        int nameCount = relativePath.getNameCount();

        // _Core子目录下的文件（相对路径的第一个目录是_Core）
        if (nameCount >= 2 && "_Core".equals(relativePath.getName(0).toString())) {
            return true;
        }

        return false;
    }


    public static void encryptAndZip(String folderPath, String zipPath, String key) {

        // 随机生成密钥
        byte[] keyBytes = {92, -2, -65, 10, 118, 103, -68, 72, -23, 124, -103, -39, 0, -128, 31, -107};


        System.out.println("密钥: " + Arrays.toString(keyBytes));

        // 构建
        AES aes = SecureUtil.aes(keyBytes);


        Path tempDir = null;
        try {
            // 创建临时目录
            tempDir = Files.createTempDirectory("nut_encrypt");
            Path sourcePath = Paths.get(folderPath);
            
            // 加密所有.nut文件到临时目录
            Path finalTempDir = tempDir;
            Files.walk(sourcePath)
                .filter(Files::isRegularFile)
                .filter(path -> (path.toString().toLowerCase().endsWith(".nut")))
                .filter(path -> isInRootOrCore(path, sourcePath))
                .forEach(nutFile -> {
                    try {
                        byte[] content = Files.readAllBytes(nutFile);
                        byte[] encrypted = aes.encrypt(content);
                        
                        Path relative = sourcePath.relativize(nutFile);
                        Path tempFile = finalTempDir.resolve(relative);
                        
                        String newName = tempFile.getFileName().toString().replace(".nut", ".nut");
                        Path sutFile = tempFile.getParent().resolve(newName);
                        
                        Files.createDirectories(sutFile.getParent());
                        Files.write(sutFile, encrypted);
                        
                        System.out.println("加密: " + relative);
                    } catch (Exception e) {
                        System.err.println("错误: " + nutFile + " - " + e.getMessage());
                    }
                });


            FileReader fileReader = new FileReader(folderPath + "/FileConfig.json");
            String result5 = fileReader.readString();
            //转json
            JSONObject jsonObject = new JSONObject(result5);

            jsonObject.remove("ProjectScript");


            String string = tempDir.toAbsolutePath()+"/FileConfig.json";
            FileUtil.writeString(jsonObject.toString(),string, "utf-8");



            // 压缩临时目录
            zipFolderToTarGz(tempDir.toString(), zipPath);
            System.out.println("压缩完成: " + zipPath);
            
        } catch (Exception e) {
            System.err.println("加密压缩失败: " + e.getMessage());
        } finally {
            if (tempDir != null) {
                deleteDirectory(tempDir.toFile());
            }
        }
    }
    
    public static void decryptFromZip(String zipPath, String outputFolder, String key) {
        try {
            Path outputPath = Paths.get(outputFolder);
            Files.createDirectories(outputPath);
            
            try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath))) {
                ZipEntry entry;
                byte[] buffer = new byte[1024];
                
                while ((entry = zis.getNextEntry()) != null) {
                    if (!entry.isDirectory() && entry.getName().toLowerCase().endsWith(".sut")) {
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            baos.write(buffer, 0, len);
                        }
                        
                        byte[] encrypted = baos.toByteArray();
                        byte[] decrypted = encryptDecryptBytes(encrypted, key);
                        
                        Path outputFile = outputPath.resolve(entry.getName());
                        String newName = outputFile.getFileName().toString().replace(".sut", ".nut");
                        Path nutFile = outputFile.getParent().resolve(newName);
                        
                        Files.createDirectories(nutFile.getParent());
                        Files.write(nutFile, decrypted);
                        
                        System.out.println("解密: " + entry.getName());
                    }
                    zis.closeEntry();
                }
            }
            
            System.out.println("解密完成: " + outputFolder);
            
        } catch (Exception e) {
            System.err.println("解压解密失败: " + e.getMessage());
        }
    }
    
    private static void zipFolder(String srcFolder, String zipPath) {
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipPath))) {
            File folder = new File(srcFolder);
            zipDirectory(folder, zos, "");
        } catch (IOException e) {
            System.err.println("压缩错误: " + e.getMessage());
        }
    }
    
    private static void zipDirectory(File folder, ZipOutputStream zos, String parentPath) throws IOException {
        for (File file : folder.listFiles()) {
            if (file.isDirectory()) {
                zipDirectory(file, zos, parentPath + file.getName() + "/");
            } else {
                try (FileInputStream fis = new FileInputStream(file)) {
                    zos.putNextEntry(new ZipEntry(parentPath + file.getName()));
                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = fis.read(buffer)) > 0) {
                        zos.write(buffer, 0, length);
                    }
                    zos.closeEntry();
                }
            }
        }
    }


    /**
     * 将文件夹压缩为 tar.gz 格式
     */
    private static void zipFolderToTarGz(String sourceFolder, String tarGzPath) throws IOException {
        Path sourcePath = Paths.get(sourceFolder);

        try (FileOutputStream fos = new FileOutputStream(tarGzPath);
             BufferedOutputStream bos = new BufferedOutputStream(fos);
             GZIPOutputStream gos = new GZIPOutputStream(bos);
             TarArchiveOutputStream tos = new TarArchiveOutputStream(gos)) {

            // 设置tar格式
            tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);

            Files.walk(sourcePath)
                    .filter(Files::isRegularFile)
                    .forEach(file -> {
                        try {
                            // 获取相对路径
                            Path relativePath = sourcePath.relativize(file);

                            // 创建tar条目
                            TarArchiveEntry entry = new TarArchiveEntry(file.toFile(), relativePath.toString().replace("\\", "/"));
                            tos.putArchiveEntry(entry);

                            // 写入文件内容
                            Files.copy(file, tos);

                            tos.closeArchiveEntry();
//                            System.out.println("添加到tar.gz: " + relativePath);

                        } catch (IOException e) {
                            System.err.println("添加文件到tar.gz失败: " + file + " - " + e.getMessage());
                        }
                    });

            tos.finish();
        }
    }
    
    private static void deleteDirectory(File dir) {
        if (dir.isDirectory()) {
            for (File file : dir.listFiles()) {
                deleteDirectory(file);
            }
        }
        dir.delete();
    }
}