package webshared

import (
	"encoding/base64"
	"strings"

	"git.mstar.dev/mstar/linstrom/shared"
)

// Generate the signed string of the headers, method and target
// and sign it using the given RSA key. Returns the base64 encoded
// result
func CreateSignatureRSA(
	method string,
	target string,
	headers map[string]string,
	privateKeyBytes []byte,
) (string, error) {
	message := genPreSignatureString(method, target, headers)
	signed, err := shared.Sign(message, privateKeyBytes, true)
	return base64.StdEncoding.EncodeToString(signed), err
}

// Generate the signed string of the headers, method and target
// and sign it using the given ED25519 key. Returns the base64
// encoded result
func CreateSignatureED(
	method string,
	target string,
	headers map[string]string,
	privateKeyBytes []byte,
) (string, error) {
	message := genPreSignatureString(method, target, headers)
	signed, err := shared.Sign(message, privateKeyBytes, false)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(signed), nil
}

func genPreSignatureString(method, target string, headers map[string]string) string {
	dataBuilder := strings.Builder{}
	dataBuilder.WriteString("(request-target) ")
	dataBuilder.WriteString(strings.ToLower(method) + " ")
	dataBuilder.WriteString(target + "\n")
	for k, v := range headers {
		dataBuilder.WriteString(k + ": " + v + "\n")
	}
	return dataBuilder.String()
}

// Generate the content of the "Signature" header based on
// The user who's key was used, the hashed and base64 encoded
// signed string, as returned by CreateSignatureED/RSA
func CreateSignatureHeaderContent(userId string, hash string, headerNames ...string) string {
	builder := strings.Builder{}
	builder.WriteString("keyId=\"")
	builder.WriteString(userId)
	builder.WriteString("\",headers=\"")
	for i, header := range headerNames {
		builder.WriteString(header)
		if i+1 < len(headerNames) {
			builder.WriteRune(' ')
		}
	}
	builder.WriteString("\",signature=\"")
	builder.WriteString(hash)
	builder.WriteRune('"')

	return builder.String()
}
