package com.crm.rely.backend.util;

import com.crm.rely.backend.exception.ServiceException;
import com.google.common.base.Strings;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

/**
 * 文件处理工具类
 */
public class FileProcessUtil {
    private static String encoding = "UTF-8";
    private static DeleteDirectory walk;
    private static EnumSet opts;

    static {
        walk = new DeleteDirectory();
        opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
    }

    /**
     * 普通文件上传
     * 1.获取文件扩展名
     * 2.生成新文件名(UUID)
     * 3.检测是否存在目录
     * 4.保存文件
     * 5.返回新文件相对路径
     *
     * @param file     文件
     * @param savePath 保存路径
     * @return 保存后的相对路径
     */
    public static String upload(MultipartFile file, String savePath) {

        return upload(file, false, savePath);
    }

    public static String upload(MultipartFile file, boolean isSaveFileName, String savePath) {

        /**
         * 获取文件名
         */
        String fileName = file.getOriginalFilename();

        fileName = getFileName(fileName, isSaveFileName);

        try {
            return upload(file.getBytes(), fileName, savePath);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "/" + fileName;
    }

    public static String upload(String fileName, InputStream inputStream, String savePath) {

        return upload(fileName, false, inputStream, savePath);
    }

    public static String upload(String fileName, boolean isSaveFileName, InputStream inputStream, String savePath) {


        fileName = getFileName(fileName, isSaveFileName);


        try {
            return upload(readAllBytes(inputStream), fileName, savePath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static String upload(byte[] bytes, String fileName, String savePath) {
        savePath += "/" + fileName;
        try {
            Path path = getPath(savePath);
            Files.createDirectories(path.getParent());
            Files.createFile(path);
            Files.write(path, bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "/" + fileName;
    }

    public static byte[] readAllBytes(InputStream inputStream) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        byte[] temp = new byte[1024]; // 每次读取的缓冲区大小
        int bytesRead;
        while ((bytesRead = inputStream.read(temp)) != -1) {
            buffer.write(temp, 0, bytesRead);
        }
        return buffer.toByteArray();
    }

    private static String getFileName(String fileName, boolean isSaveFileName) {
        if (isSaveFileName) {
            fileName = fileName.substring(0, fileName.lastIndexOf("."));
        } else {
            /**
             * 获取文件的后缀名
             */
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            fileName = UUIDUtil.getUUID() + suffixName;
        }
        return fileName;
    }

    /**
     * 删除空目录
     *
     * @param path 将要删除的目录路径
     */
    public static void deleteFile(String path) throws Exception {
        if (Strings.isNullOrEmpty(path) || Strings.isNullOrEmpty(path.trim())) {
            return;
        }
        Path directory = getPath(path);

        deleteFile(directory);
    }

    /**
     * 批量删除文件
     *
     * @param paths
     * @throws Exception
     */
    public static void deleteFiles(List<String> paths) throws Exception {
        for (String path : paths) {

            deleteFile(path);
        }
    }

    /**
     * 删除文件
     *
     * @param path
     * @throws Exception
     */
    public static void deleteFile(Path path) throws Exception {

        Files.walkFileTree(path, opts, Integer.MAX_VALUE, walk);
    }

    /**
     * 文件移动
     *
     * @param sourcePath
     * @param destPath
     * @throws Exception
     */
    public static void move(String sourcePath, String destPath) throws Exception {

        Path source = getPath(sourcePath);

        Path dest = getPath(destPath);
        Files.createDirectories(dest.getParent());
        move(source, dest);

    }

    /**
     * 文件移动
     *
     * @param source
     * @param dest
     * @throws Exception
     */
    public static void move(Path source, Path dest) throws Exception {

        Files.move(source, dest, REPLACE_EXISTING, ATOMIC_MOVE);

    }

    /**
     * 读取文件内容
     *
     * @param filePathName
     * @return
     */
    public static String getFileContent(String filePathName) {

        try {
            Path path = getPath(filePathName);
            byte[] filecontent = Files.readAllBytes(path);
            String content = new String(filecontent, encoding);
            return content;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException("文件读取失败");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过相对或绝对路径获取path真实路径
     *
     * @param savePath
     * @return
     * @throws IOException
     */
    public static Path getPath(String savePath) throws IOException {
        Path path = null;
        if (savePath.startsWith("./") || savePath.startsWith("../")) {

            File rootFile = new File("");
            File file = new File(rootFile.getAbsolutePath(), savePath);
            path = Paths.get(file.getCanonicalPath()).normalize();

        } else {
            path = Paths.get(savePath).normalize();
        }

        return path;
    }

    public static File getFile(String savePath) throws IOException {
        
        return getPath(savePath).toFile();
    }

    public static File getFile(Path path) {

        return path.toFile();
    }

    /**
     * 获取文件内容并替换
     *
     * @param filePathName 文件路径及名称
     * @param map          替换内容
     * @return
     */
    public static String getFileContentAndReplace(String filePathName, Map<String, String> map) {
        String content = getFileContent(filePathName);

        return TemplateUtil.replace(content, map);
    }

    /**
     * 生成导出文件名
     *
     * @param namePrefix 名称前缀
     * @return
     * @throws Exception
     */
    public static String genExportFileName(String namePrefix) {
        StringBuffer stringBuffer = new StringBuffer();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        stringBuffer.append(namePrefix == null ? "IB_EXPORT" : namePrefix);
        stringBuffer.append("_");
        stringBuffer.append(sdf.format(new Date()));
        stringBuffer.append(".xlsx");
        String fileName = stringBuffer.toString();
        return fileName;
    }

    /**
     * 压缩文件
     *
     * @param inputPath     来源文件的绝对路径
     * @param files         需要压缩的文件名列表
     * @param zipOutputPath 压缩后文件的绝对路径及名称
     * @throws Exception
     */
    public static void zipFiles(String inputPath, List<String> files, String zipOutputPath) throws Exception {

        try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipOutputPath))) {
            for (String file : files) {
                // 创建ZipEntry对象并设置文件名
                ZipEntry entry = new ZipEntry(file);
                zipOutputStream.putNextEntry(entry);

                // 读取文件内容并写入Zip文件
                try (FileInputStream fileInputStream = new FileInputStream(inputPath + File.separator + file)) {
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                        zipOutputStream.write(buffer, 0, bytesRead);
                    }
                }

                // 完成当前文件的压缩
                zipOutputStream.closeEntry();
            }

        } catch (Exception e) {
            throw ServiceException.exception(e.getMessage());
        }

    }

    public static void main(String[] args) throws Exception {
//        List<String> paths = new ArrayList<String>();
//        paths.add("./upload/3/12/image - 副本 - 副本/");
//        paths.add("./upload/3/12/image - 副本/");
//        deleteFiles(paths);
////        move("./upload/3/9/image/", "./upload/3/12/image/");

//        Path path1 = getPath("../upload/abc.jpg");
//        byte[] bytes = Files.readAllBytes(path1);
//        String str = "F:\\iemans-backend\\target\\classes\\upload\\1\\2f5aa03113a84d239f532b80fb4077e3.png";
//        Path path = getPath(str);
//
//        Files.createDirectories(path.getParent());
//        Files.createFile(path);
//        Files.write(path, bytes);

//        System.out.println(getFileContent("../123123.txt"));
        deleteFile("G:\\crm\\crm-back\\IP2LOCATION\\download\\202206");

    }


}
