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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.boot.api.exception.ApiException;
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.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.UploadFileEnum;
import com.qmth.teachcloud.common.mapper.BasicAttachmentMapper;
import com.qmth.teachcloud.common.service.BasicAttachmentService;
import com.qmth.teachcloud.common.util.FileStoreUtil;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * <p>
 * 所有附件记录表 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class BasicAttachmentServiceImpl extends ServiceImpl<BasicAttachmentMapper, BasicAttachment> implements BasicAttachmentService {
    private final static Logger log = LoggerFactory.getLogger(BasicAttachmentServiceImpl.class);

//    @Resource
//    OssUtil ossUtil;

    @Resource
    private FileStoreUtil fileStoreUtil;

    @Autowired
    private DictionaryConfig dictionaryConfig;


    /**
     * 保存html附件
     *
     * @param fileName
     * @param htmlContent
     * @return
     * @throws IOException
     */
    @Override
    public File saveAttachmentHtml(String rootPath, String fileName, String htmlContent) {
        File file = null;
        try {
            byte[] bytes = htmlContent.getBytes();
            //上传至服务器
            File mkdir = new File(rootPath);
            if (!mkdir.exists()) {
                mkdir.mkdirs();
            }
            file = new File(rootPath, fileName);
            FileCopyUtils.copy(bytes, file);
            //计算html文件md5
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
        return file;
    }

    /**
     * 保存附件
     *
     * @param dirName
     * @param userId
     * @return
     * @throws IOException
     */
    @Override
    @Transactional
    public BasicAttachment saveAttachmentPdf(String dirName, Long userId) throws IOException {
        BasicAttachment basicAttachment = null;
        try {
            StringJoiner stringJoiner = new StringJoiner("").add(SystemConstant.PDF_TEMP_FILES_DIR).add(File.separator);
            File localPdfFile = new File(stringJoiner.toString() + File.separator + dirName);
            if (!localPdfFile.getParentFile().exists()) {
                localPdfFile.getParentFile().mkdirs();
                localPdfFile.createNewFile();
            }
            boolean oss = dictionaryConfig.sysDomain().isOss();
            JSONObject jsonPdf = new JSONObject();
            if (oss) {
                jsonPdf.put(SystemConstant.TYPE, SystemConstant.OSS);
                jsonPdf.put(SystemConstant.PATH, dirName);
            } else {
                jsonPdf.put(SystemConstant.TYPE, SystemConstant.LOCAL);
                jsonPdf.put(SystemConstant.PATH, localPdfFile);
            }
            jsonPdf.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.PDF);
            basicAttachment = new BasicAttachment(jsonPdf.toJSONString(), localPdfFile.getName(), SystemConstant.PDF_PREFIX, new BigDecimal(localPdfFile.length()), DigestUtils.md5Hex(new FileInputStream(localPdfFile)), userId);
            save(basicAttachment);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            deleteAttachment(basicAttachment);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return basicAttachment;
    }

    /**
     * 删除附件
     *
     * @param basicAttachment
     */
    @Override
    public void deleteAttachment(BasicAttachment basicAttachment) {
        deleteAttachmentCommon(basicAttachment);
    }

    /**
     * 批量删除附件
     *
     * @param basicAttachmentList
     */
    @Override
    public void batchDeleteAttachment(List<BasicAttachment> basicAttachmentList) {
        if (Objects.nonNull(basicAttachmentList) && basicAttachmentList.size() > 0) {
            for (BasicAttachment basicAttachment : basicAttachmentList) {
                deleteAttachmentCommon(basicAttachment);
            }
        }
    }

    @Override
    public BasicAttachment saveAttachment(MultipartFile file, String md5, UploadFileEnum type) {
        if (Objects.isNull(type)) {
            throw ExceptionResultEnum.ATTACHMENT_TYPE_EMPTY.exception();
        }
        BasicAttachment basicAttachment = null;
        try {
            SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
            int temp = file.getOriginalFilename().indexOf(".");
            String fileName = file.getOriginalFilename().substring(0, temp);
            String format = file.getOriginalFilename().substring(temp, file.getOriginalFilename().length());
            List<String> attachmentTypeList = dictionaryConfig.sysDomain().getAttachmentType();
            if (Objects.nonNull(format)) {
                long count = attachmentTypeList.stream().filter(s -> format.equalsIgnoreCase(s)).count();
                if (count == 0) {
                    throw ExceptionResultEnum.ERROR.exception("文件格式只能为" + attachmentTypeList.toString());
                }
            }
            int attachmentLength = dictionaryConfig.sysDomain().getAttachmentLength().intValue();
            if (Objects.nonNull(fileName) && fileName.length() > attachmentLength) {
                throw ExceptionResultEnum.ERROR.exception("文件名长度不能超过" + attachmentLength + "个字符");
            }
            long size = file.getSize();
            BigDecimal b = new BigDecimal(size);
            BigDecimal num = new BigDecimal(1024);
            b = b.divide(num, 2, BigDecimal.ROUND_HALF_UP).divide(num, 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
            double attachmentSize = dictionaryConfig.sysDomain().getAttachmentSize().doubleValue();
            if (b.doubleValue() > attachmentSize) {
                throw ExceptionResultEnum.ERROR.exception("文件大小不能超过" + attachmentSize + "MB");
            }
            log.info("fileName:{}", fileName);
            log.info("format:{}", format);
            log.info("size:{}", b);
            log.info("getOriginalFilename:{}", file.getOriginalFilename());
            String fileMd5 = DigestUtils.md5Hex(file.getBytes());
            log.info("fileMd5:{}", fileMd5);
            log.info("md5:{}", md5);
            if (!Objects.equals(fileMd5, md5)) {
                throw ExceptionResultEnum.MD5_EQUALS_FALSE.exception();
            }
            boolean oss = dictionaryConfig.sysDomain().isOss();
            LocalDateTime nowTime = LocalDateTime.now();
            StringJoiner stringJoiner = new StringJoiner("");
            if (!oss) {
                stringJoiner.add(SystemConstant.TEMP_FILES_DIR).add(File.separator);
            }
            stringJoiner.add(type.getTitle()).add(File.separator);
            stringJoiner.add(String.valueOf(nowTime.getYear())).add(File.separator)
                    .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                    .add(String.format("%02d", nowTime.getDayOfMonth()));

            JSONObject jsonObject = new JSONObject();
            stringJoiner.add(File.separator).add(SystemConstant.getUuid()).add(format);
            if (oss) {//上传至oss\
                String dirName = stringJoiner.toString().replaceAll("\\\\", "/");
                fileStoreUtil.ossUpload(dirName, file.getInputStream(), DigestUtils.md5Hex(file.getInputStream()), type.getFssType());
                jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
                jsonObject.put(SystemConstant.PATH, dirName);
            } else {//上传至服务器
                File finalFile = new File(stringJoiner.toString());
                if (!finalFile.exists()) {
                    finalFile.getParentFile().mkdirs();
                    finalFile.createNewFile();
                }
                FileUtils.copyInputStreamToFile(file.getInputStream(), finalFile);
                jsonObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
                jsonObject.put(SystemConstant.PATH, stringJoiner.toString());
            }
            jsonObject.put(SystemConstant.UPLOAD_TYPE, type);

            basicAttachment = new BasicAttachment(jsonObject.toJSONString(), fileName, format, b, fileMd5, requestUser.getId(), null);
            save(basicAttachment);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            deleteAttachment(basicAttachment);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return basicAttachment;
    }

    /**
     * 删除附件公用
     *
     * @param basicAttachment
     */
    public void deleteAttachmentCommon(BasicAttachment basicAttachment) {
        if (Objects.nonNull(basicAttachment) && Objects.nonNull(basicAttachment.getPath())) {
            JSONObject jsonObject = JSONObject.parseObject(basicAttachment.getPath());
            String type = String.valueOf(jsonObject.get(SystemConstant.TYPE));
            if (Objects.nonNull(type) && Objects.equals(type, SystemConstant.OSS)) {//删除阿里云附件
                // TODO: 2021/8/18 fss删除逻辑
//                ossUtil.ossDelete(jsonObject.get(SystemConstant.PATH).toString());
//                if (Objects.nonNull(jsonObject.get(SystemConstant.PDF_PATH))) {
//                    ossUtil.ossDelete(jsonObject.get(SystemConstant.PDF_PATH).toString());
//                }
            } else {//删除服务器附件
                if (Objects.nonNull(dictionaryConfig.sysDomain()) && dictionaryConfig.sysDomain().isOss()) {
                    File file = new File(jsonObject.get(SystemConstant.PATH).toString());
                    file.delete();
                    if (Objects.nonNull(jsonObject.get(SystemConstant.PDF_PATH))) {
                        file = new File(jsonObject.get(SystemConstant.PDF_PATH).toString());
                        file.delete();
                    }
                }
            }
        }
    }
}
