package com.mall.thirdParty.service.impl;

import com.aliyun.oss.common.utils.BinaryUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mall.thirdParty.client.AliOssClient;
import com.mall.thirdParty.service.AliOssService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.mall.thirdParty.service.ext.AliOssServiceImplExt.*;

@Service
@RequiredArgsConstructor
public class AliOssServiceImpl implements AliOssService {

    private final AliOssClient aliOssClient;

    /**
     * OSS获取服务端签名
     *
     * @return OSS服务端签名
     */
    @SneakyThrows
    public Map<String, String> getPostSignatureForOssUpload() {
        // 基础信息获取
        String accesskeyid = aliOssClient.getAccessKeyId();
        String accesskeysecret = aliOssClient.getAccessKeySecrect();
        String uploadDir = "images/" + LocalDate.now().format(DateTimeFormatter.ISO_DATE);
        String region = aliOssClient.getRegion();
        String bucket = aliOssClient.getBucketName();

        // 时间格式化
        ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
        String date = now.format(DateTimeFormatter.BASIC_ISO_DATE);
        String xOssDate = now.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));
        String xOssCredential = String.format("%s/%s/%s/oss/aliyun_v4_request", accesskeyid, date, region);

        // 创建policy
        Map<String, Object> policy = new HashMap<>();
        policy.put("expiration", generateExpiration(3600L));

        List<Object> conditions = Arrays.asList(
                Map.of("bucket", bucket),
                Map.of("x-oss-signature-version", "OSS4-HMAC-SHA256"),
                Map.of("x-oss-credential", xOssCredential),
                Map.of("x-oss-date", xOssDate),
                Arrays.asList("content-length-range", 1, 10240000),
                Arrays.asList("eq", "$success_action_status", "200"),
                Arrays.asList("starts-with", "$key", uploadDir)
        );
        policy.put("conditions", conditions);

        // 签名计算
        String jsonPolicy = new ObjectMapper().writeValueAsString(policy);
        String stringToSign = Base64.encodeBase64String(jsonPolicy.getBytes());

        byte[] signingKey = calculateSigningKey(accesskeysecret, date, region);
        String signature = BinaryUtil.toHex(hmacsha256(signingKey, stringToSign));

        // 构建返回结果
        return Map.of(
                "version", "OSS4-HMAC-SHA256",
                "policy", stringToSign,
                "x_oss_credential", xOssCredential,
                "x_oss_date", xOssDate,
                "signature", signature,
                "dir", uploadDir,
                "accessId", aliOssClient.getAccessKeyId(),
                "host", aliOssClient.getEndpoint()
        );
    }

}
