package middleware

import (
	"context"
	"errors"
)

// ctxKey is an unexported type for request-scoped authentication values.
// Using a distinct type (rather than a bare string) keeps our keys out of
// collision range for any other package that also calls context.WithValue,
// and silences go vet's SA1029.
type ctxKey string

const (
	ctxKeyUserAddress   ctxKey = "user_address"
	ctxKeyUserTrack     ctxKey = "user_track"
	ctxKeyAuthenticated ctxKey = "authenticated"
)

// Default track level applied to unauthenticated requests (Track 1 = public).
const defaultTrackLevel = 1

// ErrMissingAuthorization is returned by extractAuth when no usable
// Authorization header is present on the request. Callers should treat this
// as "no auth supplied" rather than a hard failure for optional-auth routes.
var ErrMissingAuthorization = errors.New("middleware: authorization header missing or malformed")

// ContextWithAuth returns a child context carrying the supplied
// authentication state. It is the single place in the package that writes
// the auth context keys.
func ContextWithAuth(parent context.Context, address string, track int, authenticated bool) context.Context {
	ctx := context.WithValue(parent, ctxKeyUserAddress, address)
	ctx = context.WithValue(ctx, ctxKeyUserTrack, track)
	ctx = context.WithValue(ctx, ctxKeyAuthenticated, authenticated)
	return ctx
}

// UserAddress returns the authenticated wallet address stored on ctx, or
// "" if the context is not authenticated.
func UserAddress(ctx context.Context) string {
	addr, _ := ctx.Value(ctxKeyUserAddress).(string)
	return addr
}

// UserTrack returns the access tier recorded on ctx. If no track was set
// (e.g. the request bypassed all auth middleware) the caller receives
// Track 1 (public) so route-level checks can still make a decision.
func UserTrack(ctx context.Context) int {
	if track, ok := ctx.Value(ctxKeyUserTrack).(int); ok {
		return track
	}
	return defaultTrackLevel
}

// IsAuthenticated reports whether the current request carried a valid auth
// token that was successfully parsed by the middleware.
func IsAuthenticated(ctx context.Context) bool {
	ok, _ := ctx.Value(ctxKeyAuthenticated).(bool)
	return ok
}
