package webhook

import (
	"crypto/hmac"
	"crypto/sha256"
	"crypto/subtle"
	"encoding/hex"
	"errors"
	"fmt"
	"strings"
)

const signaturePrefix = "sha256="

var (
	ErrMissingSignature = errors.New("missing webhook signature")
	ErrInvalidSignature = errors.New("invalid webhook signature")
)

// VerifySignature validates the Bitbucket X-Hub-Signature header against the raw body.
func VerifySignature(secret string, rawBody []byte, header string) error {
	header = strings.TrimSpace(header)
	if header == "" {
		return ErrMissingSignature
	}
	if !strings.HasPrefix(header, signaturePrefix) {
		return ErrInvalidSignature
	}
	gotHex := strings.TrimPrefix(header, signaturePrefix)
	got, err := hex.DecodeString(gotHex)
	if err != nil {
		return ErrInvalidSignature
	}

	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write(rawBody)
	expected := mac.Sum(nil)

	if subtle.ConstantTimeCompare(got, expected) != 1 {
		return ErrInvalidSignature
	}
	return nil
}

// SignBody computes the X-Hub-Signature value for testing.
func SignBody(secret string, rawBody []byte) string {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write(rawBody)
	return fmt.Sprintf("%s%s", signaturePrefix, hex.EncodeToString(mac.Sum(nil)))
}
