package com.dcsoft.file.controller;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSONObject;
import com.dcsoft.file.service.IAlgoService;
import com.dcsoft.file.service.IFaceService;
import com.dcsoft.file.utils.*;
import com.dcsoft.system.api.RemoteStudentService;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.reflect.MethodSignature;
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.http.MediaType;
import org.springframework.util.ClassUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.dcsoft.common.core.domain.R;
import com.dcsoft.common.core.utils.file.FileUtils;
import com.dcsoft.file.service.ISysFileService;
import com.dcsoft.system.api.domain.SysFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

import static com.dcsoft.file.utils.MinioUtil.getBase64String;

/**
 * 文件请求处理
 *
 * @author dcsoft
 */
@RestController
public class SysFileController
{
    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);

    /** 获取yml配置类里的桶名称*/
    @Value("${minio.bucket-name}")
    private String bucketName;

    @Autowired
    private ISysFileService sysFileService;

    @Value("${minio.bucket-name1}")
    private String bucketName1;

    @Autowired
    private IAlgoService algoService;

    @Autowired
    private IFaceService faceService;

    @Value("${minio.url}")
    private String miniourl;

    @Value("${minio.gwurl}")
    private String miniogwurl;

    @Value("${minio.bucket-name2}")
    private String bucketName2;

    @Value("${file.domain}")
    private String fileurl;

    @Value("${file.gwurl}")
    private String filegwurl;

    /**
     * 文件上传请求
     */
    @PostMapping("upload")
    public R<SysFile> upload(MultipartFile file)
    {
        try
        {
            // 上传并返回访问地址
            String url = sysFileService.uploadFile(file);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(url));
            url=url.replace(fileurl,filegwurl);
            sysFile.setUrl(url);
            return R.ok(sysFile);
        }
        catch (Exception e)
        {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 文件上传请求
     */
    @PostMapping("avatar")
    public R<SysFile> avatar(@RequestParam("avatarfile") MultipartFile file)
    {
        try
        {
            // 上传并返回访问地址
            String url = sysFileService.uploadFile(file);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(url));
            sysFile.setUrl(url);
            return R.ok(sysFile);
        }
        catch (Exception e)
        {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    @PostMapping("uploadMinioCar")
    public R<SysFile> uploadMinioCar(@RequestParam("file") MultipartFile file)
    {
        try
        {
            String fileNames = FileUploadUtils.uploadMinio(file,this.bucketName2,file.getName());
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(fileNames));
            fileNames=fileNames.replace(miniourl,miniogwurl);
            sysFile.setUrl(fileNames);
            return R.ok(sysFile);
        }catch (Exception e){
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }



    /**
     * 文件上传请求
     */
    @PostMapping("uploadMinio")
    public R<SysFile> uploadMinio(MultipartFile file, String fileName)
    {
       /* //判断压缩图片
        if((1024 * 1024 * 0.1) <= file.getSize()){
            // 小于 1M 的
            try {
                String fileNames1 = file.getOriginalFilename();
                File newFile = new File(fileNames1);
                if ((1024 * 1024 * 0.1) <= file.getSize() && file.getSize() <= (1024 * 1024)) {
                    Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.4f).toFile(newFile);
                }
                // 1 - 2M 的
                else if ((1024 * 1024) < file.getSize() && file.getSize() <= (1024 * 1024 * 2)) {
                    Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.2f).toFile(newFile);
                }
                // 2M 以上的
                else if ((1024 * 1024 * 2) < file.getSize()) {
                    Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.1f).toFile(newFile);
                }
                // 转为 MultipartFile
                file = PictureUtils.getMultipartFile(newFile);
                newFile.delete();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }*/
        try
        {
           /* initFlowRules();//
            // 上传并返回访问地址
            //上传前进行人脸检测
            String base64String=MinioUtil.getBase64String(file);
            int data=faceService.judgeImageBase64(base64String);
            log.info("人脸检测返回值==========="+data);
            if(data!=0){
                log.error("人脸检测不符合要求");
                return R.fail("人脸检测不符合要求");
            }
            //提取特征值
            String feature=faceService.getFeature(base64String);*/
            String fileNames = FileUploadUtils.uploadMinio(file,this.bucketName,fileName);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(fileNames));
            fileNames=fileNames.replace(miniourl,miniogwurl);

            sysFile.setUrl(fileNames);
            //sysFile.setFeature(feature);
            return R.ok(sysFile);
        }catch (Exception e){
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 文件上传请求
     */
    @PostMapping("uploadMinios")
    public R<SysFile> uploadMinios(MultipartFile file,String fileName)
    {

        //判断压缩图片
        if((1024 * 1024 * 0.1) <= file.getSize()){
            // 小于 1M 的
            try {
                String fileNames1 = file.getOriginalFilename();
                File newFile = new File(fileNames1);
                if ((1024 * 1024 * 0.1) <= file.getSize() && file.getSize() <= (1024 * 1024)) {
                    Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.4f).toFile(newFile);
                }
                // 1 - 2M 的
                else if ((1024 * 1024) < file.getSize() && file.getSize() <= (1024 * 1024 * 2)) {
                    Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.2f).toFile(newFile);
                }
                // 2M 以上的
                else if ((1024 * 1024 * 2) < file.getSize()) {
                    Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.1f).toFile(newFile);
                }
                // 获取输入流
                FileInputStream input = new FileInputStream(newFile);
                // 转为 MultipartFile
                file = PictureUtils.getMultipartFile(newFile);
                newFile.delete();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        try
        {
            // 上传并返回访问地址
            String fileNames = FileUploadUtils.uploadMinio(file,this.bucketName,fileName);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(fileNames));
            fileNames=fileNames.replace(miniourl,miniogwurl);
            sysFile.setUrl(fileNames);
            return R.ok(sysFile);
        }catch (Exception e){
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 文件非证件照上传请求
     */
    @PostMapping("uploadMinio1")
    public R<SysFile> uploadMinio1(MultipartFile file,String fileName)
    {
        try
        {
            try {
                String fileNames1 = file.getOriginalFilename();
                File newFile = new File(fileNames1);
                if((1024 * 1024 * 0.15) <= file.getSize()){// 大于 150k 的  //判断压缩图片
                    Thumbnails.of(file.getInputStream()).size(480,640 ).keepAspectRatio(false).toFile(newFile);
                }else{
                    Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.9f).toFile(newFile);
                }
                int targetSize=100;
                BufferedImage image = ImageIO.read(newFile);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                ImageIO.write(image, "jpg", outputStream);
                byte[] imageBytes = outputStream.toByteArray();
                int currentSize = imageBytes.length / 1024; // 当前文件大小（单位为KB）
                while (currentSize < targetSize) {
                    // 将图片数据不断复制进行扩大
                    byte[] tmpBytes = new byte[imageBytes.length+40*1024];
                    System.arraycopy(imageBytes, 0, tmpBytes, 0, imageBytes.length);
                    imageBytes = tmpBytes;
                    currentSize = imageBytes.length / 1024;
                }
                file = PictureUtils.getMultipartFile(fileName+".jpg",imageBytes);
                // 转为 MultipartFile
                newFile.delete();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            // 上传并返回访问地址
            String fileNames = FileUploadUtils.uploadMinio(file,this.bucketName1,fileName);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(fileNames));
            fileNames=fileNames.replace(miniourl,miniogwurl);
            sysFile.setUrl(fileNames);
            return R.ok(sysFile);
        }
        catch (Exception e)
        {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 文件上传请求
     */
    @GetMapping("compareTwoPic")
    public R<Float> compareTwoPic(@RequestParam("url1") String url1,@RequestParam("url2") String url2){
        try
        {
            //进行人脸1v1
            byte[] image1= Base64.decodeBase64(ImageToBase64Utils.getImgUrlToBase64(url1));
            byte[] image2=Base64.decodeBase64(ImageToBase64Utils.getImgUrlToBase64(url2));
            float data=faceService.compareTwoPic(image1,image2);
            return R.ok(data);
        }
        catch (Exception e)
        {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 文件上传请求
     */
    @GetMapping("comparePic")
    public R<Float> comparePic(@RequestParam("feature1") String feature1,@RequestParam("feature2") String feature2){
        try
        {
            //进行人脸1v1
            float data=faceService.compareTwoPic(feature1,feature2);
            return R.ok(data);
        }
        catch (Exception e)
        {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    private static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("HelloWorld");
        //通过QPS来限流
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        //设置QPS为20.
        rule.setCount(10);
        rule.setLimitApp("default");
        rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }


}
