package com.gree.mall.manager.utils.oss;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;


@Service
@Slf4j
public class OSSUtil {

    @Value("${ali.access.key.id}")
    private String ACCESS_KEY_ID;
    @Value("${ali.access.key.secert}")
    private String ACCESS_KEY_SECERT;

    @Value("${ali.oss.bucket.name}")
    private String OSS_BUCKET_NAME;
    @Value("${ali.oss.endpoint.ww}")
    private String OSS_ENDPOINT_WW;
    @Value("${ali.oss.endpoint}")
    private String OSS_ENDPOINT;
    @Value("${ali.cdn.url}")
    private String CDN_URL;
    @Value("${spring.profiles.active}")
    private String active;

    public String getAccessUrl(){
        return "https://" + OSS_BUCKET_NAME +"."+ OSS_ENDPOINT_WW;
    }

    public String getFilePath() {
        String month = new SimpleDateFormat("yyyy-MM").format(new Date());
        return month;
    }

    public OSS buildClient(){
        return new OSSClientBuilder().build(OSS_ENDPOINT_WW, ACCESS_KEY_ID, ACCESS_KEY_SECERT);
    }

    /**
     * 上传到oss
     *
     * @param ossObjectKey 附件的唯一路径名称
     * @param file         附件
     * @return
     */
    public boolean uploadFile(String ossObjectKey, File file) {
        PutObjectResult putObjectResult = buildClient().putObject(new PutObjectRequest(OSS_BUCKET_NAME, ossObjectKey, file));
        log.info("putObjectResult" + putObjectResult);
        return true;
    }

    public boolean uploadFile(String ossObjectKey, byte[] file) {
        PutObjectResult putObjectResult = buildClient().putObject(new PutObjectRequest(OSS_BUCKET_NAME, ossObjectKey, new ByteArrayInputStream(file)));
        log.info("putObjectResult" + putObjectResult);
        return true;
    }

    public boolean uploadFile(String ossObjectKey, ByteArrayInputStream byteArrayInputStream) {
        PutObjectResult putObjectResult = buildClient().putObject(new PutObjectRequest(OSS_BUCKET_NAME, ossObjectKey, byteArrayInputStream));
        log.info("putObjectResult" + putObjectResult);
        return true;
    }

    public String uploadFile(InputStream inputStream,String uploadFileSuffix){
        long currentTime = new Date().getTime();
        if(StringUtils.indexOf(uploadFileSuffix,".") == -1){
            uploadFileSuffix = "."+uploadFileSuffix;
        }
        String filePath = this.getFilePath() + "/" + currentTime + UUID.randomUUID().toString() + uploadFileSuffix;
        PutObjectResult putObjectResult = buildClient().putObject(new PutObjectRequest(OSS_BUCKET_NAME, filePath, inputStream));
        log.info("putObjectResult" + putObjectResult);
        return this.getAccessUrl() + filePath;
    }

    public String uploadFile(byte[] bytes,String uploadFileSuffix){
        long currentTime = new Date().getTime();
        if(StringUtils.indexOf(uploadFileSuffix,".") == -1){
            uploadFileSuffix = "."+uploadFileSuffix;
        }
        String filePath = this.getFilePath() + "/" + currentTime + UUID.randomUUID().toString() + uploadFileSuffix;
        PutObjectResult putObjectResult = buildClient().putObject(new PutObjectRequest(OSS_BUCKET_NAME, filePath, new ByteArrayInputStream(bytes)));
        log.info("putObjectResult" + putObjectResult);
        return this.getAccessUrl() + filePath;
    }

    public boolean uploadFile(String ossObjectKey, InputStream inputStream) {
        PutObjectResult putObjectResult = buildClient().putObject(new PutObjectRequest(OSS_BUCKET_NAME, ossObjectKey, inputStream));
        log.info("putObjectResult" + putObjectResult);
        return true;
    }


    public boolean uploadFile(String ossObjectKey, InputStream inputStream, Long second) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(OSS_BUCKET_NAME, ossObjectKey, inputStream);
        //文件过期时间
        putObjectRequest.addHeader("x-oss-expires", second + "");
        PutObjectResult putObjectResult = buildClient().putObject(putObjectRequest);
        log.info("putObjectResult" + putObjectResult);
        return true;
    }


    public Map<String, String> getConfig() throws UnsupportedEncodingException {
        OSS client = buildClient();
        String host = "https://" + OSS_BUCKET_NAME + "." + OSS_ENDPOINT_WW; // host的格式为 bucketname.endpoint

        if (!StringUtils.isEmpty(CDN_URL)) {
            host = CDN_URL;
        }

//        OSSClient client = new OSSClient(endpoint, accessId, accessKey);
        long expireTime = 300;
        long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
        java.sql.Date expiration = new java.sql.Date(expireEndTime);
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, getFilePath());

        String postPolicy = client.generatePostPolicy(expiration, policyConds);
        byte[] binaryData = postPolicy.getBytes("utf-8");
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = client.calculatePostSignature(postPolicy);

        Map<String, String> respMap = new LinkedHashMap<String, String>();
        respMap.put("OSSAccessKeyId", ACCESS_KEY_ID);
        respMap.put("expire", String.valueOf(expireEndTime / 1000));
        respMap.put("policy", encodedPolicy);
        respMap.put("signature", postSignature);
        respMap.put("id", ACCESS_KEY_ID);
        respMap.put("dir", getFilePath()+"/");
        respMap.put("host", host);
        return respMap;
    }


    public String getUrl(String key) {
        if (StringUtils.isEmpty(key)) {
            return "";
        }
        // 设置URL过期时间为1小时
        Date expiration = new Date(new Date().getTime() + 3600 * 1000);
        GeneratePresignedUrlRequest generatePresignedUrlRequest;
        generatePresignedUrlRequest = new GeneratePresignedUrlRequest(OSS_BUCKET_NAME, key);
        generatePresignedUrlRequest.setExpiration(expiration);
        URL url = buildClient().generatePresignedUrl(generatePresignedUrlRequest);
        return url.toString();
    }

    public URL getUrl2(String key) {
        // 设置URL过期时间为1小时
        Date expiration = new Date(new Date().getTime() + 3600 * 1000);
        GeneratePresignedUrlRequest generatePresignedUrlRequest;
        generatePresignedUrlRequest = new GeneratePresignedUrlRequest(OSS_BUCKET_NAME, key);
        generatePresignedUrlRequest.setExpiration(expiration);
        return buildClient().generatePresignedUrl(generatePresignedUrlRequest);
    }


    public String getUrlWw(String key) {
        return getUrlWw(key, null);
    }

    public String getUrlWw(String key, MediaType mediaType) {
        if (StringUtils.isEmpty(key)) {
            return "";
        }
        // 设置URL过期时间为1小时
        Date expiration = new Date(new Date().getTime() + 3600 * 1000);
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(OSS_BUCKET_NAME, key);
        request.setExpiration(expiration);
        if (mediaType != null) {
            request.setContentType(mediaType.toString());
        }

        URL url = new OSSClientBuilder()
                .build("https://" + OSS_ENDPOINT_WW, ACCESS_KEY_ID, ACCESS_KEY_SECERT)
                .generatePresignedUrl(request);

        String resultUrl = url.toString();
        if (StringUtils.isEmpty(CDN_URL)) {
            return resultUrl;
        }
        return resultUrl.replace("https://" + OSS_BUCKET_NAME + "." + OSS_ENDPOINT_WW, CDN_URL);
    }


    public boolean imageHandle(String ossObjectKey, String style, String savePath) {
        OSS client = new OSSClientBuilder().build(OSS_ENDPOINT_WW, ACCESS_KEY_ID, ACCESS_KEY_SECERT);
        GetObjectRequest getObjectRequest = new GetObjectRequest(OSS_BUCKET_NAME, ossObjectKey);
        getObjectRequest.setProcess(style);
        log.info("getObjectRequest: {}", getObjectRequest);
        client.getObject(getObjectRequest, new File(savePath));
        return true;
    }
}
