package com.sptg.gateway.controller.common;

import cn.hutool.core.io.FileTypeUtil;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.beans.StorePathChildren;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.util.Base64DecodeMultipartFileUtils;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.common.core.util.aliface.FaceDetectUtil;
import com.sptg.estate.api.dto.ThirdUserDto;
import com.sptg.estate.api.entity.ThirdUser;
import com.sptg.estate.api.feigns.ThirdUserFeign;
import com.sptg.estate.api.feigns.UserFeign;
import com.sptg.permissions.api.feigns.ConfFeign;
//import it.sauronsoftware.jave.Encoder;
import com.sptg.permissions.api.feigns.FaceVerifyFeign;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;

/**
 * title: UploadFileController
 * package: com.sptg.gateway.controller.common
 * description: 文件上传-控制器
 *
 *
 *
 */
@RestController
@RequestMapping(value = "/common/file")
@RequiredArgsConstructor
@Slf4j
public class FileManageController {

    private final FastFileStorageClient fastFileStorageClient;
    private  RestTemplate restTemplate;
    private final ThirdUserFeign thirdUserFeign;
    private final UserFeign userFeign;

    private final FastFileStorageClient storageClient;

    @Autowired
    private final ConfFeign confFeign;
    private final FaceVerifyFeign faceVerifyFeign;
    private static final String FILE_PNG=".png";
    private static final String FILE_JPG=".jpg";
    private static final String FILE_JPEG=".jpeg";

    /**
     * 功能描述:文件上传
     * @param multipartFile 上传的文件对象
     * @param isNeedMd5 是否计算md5
     * @return ResultBean<StorePath>
     *
     *
     */
    @RequestMapping(value = "/upload")
    public ResultBean<StorePath> uploadFile(@RequestParam("file") MultipartFile multipartFile,Boolean isNeedMd5) throws Exception{
        Assert.notNull(multipartFile,"参数异常");
        String filename = multipartFile.getOriginalFilename();
        String fileType = filename.substring(filename.lastIndexOf("."));
        //先判断后缀名
        if (FILE_PNG.equalsIgnoreCase(fileType) || FILE_JPG.equalsIgnoreCase(fileType) || FILE_JPEG.equalsIgnoreCase(fileType)) {
            String type ;
            try {
                type = FileTypeUtil.getType(multipartFile.getInputStream());
                //根据首部字节判断文件类型
                if (FILE_PNG.contains(type)||FILE_JPG.contains(type)||FILE_JPEG.contains(type)){
                    StorePathChildren storePath = this.getStorePathChildren(fastFileStorageClient.uploadFile(
                            multipartFile.getInputStream(),multipartFile.getSize(),
                            FilenameUtils.getExtension(multipartFile.getOriginalFilename()),null));
                    if(isNeedMd5!=null && isNeedMd5){
                        String md5Hex = DigestUtils.md5Hex(multipartFile.getInputStream());
                        storePath.setMd5(md5Hex);
                    }
                    return new ResultBean<>(ResultEnum.SUCCESS,storePath);
                }else{
                    return new ResultBean(ResultEnum.FAILURE,"不支持的文件格式");
                }
            } catch (Exception e) {
                return new ResultBean(ResultEnum.FAILURE,"不支持的文件格式");

            }
        }else{
            return new ResultBean(ResultEnum.FAILURE,"不支持的文件格式");
        }
        /*
         * 返回的对象storePath
         *  storePath.fullPath = "group1/M00/00/00/wKgAYlvpNveAQ9jgAACQxvfzaOY198.jpg"
         *  storePath.group = "group1"
         *  storePath.path = "M00/00/00/wKgAYlvpNveAQ9jgAACQxvfzaOY198.jpg"
         */

//        Conf conf = confFeign.getEntityByToken("file.max.size");
//        String size = conf.getConfValue();
//        if(StringUtils.hasText(size)){
//            Assert.isTrue(this.checkFileSize(multipartFile.getSize(), 100, "M"), "文件大小不能超过100M");
//        }
    }

    @PostMapping(value = "/uploadMaterialFile")
    public ResultBean<StorePath> uploadMaterialFile(@RequestParam("file") MultipartFile multipartFile,Boolean isNeedMd5)throws Exception{
        Assert.notNull(multipartFile,"参数异常");
        if(multipartFile.getContentType().contains("video")){
            File file;
            if(File.separator.equals("/")){//linux环境
               file = new File("/opt/app-server/1.mp4");
                if (!file.exists()) {
                    file.createNewFile();
                }
            }else{
                file = new File(System.getProperties().getProperty("user.dir")+File.separator+"1.mp4");
                if (!file.exists()) {
                    file.createNewFile();
                }
            }
            multipartFile.transferTo(file);
            BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
            bufferedReader.close();
            Map map = new HashMap();
//            it.sauronsoftware.jave.Encoder encoder = new Encoder();
            try {
//                it.sauronsoftware.jave.MultimediaInfo m = encoder.getInfo(file);
//                int width = m.getVideo().getSize().getWidth();
//                int height = m.getVideo().getSize().getHeight();
//                if(width == 1080 && height == 1920){
//                }else {
//                    return  new ResultBean<>("200","上传视频分辨率必须为1080*1920");
//                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
            }
        }

        StorePathChildren storePath = this.getStorePathChildren(fastFileStorageClient.uploadFile(
                multipartFile.getInputStream(),multipartFile.getSize(),
                FilenameUtils.getExtension(multipartFile.getOriginalFilename()),null));
        //计算文件的md5
        if(isNeedMd5!=null && isNeedMd5){
            String md5Hex = DigestUtils.md5Hex(multipartFile.getInputStream());
            //临时保存文件md5字符串
            storePath.setMd5(md5Hex);
        }
        return new ResultBean<>(ResultEnum.SUCCESS,storePath);
    }

    @PostMapping(value = "/uploadImageZip")
    public ResultBean<String> uploadImageZip(@RequestParam("file") MultipartFile multipartFile)throws Exception{
        Assert.notNull(multipartFile,"参数异常");

        String s = uploadZipFilesAndParse(multipartFile, "1");
        return new ResultBean<>(ResultEnum.SUCCESS, s);
    }

    @RequestMapping(value = "/uploadBase64")
    public ResultBean<StorePath> uploadBase64File(@RequestBody String base64Array) throws Exception{
        MultipartFile multipartFile = null;
        multipartFile  = Base64DecodeMultipartFileUtils.base64ToMultipart(base64Array);
       /* if(base64Array.indexOf("PNG") > 0){
            multipartFile  = Base64DecodeMultipartFileUtils.base64ToMultipart(base64Array);
        }else{
            String fileName = String.valueOf(IdWorker.getId());
            this.convert(base64Array,fileName);
            multipartFile= toFile(fileName);
        }*/

        StorePathChildren storePath =null;
        /*
                //检测人脸图片是否合格
        //再次转成base64字符去掉'data:image/jpeg;base64,字符
        base64Array= new BASE64Encoder().encode(multipartFile.getBytes());
        //去换行回车
        base64Array=base64Array.replace("\r\n","");
        base64Array=base64Array.replace("\n","");
        Map<String, Object> checkResultMap = this.checkFaceImage(base64Array);
        int ret = (int)checkResultMap.get("ret");
        if(ret!=0){
           return new ResultBean<>("500.1","请使用符合标准的真实人脸！");
        }
        */
        storePath = this.getStorePathChildren(fastFileStorageClient.uploadFile(
                multipartFile.getInputStream(),multipartFile.getSize(),
                FilenameUtils.getExtension(multipartFile.getOriginalFilename()),null));
        String md5Hex = DigestUtils.md5Hex(multipartFile.getInputStream());
        //临时保存文件md5字符串
        storePath.setMd5(md5Hex);

        String faceUrl = confFeign.getFileServerHost() + storePath.getFullPath();

//        FaceDetectUtil faceDetectUtil = new FaceDetectUtil();
//        ResultBean resultBean = faceDetectUtil.detectImage(faceUrl);
        ResultBean resultBean = faceVerifyFeign.verify(faceUrl);
        if (resultBean != null){
            return resultBean;
        }
        return new ResultBean<>(ResultEnum.SUCCESS,storePath);
    }

    /**
     *  数据封装--返回子类对象
     * @param storePath
     * @return
     */
    private StorePathChildren getStorePathChildren(StorePath storePath){
        StorePathChildren storePathChildren = new StorePathChildren();
        storePathChildren.setGroup(storePath.getGroup());
        storePathChildren.setPath(storePath.getPath());
        return  storePathChildren;
    }

    /**
     * 功能描述:图片类型转化，生成缓存png格式
     * @param
     *
     *
     */
    private void convert(String base64Array,String fileName ) {
        try {
            MultipartFile multipartFile  = Base64DecodeMultipartFileUtils.base64ToMultipart(base64Array);
            BufferedImage input = ImageIO.read(multipartFile.getInputStream());
            ImageIO.write(input, "PNG", new File(fileName+".png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 功能描述:读取缓存png图片
     * @param
     *
     *
     */
    private MultipartFile toFile(String fileName){
        File imageFile = new File(fileName+".png");
        FileInputStream input = null;
        MultipartFile multipartFile = null;
        try {
            input = new FileInputStream(imageFile);
            multipartFile = new MockMultipartFile("file", imageFile.getName(), "text/plain", IOUtils.toByteArray(input));
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(imageFile.exists()){
                imageFile.delete();
            }
        }
        return  multipartFile;
    }

    private boolean checkFileSize(Long len, int size, String unit) {
//        long len = file.length();
        double fileSize = 0;
        if ("B".equals(unit.toUpperCase())) {
            fileSize = (double) len;
        } else if ("K".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1024;
        } else if ("M".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1048576;
        } else if ("G".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1073741824;
        }
        if (fileSize > size) {
            return false;
        }
        return true;
    }

    /**
     * 人脸检测接口
     * @param base64Image 人脸图片base64
     * @return Map<String,Object>
     */
    private  Map<String,Object> checkFaceImage(String base64Image){
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", MediaType.APPLICATION_JSON_UTF8.toString());
        headers.add("Content-Type", MediaType.APPLICATION_JSON_UTF8.toString());
        Map<String, Object> params = new HashMap<>(OperationConstant.THREE);
        params.put("access_token","b8ac10c5bc73385544d28840babcd5e8d6a1475cf3aaa88a333766b7");
        params.put("operation","CHECK");
        Map<String, String> imageParams = new HashMap<>(OperationConstant.ONE);
        imageParams.put("image",base64Image);
        params.put("data",imageParams);
        String url = "http://114.115.157.209:12021/dmface/server/check_face";
        HttpEntity<String> requestEntity = new HttpEntity<>(JsonUtils.objectToJson(params), headers);
        RestTemplate restTemplate=new RestTemplate();
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        Map resultMap = JsonUtils.jsonToPojo(result, Map.class);
        int ret = (int)resultMap.get("ret");
        if(ret!=0&&ret!=1){
                log.error("人脸图片检查错误",JsonUtils.objectToJson(resultMap));
         }
        return resultMap;
    }


    /**
     *返回的是批次号
     *同时我另外开了线程处理zip文件里面的图片和excel，
     */
    public String uploadZipFilesAndParse(MultipartFile file, String createdId) throws Exception {
        String filename = file.getOriginalFilename();
        String fileType = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase(Locale.US);
        String uuid = UUID.randomUUID().toString();
        //判断文件是不是zip类型
        if(fileType.equals("zip")){

            //FileConfig.localtion是配置文件和config类生产的，我会在评论区附上这些代码，测试demo的时候大家可以直接把FileConfig.localtion替换成D:/test
            String desPath = FileConfig.localtion + File.separator + uuid.replaceAll("-", "");
//            String desPath = "D:/test" + File.separator + uuid.replaceAll("-", "");


            //下面这三行的代码就是把上传文件copy到服务器，一定不要遗漏了。
            //遗漏了这个代码，在本地测试环境不会出问题，在服务器上一定会报没有找到文件的错误
            String savePath = FileConfig.localtion + File.separator;
            File savefile = new File(savePath+filename);
            file.transferTo(savefile);

            FileUtil fileUtil = new FileUtil();
            //解压zip文件，我是写在公共类里面，FileUtil类代码评论区见

            List<Map<String, String>> imageInfoList = fileUtil.unZip(file, desPath, savePath, this.storageClient);

            imageInfoList.forEach(map -> {
                String imageName = map.get("imageName");
                String imageUrl = map.get("imageUrl");
                String md5Hex = map.get("md5Hex");

                ThirdUserDto userDto = new ThirdUserDto();
                userDto.setImageName(imageName);
                List<ThirdUser> userlist = this.thirdUserFeign.getListByCondition(userDto);
                if (userlist.size() > 0){
                    ThirdUser user = userlist.get(0);
                    user.setImageUrl(imageUrl);
                    user.setImageMd5(md5Hex);
                    thirdUserFeign.updateEntity(user);
                }

                /*UserDto dto = new UserDto();
                dto.setImageUri(imageName);
                List<User> list = this.userFeign.getListByCondition(dto);
                if (list.size() > 0){
                    User user = list.get(0);
                    user.setImageUri(imageUrl);
                    user.setSign(1);
                    this.userFeign.updateEntity(user);
                }*/
            });


            /*new Thread(new Runnable() {
                @Override
                public void run() {
                    List<File> fileList = new ArrayList<>();
                    fileList = fileUtil.getSubFiles(desPath, fileList);
                    for (File oneFile : fileList){
                        if (oneFile.getName().toLowerCase().endsWith(".xls") || oneFile.getName().toLowerCase().endsWith(".xlsx") ) {
                            try {
                                //解析处理excel文件
//                                parseExcelFile(oneFile,createdId,uuid);
                            } catch (Exception e) {
                                log.error(e.getMessage());
                            }
                        }else if(oneFile.getName().toLowerCase().endsWith(".jpg")) {
                            try {
                                //解析处理图片文件
                                parseImageFile(oneFile,createdId,uuid);
                            } catch (Exception e) {
                                log.error(e.getMessage());
                            }
                        }
                    }

                    //最后要删除文件，删除文件的方法见评论区FileUtil类
                    FileUtil.clearFiles(desPath);

                }
            }).start();*/

        }
        return uuid;
    }

    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
            log.warn("MultipartFile transform to File completed!");
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void parseImageFile(File file, String createdId, String uuid) throws Exception {

//        String imgStr ="";
//        FileInputStream fis = new FileInputStream(file);
//        byte[] buffer = new byte[(int) file.length()];
//        int offset = 0;
//        int numRead = 0;
//        while (offset < buffer.length && (numRead = fis.read(buffer, offset, buffer.length - offset)) >= 0) {
//            offset += numRead;
//        }
//        if (offset != buffer.length) {
//            throw new IOException("Could not completely read file " + file.getName());
//        }
//        fis.close();
//        Base64 encoder = new Base64();
//        imgStr = Base64.encodeBase64String(buffer);
//        imgStr.length();
        log.warn("file name:"+file.getName());
//        LogUtils.info("file imgStr:"+imgStr);
//        LogUtils.info("file imgStr.length:"+imgStr.length());

    }
}
