package com.zhiqiyun.open.core.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhiqiyun.open.core.mapper.statistics.UploadFileInfoMapper;
import com.zhiqiyun.open.core.models.UploadResult;
import com.zhiqiyun.open.core.models.statistics.UploadFileInfo;
import com.zhiqiyun.open.core.service.SequenceService;
import com.zhiqiyun.open.core.service.UploadFileInfoService;
import com.zhiqiyun.open.exception.UploadException;
import com.zhiqiyun.open.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicMatch;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Service
public class UploadFileInfoServiceImpl extends ServiceImpl<UploadFileInfoMapper, UploadFileInfo> implements UploadFileInfoService {
    @Value("${uploader.max-size}")
    private long maxSize;

    @Value("${uploader.allow-file-types}")
    private String[] allowExtensions;

    @Value("${uploader.save-path}")
    private String savePath;

    @Value("${uploader.file-host}")
    private String fileHost;

    @Autowired
    private SequenceService sequenceService;

    @Override
    public UploadResult handle(String originalFilename, byte[] fileBuff) {
        UploadResult result = new UploadResult();
        result.setSuccess(false);
        result.setOriginalFileName(originalFilename);
        try {
            // 验证文件件大小
            if (fileBuff.length > maxSize * 1024) {
                throw new UploadException("上传文件大小不能超过" + (maxSize / 1024) + "M");
            }

            MagicMatch magicMatch = Magic.getMagicMatch(fileBuff);

            String extension = magicMatch.getExtension();
            String mimeType = magicMatch.getMimeType();

            // 验证文件类型
            if (extension == null) {
                throw new UploadException("无的文件扩展名，请重新上传");
            }

            extension = extension.toLowerCase();
            List<String> listAllowExtensions = Arrays.asList(allowExtensions);
            if (!listAllowExtensions.contains(extension)) {
                throw new UploadException(String.format("只能上传%s类型的文件", String.join(",", allowExtensions)));
            }

            String filePath = String.format("%s/%s", savePath, DateUtil.format("yyyy/MM/dd"));
            File fileDir = new File(filePath);
            if (!fileDir.exists()) {
                boolean mkdirResult = fileDir.mkdirs();
                if (!mkdirResult) {
                    log.warn("mkdir save file path error {}", filePath);
                    throw new UploadException("创建上传目录失败");
                }
            }
            filePath = String.format("%s/%s.%s", filePath, DigestUtils.md5Hex(fileBuff), extension);
            File file = new File(filePath);


            try {
                ByteArrayInputStream in = new ByteArrayInputStream(fileBuff);
                BufferedImage bi = ImageIO.read(in);
                if (bi.getHeight() > 1000 || bi.getWidth() > 1000) {
                    Thumbnails.of(bi).size(1000, 1000).toFile(file);
                } else {
                    Thumbnails.of(bi).size(bi.getWidth(), bi.getHeight()).toFile(file);
                }
            } catch (IOException e) {
                log.warn("upload is not image file", e);
                throw new UploadException("只能上传图片文件");
            }

            result.setSuccess(true);
            result.setMessage("上传文件成功");
            result.setMimeType(mimeType);
            // 获取服务地址和端口
            String url = filePath.replaceFirst(this.savePath, "");
            result.setSrc(fileHost + url);
            result.setSize(fileBuff.length);
            result.setExtension(extension);
            result.setId(this.sequenceService.nextId());

            UploadFileInfo fileInfo = new UploadFileInfo();
            BeanUtils.copyProperties(result, fileInfo);
            fileInfo.setCreatedTime(DateUtil.current());
            this.save(fileInfo);
        } catch (UploadException e) {
            result.setMessage(e.getMessage());
        } catch (Exception e) {
            log.error("upload file error", e);
            result.setMessage("服务异常，请稍后再试");
        }
        return result;
    }
}
