package domain

import (
	"fmt"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	domainAuth "github.com/haydenhargreaves/Potion/internal/domain/auth"
	domainEngagement "github.com/haydenhargreaves/Potion/internal/domain/engagement"
	domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe"
	domainUser "github.com/haydenhargreaves/Potion/internal/domain/user"
	"github.com/joho/godotenv"
	"github.com/kelseyhightower/envconfig"
)

// EnvironmentConfig stores the configuration of the environment. Anything loaded from the .env
// or docker environment will be stored here and can be accessed from the InjectedDependencies
// struct, which this is attached to.
type EnvironmentConfig struct {
	GoogleClientId     string `envconfig:"GOOGLE_CLIENT_ID" required:"true"`
	GoogleClientSecret string `envconfig:"GOOGLE_CLIENT_SECRET" required:"true"`
	JwtSecret          string `envconfig:"JWT_SECRET" required:"true"`
	DatabaseUrl        string `envconfig:"DATABASE_URL" required:"true"`
	Domain             string `envconfig:"DOMAIN" required:"true"`
	FrontendDomain     string `envconfig:"FRONTEND_DOMAIN" required:"true"`
	Environment        string `envconfig:"ENVIRONMENT" required:"true"`
	LogFilePath        string `envconfig:"LOG_FILE_PATH" required:"false"`
}

// InjectedDependencies is a collection of dependencies that are injected into the application. They
// are stored in the context and can be accessed by handlers via the context.
type InjectedDependencies struct {
	UserService       domainUser.UserService
	AuthService       domainAuth.AuthService
	RecipeService     domainRecipe.RecipeService
	EngagementService domainEngagement.EngagementService
	EnvironmentConfig EnvironmentConfig
}

// JwtClaims is the data stored in the JSON web token. All that is needed is the users ID and their
// Google email provided.
type JwtClaims struct {
	UserId int    `json:"Id"`
	Email  string `json:"Email"`
	jwt.RegisteredClaims
}

// IsLoggedIn checks the cookies in a request and returns whether the user is logged in.
func IsLoggedIn(ctx *gin.Context) bool {
	_, id := ctx.Get("userId")
	_, email := ctx.Get("userEmail")
	return id && email
}

// LoadEnvironment loads the environment values from either an .env file or docker environment.
func LoadEnvironment() (*EnvironmentConfig, error) {
	// NOTE: Does the error return matter?
	godotenv.Load(".env")

	cfg := &EnvironmentConfig{}
	if err := envconfig.Process("", cfg); err != nil {
		return nil, fmt.Errorf("Failed to load environment: %w", err)
	}

	return cfg, nil
}

// SetCookie sets a cookie value with a duration provided. This function handles setting the security
// configuration as well as the domain. These values are based on the EnvironmentConfig, therefore
// the value should be set. Nothing is returned by this function, but the cookie will be set.
//
// This function can also be used to clear cookies, if a blank value ("") and invalid duration (-1)
// is provided.
//
// If 0 is provided as the duration, then a session cookie is created, which will be cleared when
// the browser is closed.
//
// DEPRECATED: As of September 4th, 2025.
// func  SetCookie(ctx *gin.Context, name, value string, duration time.Duration) {
// 	deps := ctx.MustGet("deps").(*InjectedDependencies)
//
// 	var (
// 		path     string = "/"
// 		httpOnly bool   = true
// 		maxAge   int
// 		secure   bool
// 		domain   string
// 	)
//
// 	if duration < 0 {
// 		// Delete the cookie
// 		maxAge = -1
// 	} else if duration == 0 {
// 		// Session cookie, clears when browser is closed
// 		maxAge = 0
// 	} else {
// 		// Normal calculation
// 		maxAge = int(time.Now().Add(duration).Sub(time.Now()).Seconds())
// 	}
//
// 	if deps.EnvironmentConfig.Environment == "prod" {
// 		secure = true
// 		domain = deps.EnvironmentConfig.Domain
//
// 	} else if deps.EnvironmentConfig.Environment == "dev" {
// 		secure = false
// 		domain = deps.EnvironmentConfig.Domain
//
// 	} else {
// 		// Defaults
// 		secure = false
// 		domain = ""
// 	}
//
// 	ctx.SetCookie(name, value, maxAge, path, domain, secure, httpOnly)
// }
