package com.qmth.teachcloud.common.service.impl;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicAttachment;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.UploadFileEnum;
import com.qmth.teachcloud.common.service.AttachmentCommonService;
import com.qmth.teachcloud.common.util.ConvertUtil;
import com.qmth.teachcloud.common.util.FileStoreUtil;
import com.qmth.teachcloud.common.util.Zip4jUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 试卷、题卡下载、预览等操作公共服务service impl
 */
@Service
public class AttachmentCommonServiceImpl implements AttachmentCommonService {
    private final static Logger log = LoggerFactory.getLogger(AttachmentCommonServiceImpl.class);

    @Resource
    DictionaryConfig dictionaryConfig;

    @Resource
    FileStoreUtil fileStoreUtil;

    @Override
    public File downloadFile(String rootPath, String fileName, BasicAttachment basicAttachment) throws Exception {
        Optional.ofNullable(basicAttachment).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("附件信息不存在"));

        JSONObject object = JSONObject.parseObject(basicAttachment.getPath());
        String filePath = object.getString(SystemConstant.PATH);
        String type = object.getString(SystemConstant.TYPE);
        UploadFileEnum uploadType = Enum.valueOf(UploadFileEnum.class, (String) object.get(SystemConstant.UPLOAD_TYPE));

        File fileTemp = null;
        try {
            fileTemp = SystemConstant.getFileTempDirVar(String.valueOf(System.currentTimeMillis() + File.separator + SystemConstant.getNanoId()), SystemConstant.TEMP_PREFIX);
            // 存储路径为空，使用默认值
            rootPath = StringUtils.isNotBlank(rootPath) ? rootPath : fileTemp.getParent();
            // 存储文件名为空，使用默认值
            fileName = StringUtils.isNotBlank(fileName) ? fileName : SystemConstant.getNanoId() + basicAttachment.getType();
            // 存储文件类型与附件类型不一样，默认改用附件类型
            if (!fileName.endsWith(basicAttachment.getType())) {
                fileName = SystemConstant.getNanoId() + basicAttachment.getType();
            }

            File localPath = new File(rootPath, fileName);
            // oss存储
            if (type.equals(SystemConstant.OSS)) {
                try {
                    return fileStoreUtil.ossDownload(filePath, localPath.getPath(), uploadType.getFssType());
                } catch (IOException e) {
                    throw ExceptionResultEnum.ERROR.exception("从OSS上下载文件失败");
                }
            } else {
                File file = null;
                if (dictionaryConfig.fssPrivateDomain().getConfig().startsWith(SystemConstant.START_PARENT) || dictionaryConfig.fssPublicDomain().getConfig().startsWith(SystemConstant.START_PARENT)) {
                    file = new File(dictionaryConfig.fssPrivateDomain().getConfig(), filePath);
                } else {
                    file = new File(filePath);
                }
                FileUtils.copyFile(file, localPath);
                return localPath;
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(fileTemp.getParent())) {
                ConvertUtil.delFolder(fileTemp.getParent());
            }
            if (Objects.nonNull(fileTemp)) {
                fileTemp.delete();
            }
        }
        return null;
    }

    @Override
    public void zipFiles(HttpServletResponse response, String filePath, String zipName, List<File> files) {
        File fileTemp = SystemConstant.getFileTempDirVar(String.valueOf(System.currentTimeMillis()) + File.separator + SystemConstant.getNanoId(), SystemConstant.TEMP_PREFIX);
        filePath = StringUtils.isNotBlank(filePath) ? filePath : fileTemp.getPath();
        File rootFile = new File(filePath);
        // 创建保存目录
        if (!rootFile.exists()) {
            rootFile.mkdirs();
        }
        File zipFile = null;
        try {
            zipName = StringUtils.isNotBlank(zipName) ? zipName : SystemConstant.getNanoId() + SystemConstant.ZIP_PREFIX;
            zipFile = FileUtil.file(filePath, zipName);
            Zip4jUtil.zipEncryptFile(zipFile.getPath(), files, SystemConstant.ZIP_ENCRYPT_PWD);
            outputFile(response, zipFile, zipName);
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception("下载失败");
        } finally {
            // 删除zip文件
            FileUtil.del(zipFile);
            // 删除压缩内容
            FileUtil.del(filePath);
        }
    }

    public static void outputFile(HttpServletResponse response, File file, String fileName) {
        try {
            if (!file.exists()) {
                response.sendError(404, "File not found!");
            }

            BufferedInputStream br = new BufferedInputStream(new FileInputStream(file));
//            byte[] buf = new byte[1024];
//            int len = 0;

            String fName = URLEncoder.encode(fileName, SystemConstant.CHARSET_NAME);

            response.reset();
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment; filename=" + fName);

//            OutputStream outStream = response.getOutputStream();
//
//            while ((len = br.read(buf)) > 0) {
//                outStream.write(buf, 0, len);
//            }
            IOUtils.copy(br, response.getOutputStream());
            br.close();
//            outStream.close();
        } catch (IOException e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
    }
}
