package com.ssj.framework.core.util;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.Callback;
import com.aliyun.oss.model.DownloadFileRequest;
import com.aliyun.oss.model.UploadFileRequest;
import com.aliyun.oss.model.UploadFileResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.ssj.framework.core.security.manager.TokenManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class OSSUtils {

    private  static Logger logger = LoggerFactory.getLogger(OSSUtils.class);

    private  static String oss_endpoint = "https://oss-cn-shenzhen-internal.aliyuncs.com";

    private  static String bucketName=PropertiesUtil.getValue("bucketName");

    private  static String sts_endpoint = "sts.aliyuncs.com";

    private  static String sts_accessKeyId =PropertiesUtil.getValue("sts_accessKeyId");

    private  static String sts_accessKeySecret =PropertiesUtil.getValue("sts_accessKeySecret");

    private  static String sts_roleArn =PropertiesUtil.getValue("sts_roleArn");

    private  static String sts_roleSessionName = "external-username";

    private static  Integer timeout=7200;//单位为秒



    private  static String policy = "{\n" +
            "    \"Version\": \"1\", \n" +
            "    \"Statement\": [\n" +
            "        {\n" +
            "            \"Action\": [\n" +
            "                \"oss:*\"\n" +
            "            ], \n" +
            "            \"Resource\": [\n" +
            "                \"acs:oss:*:*:*\" \n" +
            "            ], \n" +
            "            \"Effect\": \"Allow\"\n" +
            "        }\n" +
            "    ]\n" +
            "}";

    //请求STS权限

    public  static  synchronized Map<String,String> getSTSSecurityToken(){
        Map<String,String>  stsMap=new HashMap<>();
        TokenManager tokenManager= SystemResourceLocator.getBean(TokenManager.class);
        String accessKeyId=tokenManager.getString("accessKeyId");
        String accessKeySecret=tokenManager.getString("accessKeySecret");
        String securityToken= tokenManager.getString("securityToken");


        if(accessKeyId!=null && accessKeySecret!=null && securityToken!=null){
            stsMap.put("accessKeyId" , accessKeyId);
            stsMap.put("accessKeySecret" , accessKeySecret);
            stsMap.put("securityToken" ,securityToken);

            return  stsMap;
        }

        Long lo =tokenManager.setnx("STSSecurityToken","1");
        if(lo==1){
            try {
                // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
                DefaultProfile.addEndpoint("", "", "Sts", sts_endpoint);
                // 构造default profile（参数留空，无需添加region ID）
                IClientProfile profile = DefaultProfile.getProfile("", sts_accessKeyId, sts_accessKeySecret);
                // 用profile构造client
                DefaultAcsClient client = new DefaultAcsClient(profile);
                final AssumeRoleRequest request = new AssumeRoleRequest();
                request.setMethod(MethodType.POST);
                request.setRoleArn(sts_roleArn);
                request.setRoleSessionName(sts_roleSessionName);
                request.setPolicy(policy); // Optional
                request.setDurationSeconds(30*60L);
                final AssumeRoleResponse response = client.getAcsResponse(request);
                stsMap=new HashMap<>();
                stsMap.put("expiration" , response.getCredentials().getExpiration());
                stsMap.put("accessKeyId" , response.getCredentials().getAccessKeyId());
                stsMap.put("accessKeySecret" , response.getCredentials().getAccessKeySecret());
                stsMap.put("securityToken" ,response.getCredentials().getSecurityToken());
                stsMap.put("requestId" , response.getRequestId());


                tokenManager.setString("accessKeyId",stsMap.get("accessKeyId"),25*60);
                tokenManager.setString("accessKeySecret",stsMap.get("accessKeySecret"),25*60);
                tokenManager.setString("securityToken",stsMap.get("securityToken"),25*60);

                tokenManager.delString("STSSecurityToken");

            } catch (ClientException e) {
                logger.error("STS请求Security Token异常....");
                e.printStackTrace();
            }
        }else{
            try{
                logger.error("STS请求Security Token休眠2秒....");
                Thread.sleep(2000);
                tokenManager.delString("STSSecurityToken");
                return  getSTSSecurityToken();
            }catch (java.lang.InterruptedException e){

            }

        }

        return  stsMap;
    }



    //取得临时权限OSS对象
    public static OSSClient getOSSClient(){
        OSSClient ossClient=null;
        Map<String,String>  stsMap= getSTSSecurityToken();
        if(stsMap!=null){
            String   accessKeyId=stsMap.get("accessKeyId");
            String  accessKeySecret=stsMap.get("accessKeySecret");
            String  securityToken= stsMap.get("securityToken");
            ossClient = new OSSClient(oss_endpoint, new DefaultCredentialProvider(accessKeyId, accessKeySecret,securityToken),null);
        }
        return ossClient;
    }



    //重载方法 下载文件
    public void downloadFile(String downloadPath,String key){
        downloadFile(bucketName,downloadPath,key);
    }

    //重载方法 下载文件
    public void downloadFile(String bucketName,String downloadPath,String key){
        OSSClient ossClient=OSSUtils.getOSSClient();
        try {
            DownloadFileRequest downloadFileRequest=new DownloadFileRequest(bucketName, key);
            downloadFileRequest.setDownloadFile(downloadPath);
            ossClient.downloadFile(downloadFileRequest);
        } catch (Throwable e) {
            logger.error("OSS上传异常...");
            e.printStackTrace();
        }finally{
            ossClient.shutdown();
        }
    }

    //重载方法 上传文件
    public static String uploadFile(String uploadPath,String key){
        return uploadFile(bucketName,uploadPath,key);
    }


    //重载方法 上传文件
    public static String uploadFile(String bucketName,String uploadPath,String key){
        OSSClient ossClient=OSSUtils.getOSSClient();
        try {
            String keys=key.substring(0,1);
            if("/".equals(keys)){
                key=key.replaceFirst(keys, "");
            }

            UploadFileRequest uploadFileRequest=new UploadFileRequest(bucketName, key);
            uploadFileRequest.setUploadFile(uploadPath);
            ossClient.uploadFile(uploadFileRequest);
        } catch (Throwable e) {
            logger.error("OSS上传异常...");
            e.printStackTrace();
        }finally{
            ossClient.shutdown();
        }


        return   key;

    }

    /**
     *  判断文件是否存在
     * @param fileName
     * @return
     */
    public static Boolean doesObjectExist(String fileName){
        Boolean result =false;
        OSSClient ossClient=OSSUtils.getOSSClient();
        try {
            String fileNames=fileName.substring(0,1);
            if("/".equals(fileNames)){
                fileName=fileName.replaceFirst(fileNames, "");
            }
            result=   ossClient.doesObjectExist( bucketName,fileName);
            logger.error("文件是否存在doesObjectExist="+result);
        } catch (Throwable e) {
            logger.error("OSS删除异常...");
            e.printStackTrace();
        }finally{
            ossClient.shutdown();
        }
        return   result;
    }

    //删除文件
    public static String deleteFile(String bucketName,String key){
        OSSClient ossClient=OSSUtils.getOSSClient();
        try {
            ossClient.deleteObject(bucketName, key);
        } catch (Throwable e) {
            logger.error("OSS删除异常...");
            e.printStackTrace();
        }finally{
            ossClient.shutdown();
        }
        return   key;

    }

    public static String uploadInputStream(InputStream input, String key){
        return uploadInputStream(bucketName,input,key);
    }

    public static String uploadInputStream(String bucketName, InputStream input, String key){

        OSSClient ossClient=OSSUtils.getOSSClient();
        try {
            String keys=key.substring(0,1);
            if("/".equals(keys)){
                key=key.replaceFirst(keys, "");
            }
            ossClient.putObject(bucketName, key,input);
        } catch (Throwable e) {
            logger.error("OSS上传异常...");
            e.printStackTrace();
        }finally{
            ossClient.shutdown();
        }

        return   key;
    }



    //重载方法 单位为秒
    public static String getFileUrl(String fileName){
        return getFileUrl(bucketName,fileName,timeout);
    }

    //重载方法 单位为秒
    public static String getFileUrl(String fileName,Integer timeout){
        return getFileUrl(bucketName,fileName,timeout);
    }

    //重载方法 单位为秒
    public static String getFileUrl(String bucketName,String fileName,Integer timeout){
        OSSClient ossClient=OSSUtils.getOSSClient();
        String imgurl =null;
        try {
            Date expiration = new Date(System.currentTimeMillis() + timeout * 1000);
            imgurl =ossClient.generatePresignedUrl(bucketName, fileName, expiration).toString();
        }catch (Throwable e) {
            logger.error("OSS查询KEY异常...");
            e.printStackTrace();
        }finally{
            ossClient.shutdown();
        }
        return imgurl;
    }

}
