package gateway

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"net/http"
)

var errRequestBodyTooLarge = errors.New("request body is too large")

func prepareTokenBudget(request *http.Request, maxBody int64) (int64, error) {
	if request.Body == nil || request.Method == http.MethodGet {
		return 0, nil
	}
	limited := io.LimitReader(request.Body, maxBody+1)
	body, err := io.ReadAll(limited)
	if err != nil {
		return 0, err
	}
	_ = request.Body.Close()
	if int64(len(body)) > maxBody {
		return 0, errRequestBodyTooLarge
	}
	restoreRequestBody(request, body)

	inputEstimate := max(int64((len(body)+3)/4), 1)
	if request.URL.Path == "/v1/embeddings" {
		return inputEstimate, nil
	}
	outputBudget := int64(1024)
	decoder := json.NewDecoder(bytes.NewReader(body))
	decoder.UseNumber()
	var payload map[string]any
	if decoder.Decode(&payload) == nil {
		for _, field := range []string{"max_output_tokens", "max_completion_tokens", "max_tokens"} {
			if value := jsonInt64(payload[field]); value > 0 {
				outputBudget = value
				break
			}
		}
	}
	// A per-request ceiling prevents malicious payloads from reserving unbounded Redis counters.
	return min(inputEstimate+outputBudget, int64(100_000_000)), nil
}
