package auth

import (
	"strings"
	"time"
)

// TokenAuth verifies Bearer credentials against the TokenStore and throttles
// brute force. Unlike the login throttle (keyed on username+IP), a Bearer token
// has no "login" step to rate-limit, so guesses are throttled by source IP
// alone. The window is looser than login's because a legitimate dashboard may
// fire many requests in a minute - only repeated *failures* count.
type TokenAuth struct {
	store    *TokenStore
	throttle *failLimiter
}

// NewTokenAuth wraps a store with an IP-keyed failure throttle.
func NewTokenAuth(store *TokenStore) *TokenAuth {
	return &TokenAuth{store: store, throttle: newFailLimiter(20, time.Minute)}
}

// Verify resolves a presented Bearer token to its name. throttled is true when
// the source IP is in cooldown after too many bad tokens; the caller should
// answer 429 without consulting the store.
func (a *TokenAuth) Verify(ip, raw string) (name string, ok, throttled bool) {
	if a.throttle.blocked(ip) {
		return "", false, true
	}
	name, found := a.store.Lookup(raw)
	if !found {
		a.throttle.fail(ip)
		return "", false, false
	}
	a.throttle.reset(ip)
	return name, true, false
}

// BearerToken extracts the credential from an Authorization header value,
// reporting whether it was a Bearer scheme. Returns ("", false) for cookie-only
// or unauthenticated requests.
func BearerToken(authHeader string) (string, bool) {
	if len(authHeader) <= 7 || !strings.EqualFold(authHeader[:7], "Bearer ") {
		return "", false
	}
	return strings.TrimSpace(authHeader[7:]), true
}
