package services

import (
	"actatempus_backend/internal/domain/app_error"
	"actatempus_backend/internal/domain/repository"
	"net/http"

	E "github.com/IBM/fp-go/either"
	F "github.com/IBM/fp-go/function"
	O "github.com/IBM/fp-go/option"
	"github.com/gin-gonic/gin"
)

// HandleError handles errors by formatting them as JSON.
func HandleError(c *gin.Context) func(error) any {
	return func(err error) any {
		// Check if the error is of type *AppError
		if appErr, ok := err.(*app_error.AppError); ok {
			response := gin.H{
				"code":    appErr.Code,
				"message": appErr.Message,
			}

			// Add details if available
			if appErr.Err != nil {
				response["details"] = appErr.Err.Error()
			}

			// Use the AppError fields for the JSON response
			c.JSON(appErr.Status, response)
		} else {
			// Fallback for non-AppError errors
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": err.Error(),
			})
		}

		return nil
	}
}

func HandleSuccess[T any](c *gin.Context, statusCode int) func(T) any {
	return func(data T) any {
		c.JSON(statusCode, data)
		return nil
	}
}

func ReadSessionToken(c *gin.Context) O.Option[string] {
	sessionToken, err := c.Cookie("session_token")
	if err != nil || sessionToken == "" {
		return O.None[string]()
	}
	return O.Some(sessionToken)
}

func CheckAuth(c *gin.Context, authRepository repository.AuthRepository) E.Either[error, string] {
	return F.Pipe2(
		ReadSessionToken(c),
		E.FromOption[string, error](
			F.Constant[error](app_error.NewUnauthorizedError("No session token found"))),
		E.Chain(
			authRepository.ValidateToken(c.Request.Context()),
		),
		//E.MapLeft[string](
		//	func(e error) error {
		//		HandleError(c)(e)
		//		return e
		//	},
		//),
	)

}
