package com.sunxung.factoring.component.util;

import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.service.sys.FileStorageService;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.UUID;

@ConfigurationProperties(prefix = "upload")
@Component
/** 文件辅助工具类 */
public class FileUtil {

    /**
     * 存储磁盘
     */
    private static String DISK;
    /**
     * 所有文件存储目录
     */
    public static String DIR = "fileResource";
    /**
     * classPath路径
     */
    private static String CLASS_PATH;
    /**
     * 资源绝对存储路径
     */
    private static String ABSOLUTE_PATH;
    /**
     * 文件存储service
     */
    private static FileStorageService fileStorageService;

    /**
     * 获取文件存储service示例
     */
    private static FileStorageService getFileStorageService() {
        if (fileStorageService == null) {
            fileStorageService = SpringUtil.getBeanByType(FileStorageService.class);
        }
        return fileStorageService;
    }

    /**
     * 资源获取资源路径
     */
    public static String getClassPath() {
        if (StringUtil.isEmpty(CLASS_PATH)) {
            CLASS_PATH = FileUtil.class.getResource("/").getPath();
        }
        return CLASS_PATH;
    }

    /**
     * 上传文件
     */
    public static List<FileStorage> uploadFile(HttpServletRequest request, FileModuleDict.ChildEnum moduleType)
            throws IllegalStateException, IOException {
        if (request instanceof MultipartHttpServletRequest) {
            return getFileStorageService().add((MultipartHttpServletRequest) request, moduleType);
        }
        return null;
    }

    /**
     * 获取文件后缀
     */
    public static String getSuffix(String name) {
        if (!StringUtil.isEmpty(name) && name.indexOf(".") > 0) {
            return name.substring(name.lastIndexOf("."));
        } else {
            return "";
        }
    }

    /**
     * 获取资源绝对存储目录
     */
    public static String getAbsoluteDir() {
        if (StringUtil.isEmpty(ABSOLUTE_PATH)) {
            File file = new File(DISK);
            if (!file.exists()) {
                file.mkdirs();
            }
            ABSOLUTE_PATH = file.getAbsolutePath();
        }
        return ABSOLUTE_PATH;
    }

    /**
     * 随机生成文件名称
     */
    public static String randomFileName() {
        return UUID.randomUUID().toString();
    }

    /**
     * 获取以日期格式的文件路径
     */
    public static String getDatePath() {
        return "/";
    }

    /**
     * 获取文件路径
     *
     * @param fileName   文件名称
     * @param suffix     文件后缀
     * @param moduleType 文件所属模块枚举实例
     * @return
     */
    public static String getFilePath(String fileName, String suffix, FileModuleDict.ChildEnum moduleType) {
        StringBuilder sb = new StringBuilder("/");
        sb.append(DIR).append("/").append(moduleType.getCode());
        sb.append(getDatePath()).append(fileName).append(suffix);
        return sb.toString();
    }

    /**
     * 获取文件路径
     *
     * @param fileName   文件名称
     * @param suffix     文件后缀
     * @param moduleName 文件所属模块枚举实例
     * @return
     */
    public static String getFilePath(String fileName, String suffix, String moduleName) {
        StringBuilder sb = new StringBuilder("/");
        sb.append(DIR).append("/").append(moduleName);
        sb.append(getDatePath()).append(fileName).append(suffix);
        return sb.toString();
    }

    /**
     * 获取资源绝对存储路径
     *
     * @param fileName   文件名称
     * @param suffix     文件后缀
     * @param moduleType 文件所属模块枚举实例
     * @return
     */
    public static String getAbsolutePath(String fileName, String suffix, FileModuleDict.ChildEnum moduleType) {
        return getAbsoluteDir() + getFilePath(fileName, suffix, moduleType);
    }

    /**
     * 获取资源绝对存储路径
     *
     * @param fileName   文件名称
     * @param suffix     文件后缀
     * @param moduleName 文件所属模块枚举实例
     * @return
     */
    public static String getAbsolutePath(String fileName, String suffix, String moduleName) {
        return getAbsoluteDir() + getFilePath(fileName, suffix, moduleName);
    }

    /**
     * spring注入存储配置
     */
    public static void setDisk(String disk) {
        if (StringUtil.isEmpty(FileUtil.DISK)) {
            FileUtil.DISK = disk;
        }
    }

    /**
     * 在工程的目录下创建需要在线预览生成的文件夹
     **/
    public static String getFileOnlinePreviewPath() {
        String newPath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "main"
                + File.separator + "resources" + File.separator + "static" + File.separator + "uploadFile";
        File directoryFile = new File(newPath);
        if (!(directoryFile.exists() && directoryFile.isDirectory())) {
            directoryFile.mkdirs();
        }
        return newPath;
    }

    /**
     * 获取工程目录下的，excel的模版文件的路径
     **/
    public static String getDataTemplateFilePath() {
        String newPath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "main"
                + File.separator + "resources" + File.separator + "static" + File.separator + "dataTemplates"
                + File.separator;
        return newPath;
    }

    /***
     *  上传单个文件
     *
     * @param request
     * @param moduleType
     * @return
     * @throws IllegalStateException
     * @throws IOException String
     */
    public static String uploadSingleFile(HttpServletRequest request, FileModuleDict.ChildEnum moduleType)
            throws IllegalStateException, IOException {
        if (request instanceof MultipartHttpServletRequest) {
            return getFileStorageService().getFilePath((MultipartHttpServletRequest) request, moduleType);
        }
        return "";
    }

    /**
     * 根据网络URL下载文件
     *
     * @param fileUrl
     * @param fileLocal
     * @return
     * @throws Exception
     */
    public static boolean downloadFile(String fileUrl, String fileLocal) throws Exception {
        boolean flag = false;
        URL url = new URL(fileUrl);
        HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
        urlCon.setConnectTimeout(15000);
        urlCon.setReadTimeout(15000);
        int code = urlCon.getResponseCode();
        if (code != HttpURLConnection.HTTP_OK) {
            throw new Exception("文件读取失败");
        }
        //读文件流
        DataInputStream in = new DataInputStream(urlCon.getInputStream());
        DataOutputStream out = new DataOutputStream(new FileOutputStream(fileLocal));
        byte[] buffer = new byte[2048];
        int count = 0;
        while ((count = in.read(buffer)) > 0) {
            out.write(buffer, 0, count);
        }
        try {
            if (out != null) {
                out.close();
            }
            if (in != null) {
                in.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        flag = true;
        return flag;
    }

    public static void downloadPdfFile(HttpServletResponse response, File file) {
        OutputStream out = null;
        BufferedInputStream inputStream = null;
        try {
            response.setHeader("Content-Type", "application/vnd.ms-exce");
            response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(file.getName(), "UTF-8"));
            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
            out = response.getOutputStream();
            inputStream = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            while ((inputStream.read(buffer)) > 0) {
                out.write(buffer);
                out.flush();
            }

        } catch (Exception e) {
            throw new BusinessException(CodeUtil.FAIL, "下载失败!");
        } finally {
            try {
                inputStream.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
