package auth

import (
	"context"
	"net/http"
)

type ctxKey string

const ClaimsCtxKey ctxKey = "claims"

type contextKey struct{}

func RequireAuth(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		token := GetTokenFromRequest(r)
		if token == "" {
			http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
			return
		}

		claims, err := GlobalJWTManager.Validate(token)
		if err != nil {
			http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
			return
		}

		ctx := r.Context()
		ctx = context.WithValue(ctx, ClaimsCtxKey, claims)
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

func RequireAdmin(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		claims := GetClaims(r.Context())
		if claims == nil || claims.Role != "admin" {
			http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
			return
		}
		next.ServeHTTP(w, r)
	})
}

func GetClaims(ctx context.Context) *Claims {
	v := ctx.Value(ClaimsCtxKey)
	if v == nil {
		return nil
	}
	return v.(*Claims)
}

var GlobalJWTManager *JWTManager

func InitJWTManager(secret string, expiryH int) {
	GlobalJWTManager = NewJWTManager(secret, expiryH)
}

func GetJWTManager() *JWTManager {
	return GlobalJWTManager
}
