package com.qs.mp.web.controller.common;


import com.qs.mp.common.core.domain.AjaxResult;
import com.qs.mp.common.enums.PicHandlerTypeEnum;
import com.qs.mp.common.image.CompressUtil;
import com.qs.mp.common.image.ThumbnailsImgFilter;
import com.qs.mp.common.qcloud.QcloudFileUtils;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.common.utils.UUIDUtils;
import com.qs.mp.core.domain.LoginUser;
import com.qs.mp.core.domain.UploadAttachment;
import com.qs.mp.framework.security.handle.HostHolder;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;
import net.coobird.thumbnailator.geometry.Positions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RequestMapping("/api/v1/mp/*")
@RestController
@Component
public class FileUploadController extends BaseApiController {
    private static final Logger log = LoggerFactory.getLogger(FileUploadController.class);

    /**
     * 文件上传路径
     */
    @Value("${mp.profile}")
    public String filePath;

    /**
     * 公开
     */
    @Value("${cloud.public-bucket-name}")
    private String publicBucketName;

    /**
     * 私有
     */
    @Value("${cloud.private-bucket-name}")
    private String privateBucketName;

    @Autowired
    protected HostHolder hostHolder;

    /**
     * 文件上传
     * @param fileType 文件类型
     * @param file 文件对象
     * @return
     */
    @PutMapping("file/remote/upload/{fileType}")
    public AjaxResult uploadFile(@PathVariable("fileType") String fileType, @RequestParam("file") MultipartFile file) {
        try {
            if(null ==  file) {
                return AjaxResult.error("上传文件参数为空.");
            }
            //logger.info("upload...");
            LoginUser loginUser = hostHolder.getUser();
//            String custId = loginUser.getCustId();
            String mimeType = file.getContentType();
            // 上传文件路径
            LogUtil.info(log, "文件上传，fileName:{0}, ContentType:{1}", new Object[]{file.getOriginalFilename(), mimeType});
            String fileName = file.getOriginalFilename();
            String saveAs = fileName;
            // 指定目录
            if (StringUtils.isNotBlank(fileType)){
                saveAs = fileType + "/" + fileName;
            }
            QcloudFileUtils.putStream(file.getInputStream(), saveAs,
                privateBucketName, mimeType);
            UploadAttachment uploadFile = new UploadAttachment(saveAs, mimeType);
            return success("", uploadFile);
        } catch (Exception e) {
            LogUtil.error(log, e, "文件上传失败.");
            return AjaxResult.error("文件上传失败.");
        }
    }

    /**
     * 上传图片，并生成缩略图
     *
     * @param auth 是否公开可访问，0 可访问，1 不可访问
     * @param file 图片文件
     * @return
     */
    @PostMapping("image/remote/upload/post/{auth}")
    public AjaxResult postImage(@PathVariable("auth") int auth, @RequestParam("file") MultipartFile file)  {
        return uploadImageFile(auth, file, PicHandlerTypeEnum.CROP.getValue());
    }

    @PutMapping("image/remote/upload/commpress/{auth}")
    public AjaxResult postCommpressImage(@PathVariable("auth") int auth, @RequestParam("file") MultipartFile file)  {
        return uploadImageFile(auth, file, PicHandlerTypeEnum.COMPRESSION.getValue());
    }

    /**
     * 上传图形方法
     * @param auth  认证
     * @param file  文件信息
     * @param handlerType   处理类型，1 裁剪，2 压缩
     * @return
     */
    private AjaxResult uploadImageFile(
        @PathVariable("auth") int auth,
        @RequestParam("file") MultipartFile file,
        int handlerType) {
        try {
            if (null == file) {
                return AjaxResult.error("上传文件参数为空.");
            }
            //logger.info("upload...");
            LoginUser loginUser = hostHolder.getUser();
            String bucketName = privateBucketName;
            if (0 == auth) {
                bucketName = publicBucketName;
            }
            // 上传文件路径
            LogUtil.info(logger, "ContentType：" + file.getContentType());
            String mimeType = file.getContentType();
            if (StringUtils.isBlank(mimeType)) {
                mimeType = "image/jpg";
            }
            LogUtil.info(logger," mimeType:" + mimeType + " fileName:" + file.getOriginalFilename());
            String name = "";
            if (PicHandlerTypeEnum.CROP.getValue().equals(handlerType)) {
                // 裁剪并上传图片
                name = cropPicAndUpLoadOSS(file, mimeType, 480, 480, bucketName);
            }else if (PicHandlerTypeEnum.COMPRESSION.getValue().equals(handlerType)) {
                // 压缩并上传图片
                // 后台不用压缩
                name = commpressPicAndUpLoadOSS(file, mimeType, bucketName);
            }
            if (StringUtils.isBlank(name)) {
                LogUtil.error(logger, "图片上传失败.");
                return AjaxResult.error("图片上传失败.");
            }
            return success("", new UploadAttachment(name, mimeType));
        } catch (Exception e) {
            LogUtil.error(log, e, "文件上传失败.");
            return AjaxResult.error("文件上传失败.");
        }
    }

    /**
     * 上传图片，并生成缩略图
     *
     * @param auth 是否公开可访问，0 可访问，1 不可访问
     * @param file 图片文件
     * @return
     */
    @PutMapping("image/remote/upload/{auth}")
    public AjaxResult uploadImage(@PathVariable("auth") int auth, @RequestParam("file") MultipartFile file)  {
        return uploadImageFile(auth, file, PicHandlerTypeEnum.CROP.getValue());
    }

    /**
     * 裁剪图片并上传
     * @param file
     * @param mimeType
     * @param width
     * @param height
     * @param bucketName
     * @return
     */
    private String cropPicAndUpLoadOSS(MultipartFile file,String mimeType,int width,int height,String bucketName) {
        String fileName = file.getOriginalFilename();
        int idx = fileName.lastIndexOf('.');
        String suffix = "";
        if (idx > 0) {
            suffix = fileName.substring(idx);
        }
        String name = UUIDUtils.newId() + suffix;
        try {
            QcloudFileUtils.putStream(file.getInputStream(), name, bucketName, mimeType );
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            Builder<BufferedImage> builder = Thumbnails.of(bufferedImage);
            int pWidth = bufferedImage.getWidth();
            int pHeight = bufferedImage.getHeight();
            if(pWidth > pHeight && pWidth > width) {
                builder.height(height);
            }else if(pHeight > pWidth && pHeight > height){
                builder.width(480);
            } else {
                builder.size(pWidth, pHeight);
            }
            String outFileDir = filePath+"/thumb";
            File tempFile = new File(outFileDir);
            if(!tempFile.exists()) {
                tempFile.mkdirs();
            }
            String thumbName = name +"_s";
            String outFilePath = filePath+"/thumb/"+thumbName+"."+mimeType.substring(mimeType.lastIndexOf("/")+1);
            builder.toFile(outFilePath);
            //裁剪尺寸
            Thumbnails.of(outFilePath).scale(1f).sourceRegion(Positions.CENTER, 480,480).toFile(outFilePath);
            File outFile = new File(outFilePath);
            QcloudFileUtils.putFile(outFile, thumbName, bucketName, mimeType);
            if(outFile.exists()) {
                LogUtil.info(log, "delete file..."+outFilePath);
                outFile.delete();
            }
        }  catch (Exception e) {
            LogUtil.error(log, e, "");
            return null;
        }
        return name;
    }


    /**
     * 压缩并上传图片
     * @param file
     * @param mimeType
     * @param bucketName
     * @return
     */
    private String commpressPicAndUpLoadOSS(MultipartFile file, String mimeType, String bucketName){
        String fileName = file.getOriginalFilename();
        int idx = fileName.lastIndexOf('.');
        String suffix = "";
        if (idx > 0) {
            suffix = fileName.substring(idx);
        }
        String name = UUIDUtils.newId() + suffix;
        try {
            QcloudFileUtils.putStream(file.getInputStream(), name, bucketName, mimeType );

            // 后台不再需要压缩，直接前端调用cos的压缩方法 2022.4.20
 /*           BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
//            Builder<BufferedImage> builder = Thumbnails.of(bufferedImage);


            int pWidth = bufferedImage.getWidth();
            int pHeight = bufferedImage.getHeight();
//            builder.size(pWidth, pHeight);
            double accuracy = CompressUtil.getAccuracy(file.getSize()/1024);
            LogUtil.info(logger, "原始文件长：{0}，大小：{1}，contentType:{2}", pWidth, file.getSize()/1024, mimeType);

            String outFileDir = filePath+"/thumb";
            File tempFile = new File(outFileDir);
            if(!tempFile.exists()) {
                tempFile.mkdirs();
            }
            String thumbName = name +"_s";
            String outFilePath = filePath+"/thumb/"+thumbName+"."+mimeType.substring(mimeType.lastIndexOf("/")+1);
//            builder.toFile(outFilePath);

            // 压缩图片
            if (pWidth > 500) {
                float scale = 500f / pWidth;
                if ("image/png".equals(file.getContentType())) {
                    Thumbnails.of(bufferedImage).scale(scale > 0.5 ? 0.5 : scale).outputQuality(0.8)
                        .imageType(BufferedImage.TYPE_INT_ARGB).outputFormat("png")
                        .toFile(outFilePath);
                } else {
                    Thumbnails.of(bufferedImage).scale(scale).outputQuality(0.8).toFile(outFilePath);
                }
            }else {
                if ("image/png".equals(file.getContentType())) {
                    Thumbnails.of(bufferedImage).scale(0.5).outputQuality(0.8)
                        .imageType(BufferedImage.TYPE_INT_ARGB).outputFormat("png")
                        .toFile(outFilePath);
                } else {
                    Thumbnails.of(bufferedImage).scale(1f).outputQuality(0.8).toFile(outFilePath);
                }
            }


            File outFile = new File(outFilePath);
            LogUtil.info(logger, "压缩后文件大小：{0}", outFile.length()/ 1024);
            if (outFile.length() < file.getSize()) {
                QcloudFileUtils.putFile(outFile, thumbName, bucketName, mimeType);
            } else {
                // 如果大小没被压缩，则用原图作为缩略图
                QcloudFileUtils.putStream(file.getInputStream(), thumbName, bucketName, mimeType );
            }
            if(outFile.exists()) {
                LogUtil.info(log, "delete file..."+outFilePath);
                outFile.delete();
            }*/
        }  catch (Exception e) {
            LogUtil.error(log, e, "");
            return null;
        }
        return name;
    }

}
