package com.jeeplus.pubmodules.oss.service;

import cn.hutool.extra.spring.SpringUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
//import com.jeeplus.sys.utils.Global;
import com.jeeplus.sys.feign.IWorkAttachmentApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.mock.web.MockMultipartFile;

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

@Slf4j
@Service
public class OSSClientService {

    @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;

    private static final String DIRECTORY = "/attachment-file";

    private static final String ALIYUNURL = "http://oss.gangwaninfo.com";
    /**
     * 上传到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;
    }
    /**
     * 上传到OSS服务器  如果同名文件会覆盖服务器上的
     *
     * @param fileName 文件名称 包括后缀名
     * @return 出错返回"" ,唯一MD5数字签名
     */
    public String uploadFileSignatureOSS(String filePath, String fileDir, String fileName) {
        //初始化OSSClient
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        File f = new File(filePath);

        try {
        MultipartFile cMultiFile = new MockMultipartFile("file", f.getName(), null, new FileInputStream(f));
        if (!cMultiFile.isEmpty()) {
            //文件原名称
            String newName = cMultiFile.getOriginalFilename();
            InputStream inStream = cMultiFile.getInputStream();
            if(StringUtils.isNotBlank(newName)){

                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;
            }
        }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得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();
        }
    }

    /**
     * 根据路径下载所有文件到本地指定文件夹
     */
    public void downloadFolderFromOss(String prefix, String localDir) {
        OSSClient ossClient = null;
        try {
            ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

            ListObjectsRequest request = new ListObjectsRequest(bucketName);
            request.setPrefix(prefix); // OSS 文件夹前缀
            request.setMaxKeys(1000);

            ObjectListing listing;

            do {
                listing = ossClient.listObjects(request);


                for (OSSObjectSummary summary : listing.getObjectSummaries()) {
                    String objectKey = summary.getKey();

                    // 跳过“文件夹”
                    if (objectKey.endsWith("/")) {
                        continue;
                    }

                    // 本地文件路径
                    String localFilePath = localDir + File.separator
                            + objectKey.substring(prefix.length());

                    File localFile = new File(localFilePath);

                    // 创建父目录
                    if (!localFile.getParentFile().exists()) {
                        localFile.getParentFile().mkdirs();
                    }

                    // 下载文件
                    OSSObject ossObject = ossClient.getObject(bucketName, objectKey);
                    try (
                            InputStream in = new BufferedInputStream(ossObject.getObjectContent());
                            OutputStream out = new BufferedOutputStream(new FileOutputStream(localFile))
                    ) {
                        byte[] buffer = new byte[4096];
                        int len;
                        while ((len = in.read(buffer)) != -1) {
                            out.write(buffer, 0, len);
                        }
                    }
                }

                request.setMarker(listing.getNextMarker());
            } while (listing.isTruncated());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 文件下载(签章系统)
     * @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;
    }

    // 文件下载和上传方法
    public String downloadAndUploadToOSS(String fileUrl,String fileName,String dir) {
        // 创建OSS客户端
        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);

        InputStream inputStream = null;
        try {
            // Step 1: 下载文件
            inputStream = downloadFile(fileUrl);
            String realPath =DIRECTORY.replaceFirst("/","")+"/"+ dir +datePath()+"/"+ System.currentTimeMillis();
            String ret = uploadFile2OSS(inputStream,realPath,fileName);
            // Step 2: 上传到OSS
            return "/"+realPath+fileName;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            // 关闭资源
            try {
                if (inputStream != null) inputStream.close();
            } catch (IOException ignored) {}
            ossClient.shutdown();
        }
    }
    public static InputStream downloadFile(String fileUrl) throws Exception {
        URL url = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);

        if (connection.getResponseCode() == 200) {
            return connection.getInputStream();
        } else {
            throw new RuntimeException("Failed to download file, response code: " + connection.getResponseCode());
        }
    }

}
