// Package auth provides authentication utilities for HTTP services.
//
// This package supports multiple authentication methods:
//   - API Key authentication (X-API-Key header)
//   - JWT Bearer token authentication
//
// Usage:
//
//	// Create a validator
//	validator := auth.NewJWTValidator(auth.JWTConfig{
//	    Secret: []byte("your-secret"),
//	})
//
//	// Use as middleware
//	r.Use(auth.Middleware(validator))
//
//	// Access user in handler
//	user := auth.GetUser(r.Context())
package auth

import (
	"context"
)

// User represents an authenticated user/principal.
type User struct {
	// ID is the unique identifier for the user
	ID string `json:"id"`
	// Email is the user's email address (optional)
	Email string `json:"email,omitempty"`
	// Roles are the user's assigned roles
	Roles []string `json:"roles,omitempty"`
	// Scopes are the permitted scopes/permissions
	Scopes []string `json:"scopes,omitempty"`
	// Metadata contains additional user data
	Metadata map[string]any `json:"metadata,omitempty"`
}

// HasRole checks if the user has a specific role.
func (u *User) HasRole(role string) bool {
	for _, r := range u.Roles {
		if r == role {
			return true
		}
	}
	return false
}

// HasAnyRole checks if the user has any of the specified roles.
func (u *User) HasAnyRole(roles ...string) bool {
	for _, role := range roles {
		if u.HasRole(role) {
			return true
		}
	}
	return false
}

// HasScope checks if the user has a specific scope.
func (u *User) HasScope(scope string) bool {
	for _, s := range u.Scopes {
		if s == scope {
			return true
		}
	}
	return false
}

// HasAnyScope checks if the user has any of the specified scopes.
func (u *User) HasAnyScope(scopes ...string) bool {
	for _, scope := range scopes {
		if u.HasScope(scope) {
			return true
		}
	}
	return false
}

// Validator validates authentication credentials and returns a User.
type Validator interface {
	// Validate validates the provided token/key and returns a User.
	// Returns an error if validation fails.
	Validate(ctx context.Context, token string) (*User, error)
}

// TokenExtractor extracts an authentication token from a request.
type TokenExtractor interface {
	// Extract extracts a token from the context (usually the request).
	// Returns empty string if no token is found.
	Extract(ctx context.Context) string
}
