package com.jeeplus.file.service;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyun.oss.model.SimplifiedObjectMeta;
import com.jeeplus.file.service.dto.FileUrlDto;
import com.jeeplus.sys.utils.Global;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;

@Slf4j
@Service
public class OSSFileService {

    @Value("${config.accessory.aliyun.aliyunDownloadUrl}")
    private String aliyunDownloadUrl;

    @Value("${config.accessory.aliyun.aliyunUrl}")
    private String aliyunUrl;

    @Value("${config.accessory.aliyun.bucketName}")
    private String bucketName;

    @Value("${qzBucketName}")
    private String qzBucketName;

    @Value("${config.accessory.aliyun.endpoint}")
    private String endpoint;

    @Value("${config.accessory.aliyun.accessKeyId}")
    private String accessKeyId;

    @Value("${config.accessory.aliyun.accessKeySecret}")
    private String accessKeySecret;

    /**
     * 上传文件
     * @param file
     * @param dir 存放文件夹名称
     * @return
     * @throws Exception
     */
    public FileUrlDto webUpload(MultipartFile file, String dir) throws IOException {
        FileUrlDto dto = new FileUrlDto();
        // 文件保存路径
        String fileDir = "attachment-file/wdterp" + "/"+dir + this.datePath() + "/"+ System.currentTimeMillis();
        // 判断文件是否为空
        if (!file.isEmpty()) {
            String name = file.getOriginalFilename ();
            this.uploadFile2OSS(file.getInputStream(), fileDir, name);
            String url = fileDir +name;
            String lsUrl = this.getFileTemporaryLookUrl(aliyunUrl + "/" + fileDir +name);
            dto.setUrl(url);
            dto.setLsUrl(lsUrl);
        }
        return dto;
    }

    /**
     * 阿里云获取临时文件查看url
     * @param url
     */
    public String getFileTemporaryLookUrl(String url){
        url = url.replace("amp;","");
        String cons = "";
        if (url.contains(aliyunUrl)){
            cons = aliyunUrl;
        }else if (url.contains("http://gangwan-app.oss-cn-hangzhou.aliyuncs.com")){
            cons = "http://gangwan-app.oss-cn-hangzhou.aliyuncs.com";
        }else {
            cons = aliyunDownloadUrl;
        }
        String key = "";
        String[] split = url.split(cons + "/");
        if(split.length>1){
            key = split[1];
        }else{
            key = url;
        }
        // 指定过期时间为24小时。
        Date expiration = new Date(new Date().getTime() + 1000 * 60 * 60 * 24 );
        //初始化OSSClient
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        return ossClient.generatePresignedUrl(bucketName, key, expiration).toString();
    }

    /**
     * 上传到OSS服务器  如果同名文件会覆盖服务器上的
     *
     * @param fileName 文件名称 包括后缀名
     * @return 出错返回"" ,唯一MD5数字签名
     */
    public String uploadFile2OSS(InputStream inStream, String fileDir, String fileName) {
        //初始化OSSClient
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        long start = System.currentTimeMillis();
        //上传文件
        PutObjectResult putResult = ossClient.putObject(bucketName, fileDir + fileName, inStream);
        String ret = putResult.getETag();

        try {
            if (inStream != null) {
                inStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        log.info("上传文件到云服务器成功，文件名：{}，耗时：{}ms",fileName,end-start);
        return ret;
    }

    /**
     * 获得url链接
     *
     * @param key
     * @return
     */
    public String getUrl(String key) {
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        // 设置URL过期时间为10年  3600l* 1000*24*365*10
        Date expiration = new Date(new Date().getTime() + 3600l * 1000 * 24 * 365 * 10);
        // 生成URL
        URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
        if (url != null) {
            return url.toString();
        }
        return null;
    }



    /**
     * 阿里云获取临时文件大小
     * @param file
     */
    public Long getSimplifiedObjectMeta(String file){
        //初始化OSSClient
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);

        URL url = null;
        SimplifiedObjectMeta simplifiedObjectMeta = new SimplifiedObjectMeta();
        try {

            file = file.replace("amp;","");
            String aliyunDownload = aliyunDownloadUrl;
            String aliDownloadUrl = aliyunUrl;
            String cons = "";
            if (file.contains(aliyunDownload)){
                cons = aliyunDownload;
            }else if (file.contains("http://gangwan-app.oss-cn-hangzhou.aliyuncs.com")){
                cons = "http://gangwan-app.oss-cn-hangzhou.aliyuncs.com";
            }else {
                cons = aliDownloadUrl;
            }
            String key = file.split(cons+"/")[1];
            simplifiedObjectMeta = ossClient.getSimplifiedObjectMeta(bucketName, key);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return simplifiedObjectMeta.getSize();
    }


    /**
     * 文件下载
     * @param key
     * @param fileName
     */
    public byte[] downBytesByStream(String key, String fileName){
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        byte[] bytes = null;
        BufferedInputStream in = null;
        ByteArrayOutputStream outputStream = null;
        log.info("开始从云服务器加载文件，文件名：{}",fileName);
        try {
            // 创建OSSClient实例
            long start = System.currentTimeMillis();
            OSSObject ossObject = ossClient.getObject(bucketName, key);
            in = new BufferedInputStream(ossObject.getObjectContent());
            outputStream = new ByteArrayOutputStream();
            byte[] car=new byte[1024];
            int L=0;
            while((L=in.read(car))!=-1){
                outputStream.write(car, 0,L);
            }
            bytes = outputStream.toByteArray();
            long end = System.currentTimeMillis();
            log.info("从云服务器加载文件成功，文件名：{}，耗时：{}ms",fileName,end-start);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (in!=null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return  bytes;
    }


    /**
     * 附件下载到本地指定文件夹
     * @param key
     * @param fileName
     */
    public void downByStreamSaveLocal(String key, String fileName,String downFileStr){
        try {
            // 创建OSSClient实例
            OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
            OSSObject ossObject = ossClient.getObject(bucketName, key);
            BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());


            //写入到文件（注意文件保存路径的后面一定要加上文件的名称）
            FileOutputStream fileOut = new FileOutputStream(downFileStr);
            BufferedOutputStream bos = new BufferedOutputStream(fileOut);
            byte[] buf = new byte[4096];
            int length = in.read(buf);
            //保存文件
            while(length != -1)
            {
                bos.write(buf, 0, length);
                length = in.read(buf);
            }
            if(bos!=null){
                bos.flush();
                bos.close();
            }
            if(in!=null){
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 文件下载(签章系统)
     * @param key
     * @param fileName
     */
    public byte[] downQzBytesByStream(String key, String fileName){
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        byte[] bytes = null;
        BufferedInputStream in = null;
        ByteArrayOutputStream outputStream = null;
        log.info("开始从云服务器加载文件，文件名：{}",fileName);
        try {
            // 创建OSSClient实例
            long start = System.currentTimeMillis();
            OSSObject ossObject = ossClient.getObject(qzBucketName, key);
            in = new BufferedInputStream(ossObject.getObjectContent());
            outputStream = new ByteArrayOutputStream();
            byte[] car=new byte[1024];
            int L=0;
            while((L=in.read(car))!=-1){
                outputStream.write(car, 0,L);
            }
            bytes = outputStream.toByteArray();
            long end = System.currentTimeMillis();
            log.info("从云服务器加载文件成功，文件名：{}，耗时：{}ms",fileName,end-start);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (in!=null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return  bytes;
    }


    /**
     * 附件下载到本地指定文件夹(签章系统)
     * @param key
     * @param fileName
     */
    public void downQzByStreamSaveLocal(String key, String fileName,String downFileStr){
        try {
            // 创建OSSClient实例
            OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
            OSSObject ossObject = ossClient.getObject(qzBucketName, key);
            BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());


            //写入到文件（注意文件保存路径的后面一定要加上文件的名称）
            FileOutputStream fileOut = new FileOutputStream(downFileStr);
            BufferedOutputStream bos = new BufferedOutputStream(fileOut);
            byte[] buf = new byte[4096];
            int length = in.read(buf);
            //保存文件
            while(length != -1)
            {
                bos.write(buf, 0, length);
                length = in.read(buf);
            }
            if(bos!=null){
                bos.flush();
                bos.close();
            }
            if(in!=null){
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 阿里云获取临时文件查看url
     * 签章文件查看
     * @param file
     */
    public String getQzFileTemporaryLookUrl(String file){
        URL url = null;
        try {
            OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);

            file = file.replace("amp;","");
            String aliyunUrl = Global.getAliyunUrl();
            String aliDownloadUrl = Global.getAliDownloadUrl();
            String cons = "";
            if (file.contains(aliyunUrl)){
                cons = aliyunUrl;
            }else if (file.contains("http://gangwan-app.oss-cn-hangzhou.aliyuncs.com")){
                cons = "http://gangwan-app.oss-cn-hangzhou.aliyuncs.com";
            }else {
                cons = aliDownloadUrl;
            }
            String key = file.split(cons+"/")[1];
            // 指定过期时间为24小时。
            Date expiration = new Date(new Date().getTime() + 1000 * 60 * 60 * 24 );
            url = ossClient.generatePresignedUrl(qzBucketName, key, expiration);

        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        return url.toString();
    }


    public String datePath(){
        Calendar date = Calendar.getInstance();
        String year = String.valueOf(date.get(Calendar.YEAR));
        String month = String.valueOf(date.get(Calendar.MONTH)+1);
        String day = String.valueOf(date.get(Calendar.DAY_OF_MONTH));
        String path = "/"+year+"/"+month+"/"+day;
        return path;
    }
}
