package com.dmw.insure.utils;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author wxx
 */
@Slf4j
public class DownLoadZip {
    public static void downloadAndZipFile(List<String> fileUrls, HttpServletResponse response, String downLoadName) {
        try {
            // 创建临时目录
            //String os = System.getProperty("os.name");
            //if (os != null && os.toLowerCase().startsWith("windows")) {
            Instant now = Instant.now();
            OffsetDateTime odt = OffsetDateTime.ofInstant(now, ZoneId.systemDefault().getRules().getOffset(now));
            String timestamp = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(odt);
            // 构建目录路径(这里以某个固定目录为例,比如用户主目录下的某个文件夹)
            Path baseDir = Paths.get(System.getProperty("user.home"), "/tmp");
            Path tempDirectory = Files.createDirectories(baseDir.resolve("download_files_" + timestamp));

            //Path tempDirectory = Files.createTempDirectory("download_files");
            log.info("创建的临时目录:{}", tempDirectory.toAbsolutePath());
            //} else {
            //    Path parentDir = Paths.get("/download/files");
            //    tempDirectory = Files.createTempDirectory(parentDir, "download_files");
            //    //tempDirectory = Files.createTempDirectory(Paths.get("/tmp"), "download_files");
            //    log.info("linux创建的临时目录:{}",tempDirectory.toAbsolutePath());


            // 下载并保存文件到临时目录
            for (String fileUrl : fileUrls) {
                downloadFile(fileUrl, tempDirectory);
            }
            // 创建zip文件并将下载的文件添加到其中
            createZipFile(tempDirectory, response, downLoadName);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void downloadFile(String fileUrl, Path tempDirectory) throws IOException {
        URL url = new URL(fileUrl);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);
        // 设置您想要的新文件名
        Instant now = Instant.now();
        OffsetDateTime odt = now.atOffset(ZoneId.systemDefault().getRules().getOffset(now));

        // 创建一个DateTimeFormatter来包含毫秒,并确保文件名是安全的
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss.SSS"); // 使用下划线替换冒号

        // 使用formatter来格式化OffsetDateTime
        String formattedDateTime = odt.format(formatter);

        //// 构造目标文件路径
        //Path targetFilePath = Paths.get(tempDirectory.toString(), desiredFileName);
        // 获取文件名  
        String fileName = formattedDateTime+fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
        Path targetFilePath = Paths.get(tempDirectory.toString(), fileName);

        try (InputStream inputStream = urlConnection.getInputStream(); OutputStream outputStream = Files.newOutputStream(targetFilePath)) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
    }

    private static void createZipFile(Path tempDirectory, HttpServletResponse response, String downLoadName) throws IOException {
        // 创建zip包并返回给前台
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(baos);
        Files.walk(tempDirectory).filter(Files::isRegularFile).forEach(filePath -> {
            try {
                addToZipFile(zos, filePath, tempDirectory);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        zos.close();
        byte[] zipBytes = baos.toByteArray();
        baos.close();

        // 设置响应头,将生成的zip包作为流返回给前台
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(downLoadName + LocalDate.now().toString(), StandardCharsets.UTF_8.toString()) + "\"");
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(zipBytes);
        outputStream.flush();
        outputStream.close();
        deleteDirectory(tempDirectory);

    }

    private static void addToZipFile(ZipOutputStream zos, Path filePath, Path tempDirectory) throws IOException {
        // 获取相对路径并创建ZipEntry  
        String relativePath = tempDirectory.relativize(filePath).toString();
        ZipEntry zipEntry = new ZipEntry(relativePath);
        zos.putNextEntry(zipEntry);

        // 将文件内容复制到zip输出流中  
        try (InputStream inputStream = Files.newInputStream(filePath)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                zos.write(buffer, 0, bytesRead);
            }
        } finally {
            zos.closeEntry();
        }
    }

    private static void deleteDirectory(Path directory) throws IOException {
        Files.walk(directory).sorted(Comparator.reverseOrder()) // 删除文件前需要先删除其对应的目录,所以需要倒序排序
                .map(Path::toFile) // 将Path转换为File对象以便可以使用File的delete方法
                .forEach(File::delete); // 删除文件或目录
    }
}