package com.qmth.boot.core.fss.utils;

import com.qmth.boot.core.exception.UnauthorizedException;
import com.qmth.boot.tools.codec.CodecUtils;
import com.qmth.boot.tools.models.ByteArray;
import org.apache.commons.lang3.StringUtils;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Arrays;

public class FssSigner {

    private String bucket;

    private String secret;

    public FssSigner(String bucket, String secret) {
        this.bucket = bucket;
        this.secret = ByteArray.sha1(bucket + ":" + secret).toHexString();
    }

    public String getBucket() {
        return bucket;
    }

    public String buildUrlParam(String path, Duration expireDuration) {
        long expireTime = System.currentTimeMillis() + expireDuration.toMillis();
        return FssUtils.INNER_ENDPOINT_PARAM_EXPIRE_TIME + "=" + expireTime + "&" + FssUtils.INNER_ENDPOINT_PARAM_BUCKET
                + "=" + CodecUtils.urlEncode(bucket) + "&" + FssUtils.INNER_ENDPOINT_PARAM_SIGNATURE + "="
                + buildSignature(path, expireTime);
    }

    public void validate(String bucket, String path, long expireTime, String signature) {
        if (!this.bucket.equals(bucket)) {
            throw new UnauthorizedException("bucket is invalid");
        }
        if (expireTime < System.currentTimeMillis()) {
            throw new UnauthorizedException("time has expired");
        }
        if (!buildSignature(path, expireTime).equals(signature)) {
            throw new UnauthorizedException("signature is invalid");
        }
    }

    private String buildSignature(String path, long expireTime) {
        return ByteArray.fromArray(CodecUtils.hmacsha256(secret.getBytes(StandardCharsets.UTF_8),
                StringUtils.join(Arrays.asList(bucket, path, expireTime, secret), "\t")
                        .getBytes(StandardCharsets.UTF_8))).toHexString().toLowerCase();
    }
}
