package com.qmth.paper.library.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.paper.library.business.bean.vo.FilePathVo;
import com.qmth.paper.library.business.service.FileUploadService;
import com.qmth.paper.library.common.contant.SysSettingConstant;
import com.qmth.paper.library.common.contant.SystemConstant;
import com.qmth.paper.library.common.enums.ExceptionResultEnum;
import com.qmth.paper.library.common.enums.UploadFileEnum;
import com.qmth.paper.library.common.service.CommonCacheService;
import com.qmth.paper.library.common.util.FileStoreUtil;
import com.qmth.paper.library.common.util.ResultUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.nio.file.Files;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * 文件上传服务类
 */
@Service
public class FileUploadServiceImpl implements FileUploadService {
    private static final Logger log = LoggerFactory.getLogger(FileUploadServiceImpl.class);

    @Resource
    FileStoreUtil fileStoreUtil;
    @Resource
    CommonCacheService commonCacheService;

    /**
     * 上传文件
     *
     * @param sourceFile     上传文件
     * @param uploadFileEnum 文件类型
     * @param fileName       文件名称
     */
    @Override
    public FilePathVo uploadFile(File sourceFile, UploadFileEnum uploadFileEnum, String fileName) {
        try {
            String rootPath = fileStoreUtil.buildPath(UploadFileEnum.FILE, true);
            String dirName = rootPath + File.separator + fileName;
            String md5 = DigestUtils.md5Hex(new FileInputStream(sourceFile));
            fileStoreUtil.fileUpload(dirName, new FileInputStream(sourceFile), md5);
            String type = fileStoreUtil.isOssStore() ? SystemConstant.OSS : SystemConstant.LOCAL;
            return new FilePathVo(dirName, uploadFileEnum, type, md5);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return null;
    }

    /**
     * @param file
     * @param filePathName
     * @param uploadFileEnum
     * @return
     */
    @Override
    public FilePathVo uploadFile(MultipartFile file, UploadFileEnum uploadFileEnum, String filePathName) {
        try {
            String md5 = DigestUtils.md5Hex(file.getInputStream());
            fileStoreUtil.fileUpload(filePathName, file.getInputStream(), md5);
            String type = fileStoreUtil.isOssStore() ? SystemConstant.OSS : SystemConstant.LOCAL;
            return new FilePathVo(filePathName, uploadFileEnum, type, md5);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return null;
    }

    @Override
    public FilePathVo uploadRotateFile(File file, UploadFileEnum uploadFileEnum, String filePathName) {
        try {
            String md5 = DigestUtils.md5Hex(Files.newInputStream(file.toPath()));
            fileStoreUtil.fileUpload(filePathName, new FileInputStream(file), md5);
            String type = fileStoreUtil.isOssStore() ? SystemConstant.OSS : SystemConstant.LOCAL;
            return new FilePathVo(filePathName, uploadFileEnum, type, md5);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return null;
    }

    /**
     * 获取附件文件
     *
     * @param path         文件路径json
     * @param filePathName 保存本地文件名
     * @return string
     */
    @Override
    public File downloadFile(String path, String filePathName) {
        FilePathVo filePathVo = JSON.parseObject(path, FilePathVo.class);
        File localFile = new File(filePathName);
        if (filePathVo.getType().equals(SystemConstant.OSS)) {
            try {
                return fileStoreUtil.fileDownload(filePathVo.getPath(), localFile.getPath());
            } catch (Exception e) {
                throw ExceptionResultEnum.ERROR.exception("从OSS上下载文件失败");
            }
        } else {
            File file = new File(filePathVo.getPath());
            if (!file.exists()) {
                throw ExceptionResultEnum.ERROR.exception("本地文件不存在");
            }
            try {
                if (!localFile.exists()) {
                    localFile.getParentFile().mkdirs(); //目标文件目录不存在的话需要创建目录
                }
                FileUtils.copyFile(file, localFile);
                return localFile;
            } catch (IOException e) {
                throw ExceptionResultEnum.ERROR.exception("本地复制文件失败");
            }
        }
    }

    @Override
    public InputStream downloadInputStream(String path, String ossType) {
        InputStream inputStream;
        try {
            if (Objects.equals(ossType, SystemConstant.OSS)) {
                inputStream = fileStoreUtil.ossDownloadIs(path);
            } else {
                inputStream = Files.newInputStream(new File(path).toPath());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return inputStream;
    }

    @Override
    public boolean copy(String sourcePath, String destPath) {
        if (StringUtils.isNotBlank(sourcePath) && StringUtils.isNotBlank(destPath)) {
            return fileStoreUtil.copy(sourcePath, destPath);
        } else {
            return false;
        }
    }

    /**
     * 预览文件
     *
     * @param path 文件路径
     */
    @Override
    public String filePreview(String path) {
        if (StringUtils.isBlank(path)) {
            return null;
        }
        FilePathVo filePathVo = JSON.parseObject(path, FilePathVo.class);
        return filePreview(filePathVo);
    }

    @Override
    public String filePreview(FilePathVo filePathVo) {
        String pathUrl;
        String path = filePathVo.getPath();
        // 本地文件
        if (Objects.equals(filePathVo.getType(), SystemConstant.LOCAL)) {

            String hostUrl = commonCacheService.getSysSettingGlobal().get(SysSettingConstant.SYS_FILE_HOST_URL);
            path = SystemConstant.getLocalFilePath(hostUrl, path);
            if (path.startsWith("/")) {
                pathUrl = hostUrl + path;
            } else {
                pathUrl = hostUrl + File.separator + path;
            }
        } else {
            pathUrl = fileStoreUtil.getFileUrl(path);

        }
        return pathUrl;
    }

    @Override
    public boolean deleteFile(String path) {
        return fileStoreUtil.deleteFile(path);
    }

}
