package com.upyuns.platform.rs.universal.service;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import com.github.wxiaoqi.security.common.util.UUIDUtils;
import com.github.wxiaoqi.security.common.util.process.SystemConfig;
import com.upyuns.platform.rs.universal.constant.RedisKey;
import com.upyuns.platform.rs.universal.controller.UploadController;
import com.upyuns.platform.rs.universal.utils.ImageWatermarkUtil;
import com.upyuns.platform.rs.universal.utils.ImgBase64Util;
import com.upyuns.platform.rs.universal.utils.ShpToGeojson;
import com.upyuns.platform.rs.website.entity.FileData;
import org.apache.commons.io.FileUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class    UploadService {

    public static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
    public static final DateTimeFormatter GAINFILE_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyMMdd");
    @Value("${universal.baseUploadPath}")
    private String baseUploadPath ;

    @Value("${universal.gaindataPath}")
    private String gaindataPath ;

    @Value("${universal.tempcachePath}")
    private String tempcachePath ;

    @Value("${universal.videoUploadPath}")
    private String videoUploadPath ;

    @Value("${universal.url}")
    private String xx_url ;
    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 写入上传文件，返回相对路径
     * @param file
     * @return
     */
    public Map<String, String> uploadShpFile(MultipartFile file, String prefix) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPathToday = "/"+prefix+ "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }
        String fileName = file.getOriginalFilename();
        String realFileRelPath = dirPathToday + "/" + no + fileName.substring(fileName.lastIndexOf("."));
        //文件存放路径
        String filePath = baseUploadPath + realFileRelPath;
        //将文件写入指定位置
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
        String key = "shp:"+ UUIDUtils.generateShortUuid();
        String geomJson = ShpToGeojson.shp2geojson(filePath);
//        String geomJson = ShpToGeojson.shp2OneGeojson(filePath);
        redisTemplate.opsForValue().setIfAbsent(key, geomJson);
//        realFileRelPath=xx_url+SystemConfig.XXMP_URL+realFileRelPath;

        Map map = CollUtil.newHashMap();
        map.put("shpKey", key);
        map.put("geom", geomJson);
        return map;
    }

    /**
     * 写入上传文件，返回相对路径
     * @param file
     * @return
     */
    public String uploadFile(MultipartFile file,String prefix) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPathToday = "/"+prefix+ "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }
        String fileName = file.getOriginalFilename();
        String realFileRelPath = dirPathToday + "/" + no + fileName.substring(fileName.lastIndexOf("."));
        //文件存放路径
        String filePath = baseUploadPath + realFileRelPath;
        //将文件写入指定位置
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
        realFileRelPath=xx_url+SystemConfig.XXMP_URL+realFileRelPath;
        return realFileRelPath;
    }


    public FileData uploadFileAndGetFileInfo(MultipartFile file, String prefix) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPathToday = "/"+prefix+ "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }
        String fileName = file.getOriginalFilename();
        String realFileRelPath = dirPathToday + "/" + no + fileName.substring(fileName.lastIndexOf("."));
        String   filetype=   fileName.substring(fileName.lastIndexOf("."));
        long fileSize = file.getSize();
      //  double fileSizeInKB = (double) fileSize / 1024; // 转换为 KB
        double fileSizeInMB = (double) fileSize / (1024 * 1024); // 转换为 MB
        double roundedFileSizeInMB = Math.round(fileSizeInMB * 100.0) / 100.0; // 保留两位小数
        String fileSizeString = String.format("%.2f MB", roundedFileSizeInMB);
//        String fileSizeInMBString = String.format("%.2f", fileSizeInMB); // 格式化为字符串，保留两位小数
        //文件存放路径
        String filePath = baseUploadPath + realFileRelPath;
        //将文件写入指定位置
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
        realFileRelPath=xx_url+SystemConfig.XXMP_URL+realFileRelPath;
        FileData fileData  = new FileData();
        fileData.setFilename(fileName);
        fileData.setFiletype(filetype);
        fileData.setFilesize(fileSizeString);
//        fileData.setFiletype(filetype);
        fileData.setFileurl(realFileRelPath);
        return fileData;
    }

    public FileData uploadGainFile(MultipartFile file, String prefix) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPath = "/"+prefix;
        String todayStr = now.toString(GAINFILE_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }
        String noStr = todayStr + "_" + no;
        String fileName = file.getOriginalFilename();
        String realFileRelPath =  gaindataPath + dirPath + "/" + noStr + fileName.substring(fileName.lastIndexOf("."));
        String filetype = fileName.substring(fileName.lastIndexOf("."));
        long fileSize = file.getSize();
        double fileSizeInMB = (double) fileSize / (1024 * 1024); // 转换为 MB
        double roundedFileSizeInMB = Math.round(fileSizeInMB * 100.0) / 100.0; // 保留两位小数
        String fileSizeString = String.format("%.2f MB", roundedFileSizeInMB);
        //文件存放路径
        String filePath = baseUploadPath + realFileRelPath;
        //将文件写入指定位置
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
        realFileRelPath=xx_url+SystemConfig.XXMP_URL+realFileRelPath;
        FileData fileData  = new FileData();
        fileData.setFilename(fileName);
        fileData.setFiletype(filetype);
        fileData.setFilesize(fileSizeString);
        fileData.setFileurl(realFileRelPath);
        fileData.setFilepath(filePath);
        return fileData;
    }

    public FileData uploadTempcaheFile(MultipartFile file, String prefix) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPath = "/"+prefix;
        String todayStr = now.toString(GAINFILE_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }
        String noStr = todayStr + "_" + no;
        String fileName = file.getOriginalFilename();
        String realFileRelPath =  tempcachePath + dirPath + "/" + noStr + fileName.substring(fileName.lastIndexOf("."));
        String filetype = fileName.substring(fileName.lastIndexOf("."));
        long fileSize = file.getSize();
        double fileSizeInMB = (double) fileSize / (1024 * 1024); // 转换为 MB
        double roundedFileSizeInMB = Math.round(fileSizeInMB * 100.0) / 100.0; // 保留两位小数
        String fileSizeString = String.format("%.2f MB", roundedFileSizeInMB);
        //文件存放路径
        String filePath = baseUploadPath + realFileRelPath;
        //将文件写入指定位置
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
        realFileRelPath=xx_url+SystemConfig.XXMP_URL+realFileRelPath;
        FileData fileData  = new FileData();
        fileData.setFilename(fileName);
        fileData.setFiletype(filetype);
        fileData.setFilesize(fileSizeString);
        fileData.setFileurl(realFileRelPath);
        fileData.setFilepath(filePath);
        return fileData;
    }

//    public String uploadFile250(MultipartFile file, String prefix) throws Exception {
////        // 创建本日存放目录
////        DateTime now = DateTime.now();
////        String dirPathToday = "/" + prefix + "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
////        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
////        Long no = redisTemplate.opsForValue().increment(redisNoKey);
////        if (no.equals(1L)) {
////            redisTemplate.expire(redisNoKey, 1, TimeUnit.DAYS);
////        }
////        String fileName = file.getOriginalFilename();
////        String realFileRelPath = dirPathToday + "/" + no + fileName.substring(fileName.lastIndexOf("."));
////        // 文件存放路径
////        String filePath = baseUploadPath + realFileRelPath;
////        // 将文件写入指定位置
////        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
////
////        // 将上传的图片压缩成250*250的尺寸
////        BufferedImage originalImage = ImageIO.read(new File(filePath));
////        BufferedImage resizedImage = new BufferedImage(250, 250, originalImage.getType());
////        Graphics2D g = resizedImage.createGraphics();
////        g.drawImage(originalImage, 0, 0, 250, 250, null);
////        g.dispose();
////
////        // 保存压缩后的图片
////        String compressedFilePath = baseUploadPath + dirPathToday  + no + ".jpg_250";
////        ImageIO.write(resizedImage, "jpg", new File(compressedFilePath));
////
////        realFileRelPath = xx_url + SystemConfig.XXMP_URL + realFileRelPath;
////        return realFileRelPath;
////    }

    public String uploadFile250(MultipartFile file, String prefix) throws Exception {
        // 创建本日存放目录
        DateTime now = DateTime.now();
        String dirPathToday = "/" + prefix + "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if (no.equals(1L)) {
            redisTemplate.expire(redisNoKey, 1, TimeUnit.DAYS);
        }
        String fileName = file.getOriginalFilename();
        String lastFormat = fileName.substring(fileName.lastIndexOf("."));
        String realFileRelPath = dirPathToday + "/" + no + lastFormat;
        // 文件存放路径
        String filePath = baseUploadPath + realFileRelPath;
        // 将文件写入指定位置
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));

        // 将上传的图片等比例缩放至250x250尺寸
        BufferedImage originalImage = ImageIO.read(new File(filePath));
        int originalWidth = originalImage.getWidth();
        int originalHeight = originalImage.getHeight();
        double scaleFactor = 1.0;

        if (originalWidth > originalHeight) {
            scaleFactor = (double) 500 / originalWidth;
        } else {
            scaleFactor = (double) 500 / originalHeight;
        }

        int newWidth = (int) (originalWidth * scaleFactor);
        int newHeight = (int) (originalHeight * scaleFactor);

        BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, originalImage.getType());
        Graphics2D g = resizedImage.createGraphics();
        g.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
        g.dispose();

        // 保存压缩后的图片
        String compressedFilePath = baseUploadPath + dirPathToday + "/"+ no + lastFormat + "_250";
        ImageIO.write(resizedImage, lastFormat.substring(1, lastFormat.length()), new File(compressedFilePath));

        realFileRelPath = xx_url + SystemConfig.XXMP_URL + realFileRelPath;
        return realFileRelPath;
    }




    /**
     * 写入上传文件，返回相对路径
     * @param file
     * @return
     */
    public String uploadFileDispose(MultipartFile file, String prefix, UploadController.DisposeDTO dto) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPathToday = "/"+prefix+ "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }
        String fileName = file.getOriginalFilename();
        String realFileRelPath = dirPathToday + "/" + no + fileName.substring(fileName.lastIndexOf("."));
        //文件存放路径
        String filePath = baseUploadPath + realFileRelPath;

        //缩略
        BufferedImage bufferedImage = ImgUtil.read(file.getInputStream());
        Image newImage = null;
        if(bufferedImage.getHeight() > dto.getScaleHight() && bufferedImage.getWidth() > dto.getScaleWidth()) {
            Float scale = 1.0f;
            if(bufferedImage.getHeight() < bufferedImage.getWidth()) {
                scale = dto.getScaleHight() / bufferedImage.getHeight();
            }else {
                scale = dto.getScaleWidth() / bufferedImage.getWidth();
            }
            newImage = ImgUtil.scale(bufferedImage, scale);
        }else {
            newImage = bufferedImage;
        }
        //加水印
        Font font = new Font(dto.getStyleName(),dto.getStyle(),dto.getSize());
        //Image newImage2 = ImgUtil.pressText(newImage, dto.getContext(), dto.getColor(), font, dto.getX(), dto.getY(), dto.getAlpha());

        //将文件写入指定位置
        //ImgUtil.write(newImage2, new File(filePath));
        //创建文件夹
        FileUtil.mkdir(baseUploadPath+ dirPathToday);
        ImageWatermarkUtil.ImageByText(dto.getContext(), newImage, filePath, dto.getDegree(), font);

        //将文件写入指定位置
        //FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
        realFileRelPath=xx_url+SystemConfig.XXMP_URL+realFileRelPath;
        return realFileRelPath;
    }

    /**
     * 写入上传文件，返回相对路径
     * @param imgFile
     * @return
     */
    public String uploadImg(String imgFile,String prefix) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPathToday = "/"+prefix+ "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }

        String realFileRelPath = dirPathToday;
        //文件存放路径
        String filePath = baseUploadPath + realFileRelPath;
        File file=new File(filePath);
        if(!file.exists()){
            file.mkdirs();

        }
         String str="/" + no + ".jpg";
        realFileRelPath = realFileRelPath+str;
        filePath=filePath +str;
        //将文件写入指定位置
        ImgBase64Util.generateImage(imgFile,filePath);
        realFileRelPath=xx_url+SystemConfig.XXMP_URL+realFileRelPath;
        return realFileRelPath;
    }


    /**
     * @Method: makeFileName
     * @Description: 生成上传文件的文件名，文件名以：uuid+"_"+文件的原始名称
     * @param filename 文件的原始名称
     * @return uuid+"_"+文件的原始名称
     */
    private String makeFileName(String filename){  //2.jpg
        //为防止文件覆盖的现象发生，要为上传文件产生一个唯一的文件名
        return UUID.randomUUID().toString() + "_" + filename;
    }

    /**
     * 为防止一个目录下面出现太多文件，要使用hash算法打散存储
     * @Method: makePath
     * @Description:
     *
     * @param filename 文件名，要根据文件名生成存储目录
     * @param savePath 文件存储路径
     * @return 新的存储目录
     */
    private String makePath(String filename,String savePath){
        //得到文件名的hashCode的值，得到的就是filename这个字符串对象在内存中的地址
        int hashcode = filename.hashCode();
        int dir1 = hashcode&0xf;  //0--15
        int dir2 = (hashcode&0xf0)>>4;  //0-15
        //构造新的保存目录
        String dir = savePath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
        //File既可以代表文件也可以代表目录
        File file = new File(dir);
        //如果目录不存在
        if(!file.exists()){
            //创建目录
            file.mkdirs();
        }
        return dir;
    }

    /**
     * 下载图片
     * @param realFileRelPath
     * @return
     * @throws Exception
     */
    public ResponseEntity<byte[]> downloadFile(String realFileRelPath) throws Exception{
        String filePath = baseUploadPath + realFileRelPath;
        File file = new File(filePath);//新建一个文件
        HttpHeaders headers = new HttpHeaders();//http头信息
        String downloadFileName = new String(file.getName());//设置编码
        headers.setContentDispositionFormData("attachment", downloadFileName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
    }

    /**
     * 写入上传文件，返回相对路径
     * @param file
     * @return
     */
    public String uploadVideo(MultipartFile file,String prefix) throws Exception{
        //创建本日存放目录
        DateTime now = DateTime.now();
        String dirPathToday = "/"+prefix+ "/" + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        String redisNoKey = RedisKey.UPLOAD_FILE_NO_PREFIX + now.toString(DEFAULT_DATE_TIME_FORMATTER);
        Long no = redisTemplate.opsForValue().increment(redisNoKey);
        if(no.equals(1l)){
            redisTemplate.expire(redisNoKey,1, TimeUnit.DAYS);
        }
        String fileName = file.getOriginalFilename();
        String realFileRelPath = dirPathToday + "/" + no + fileName.substring(fileName.lastIndexOf("."));
        //文件存放路径
        String filePath = videoUploadPath + realFileRelPath;
        //将文件写入指定位置
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath));
        realFileRelPath=xx_url+SystemConfig.VIDEO_URL+realFileRelPath;
        return realFileRelPath;
    }


}
