package middleware

import (
	"context"
	"io"
	"net/http"

	"apps/backend/internal/response"
)

const stripeWebhookMaxBytes = 1 << 20

type stripeRawBodyKey struct{}
type stripeSignatureKey struct{}

type StripeRawBodyMiddleware struct {
}

func NewStripeRawBodyMiddleware() *StripeRawBodyMiddleware {
	return &StripeRawBodyMiddleware{}
}

func (m *StripeRawBodyMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		body, err := io.ReadAll(http.MaxBytesReader(w, r.Body, stripeWebhookMaxBytes))
		if err != nil {
			response.Fail(w, http.StatusRequestEntityTooLarge, 413001, "webhook payload too large", nil)
			return
		}
		ctx := context.WithValue(r.Context(), stripeRawBodyKey{}, body)
		ctx = context.WithValue(ctx, stripeSignatureKey{}, r.Header.Get("Stripe-Signature"))
		next(w, r.WithContext(ctx))
	}
}

func StripeWebhookPayload(ctx context.Context) ([]byte, string, bool) {
	payload, payloadOK := ctx.Value(stripeRawBodyKey{}).([]byte)
	signature, signatureOK := ctx.Value(stripeSignatureKey{}).(string)
	return payload, signature, payloadOK && signatureOK
}
