package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
	domain "github.com/haydenhargreaves/Potion/internal/domain/user"
)

// AuthenticatedFunc is a function that handles authenticated requests
type AuthenticatedFunc func(ctx *gin.Context, user *domain.User)

// withAuthenticatedUser is a helper to run a handler only if user is authenticated. Otherwise
// the function will return an error with a 401 status.
//
// BUG: This is probably not very effecient, since we hit the DB on every single protected request.
//
//	  If this ends up being a bottle neck we could simply hit the context for the userId, since
//	  that is usually all we need...Or maybe have two methods, for those that need the whole user
//		and those that just need the ID.
func (s *Server) withAuthenticatedUser(ctx *gin.Context, handler AuthenticatedFunc) {
	user := s.deps.UserService.GetAuthenicatedUser(ctx)
	if user == nil {
		// User is stale, ensure they are logged out so they can be prompted to log back in
		s.SetCookie(ctx, "jwt_token", "", -1)
		// s.SetCookie(ctx, "search-filters", "", -1) // TODO: Might need this again

		ctx.JSON(http.StatusUnauthorized, gin.H{
			"status":  http.StatusUnauthorized,
			"message": "[UNAUTHORIZED] Could not fetch authenticated user.",
		})
		return
	}
	handler(ctx, user)
}

// getUserId retrieves the userId from the context and returns a pointer to it. A nil
// pointer can be returned and will if the userId does not exist.
func getUserId(ctx *gin.Context) *int {
	userIdAny, exists := ctx.Get("userId")
	if !exists {
		return nil
	}
	userIdInt, ok := userIdAny.(int)
	if !ok {
		return nil
	}
	return &userIdInt
}
