package com.njyunzhi.pet_identity.common;

import com.aliyun.oss.OSSClient;
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.njyunzhi.pet_identity.config.AliyunConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class OSSUtils {

    private final static String STS_ENDPOINT = "sts.aliyuncs.com";

    @Autowired
    AliyunConfig aliyunConfig;

    private String getMonth() {
        return DateTimeFormatter.ofPattern("yyyyMM").format(LocalDateTime.now());
    }

    private String getUploadPath(String[] toDirs) {
        String path = toDirs.length > 0 ? toDirs[0] : "/";
        if (!path.endsWith("/")) {
            path += "/";
        }

        return path + getMonth() + "/";
    }

    /**
     * 上传 base64
     * @param base64Str
     * @param toDirs
     * @return
     * @throws IOException
     */
    public String putObject(String base64Str, String ...toDirs) throws IOException {
        int index = base64Str.indexOf("base64,");

        if (index > -1) {
            index += 7;
        } else {
            index = 0;
        }

        String dataStr = base64Str.substring(index);
        byte[] data = Base64.getDecoder().decode(dataStr);
        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
        String toDir = getUploadPath(toDirs);
        String nwFName = toDir + System.currentTimeMillis() + ".png";
        nwFName = StringUtils.trim(nwFName,"/");
        return putFile(nwFName, inputStream);
    }

    /**
     * 上传文件
     * @param mf 上传的文件
     * @param toDirs 上传到的目录
     * @return
     */
    public String putObject(MultipartFile mf, String ... toDirs) throws IOException {
        String fName = formatFileName(mf.getOriginalFilename());
        String preFix = String.valueOf(System.currentTimeMillis());
        String toDir = getUploadPath(toDirs);
        String nwFName = toDir + preFix + "-" + fName;
        nwFName = StringUtils.trim(nwFName,"/");

        return putFile(nwFName, new ByteArrayInputStream(mf.getBytes()));
    }

    public String putObject(File f, String ... toDirs) throws FileNotFoundException {
        String fName = formatFileName(f.getName());
        String preFix = String.valueOf(System.currentTimeMillis());
        String toDir = getUploadPath(toDirs);
        String nwFName = toDir + preFix + "-" + fName;
        nwFName = StringUtils.trim(nwFName,"/");

        InputStream inputStream = new FileInputStream(f);
        return putFile(nwFName, inputStream);
    }

    public String putObject(InputStream inputStream, String fName, String ... toDirs) {
        String toDir = getUploadPath(toDirs);
        String nwFName = toDir + fName;
        nwFName = StringUtils.trim(nwFName,"/");
        return putFile(nwFName, inputStream);
    }

    private String formatFileName(String fName) {
        return StringUtils.ifNull(fName, StringUtils.random(16) + ".png");
    }

    private String putFile(String fname, InputStream input) {
        OSSClient ossClient = new OSSClient(aliyunConfig.getOss().getEndpoint(), aliyunConfig.getAccessKeyId(), aliyunConfig.getAccessKeySecret());
        ossClient.putObject(aliyunConfig.getOss().getBucketName(), fname, input);
        ossClient.shutdown();

        // String url = ossClient.generatePresignedUrl(AliOSSUtils.oss.getBucketName(), fname, expiration).toString();

        String preURL = aliyunConfig.getOss().getBucketURL();
        if (!preURL.endsWith("/")) {
            preURL += "/";
        }

        return preURL + fname.replaceAll("\\ ", "%20").replaceAll("\\'", "%27");
    }

    /**
     * 获取上传凭证
     * @return
     * @throws Exception
     */
    public Map<String, Object> getSTSAKToken() throws Exception {
        AliyunConfig.Oss oss = aliyunConfig.getOss();

        try {
            // 添加endpoint（直接使用STS endpoint，无需添加region ID）
            DefaultProfile.addEndpoint("", "Sts", STS_ENDPOINT);
            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("", oss.getAccessKeyId(), oss.getAccessKeySecret());

            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setSysMethod(MethodType.POST);
            request.setRoleArn(oss.getArn());
            request.setRoleSessionName(oss.getRoleSessionName());
            request.setPolicy(null); // 若policy为空，则用户将获得该角色下所有权限
            request.setDurationSeconds(30 * 60L); // 设置凭证有效时间 1800 秒 = 30 分钟
            final AssumeRoleResponse response = client.getAcsResponse(request);

            AssumeRoleResponse.Credentials credentials = response.getCredentials();

            Map<String, Object> res = new HashMap<>();
            res.put("stsToken", credentials.getSecurityToken());
            res.put("accessKeySecret", credentials.getAccessKeySecret());
            res.put("accessKeyId", credentials.getAccessKeyId());
            res.put("expiration", credentials.getExpiration());

            return res;
        } catch (ClientException e) {
            e.printStackTrace();
            log.error("Error code: " + e.getErrCode());
            log.error("Error message: " + e.getErrMsg());
            log.error("RequestId: " + e.getRequestId());
            throw new Exception(e.getMessage());
        }
    }

}
