package com.fjhx.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.springblade.core.log.exception.ServiceException;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class OssUtil {

    public static final String endpoint = "oss-cn-hangzhou.aliyuncs.com";

    public static final String accessKeyId = "LTAI4G5JQxLKhvc53izDwT4x";

    public static final String secretAccessKey = "oQBndIWAzxsNbM96zFkkFZZAAtuy1c";

    public static final String bucketName = "fzjx";

    private OssUtil() {
    }

    private static OSS getOssClient() {
        return new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
    }

    /**
     * Base64字符串上传文件
     */
    public static void uploadFile(String key, String base64) {
        ByteArrayInputStream stream;

        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bytes = decoder.decodeBuffer(base64);
            stream = new ByteArrayInputStream(bytes);
        } catch (IOException e) {
            throw new ServiceException("base64错误");
        }
        OSS ossClient = getOssClient();
        ossClient.putObject(bucketName, key, stream);
        ossClient.shutdown();
    }


    /**
     * inputStream上传文件
     */
    public static void uploadFile(String key, InputStream inputStream) {
        OSS ossClient = getOssClient();
        ossClient.putObject(bucketName, key, inputStream);
        ossClient.shutdown();
    }

    /**
     * 删除文件夹
     */
    public static void deleteFile(String key) {
        OSS ossClient = getOssClient();
        ossClient.deleteObject(bucketName, key);
        ossClient.shutdown();
    }

    /**
     * 获取文件key
     *
     * @param suffix
     * @return
     */
    public static String getFileKey(String suffix) {
        StringJoiner joiner = new StringJoiner("/");
        joiner.add("fzjs");
        joiner.add(DateUtil.format(new Date(), "yyyyMM/dd"));
        joiner.add(IdUtil.fastSimpleUUID() + "." + suffix);
        return joiner.toString();
    }

    public static String getFilePath(String fileKey) {
        return "https://" + bucketName + "." + endpoint + "/" + fileKey;
    }

    /**
     * oss前端获取签名直传
     *
     * @param fileName 文件名称，带后缀
     * @return
     */
    public static Map<String, Object> getOssSign(String fileName) {
        // 获取oss链接实例
        OSS ossClient = OssUtil.getOssClient();
        // 生成文件保存在oss中的存放位置
        String dir = getFileKey(FileUtil.getSuffix(fileName));

        HashMap<String, Object> map = new LinkedHashMap<>();
        // 生成直连签名逻辑
        try {
            long expireTime = 60;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConditions = new PolicyConditions();
            // PostObject请求最大可支持的文件大小为5 GB，在此设置最大上次文件大小为1000M
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            // MatchMode.Exact：精确匹配    MatchMode.StartWith：前缀匹配
            policyConditions.addConditionItem(MatchMode.Exact, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            // 记录签名信息
            map.put("accessId", accessKeyId);
            map.put("policy", encodedPolicy);
            map.put("signature", postSignature);
            map.put("dir", dir);
            map.put("host", getFilePath(""));
            map.put("fileUrl", getFilePath(dir));

        } catch (Exception e) {
            throw new ServiceException("获取oss前端直传签名失败");
        } finally {
            ossClient.shutdown();
        }

        return map;
    }
}
