package validation

import (
	"GoMembership/internal/constants"
	"GoMembership/internal/models"
	"GoMembership/internal/repositories"
	"GoMembership/pkg/logger"
	"strings"
	"time"

	"github.com/go-playground/validator/v10"
	passwordvalidator "github.com/wagslane/go-password-validator"
)

var passwordErrorTranslations = map[string]string{
	"insecure password, try ":           "",
	"or using a longer password":        "server.validation.longer",
	"including more special characters": "server.validation.special",
	"using lowercase letters":           "server.validation.lowercase",
	"using uppercase letters":           "server.validation.uppercase",
	"using numbers":                     "server.validation.numbers",
}

func ValidateUser(sl validator.StructLevel) {
	user := sl.Current().Interface().(models.User)

	isSuper := user.RoleID >= constants.Roles.Admin
	isSupporter := user.RoleID == constants.Roles.Supporter
	// validate subscriptionModel
	if user.Membership.SubscriptionModel.Name == "" {
		sl.ReportError(user.Membership.SubscriptionModel.Name, "subscription.name", "name", "required", "")
	} else {
		selectedModel, err := repositories.GetSubscriptionByName(&user.Membership.SubscriptionModel.Name)
		if err != nil {
			logger.Error.Printf("Error finding subscription model for user %v: %v", user.Email, err)
			sl.ReportError(user.Membership.SubscriptionModel.Name, "subscription.name", "name", "invalid", "")
		} else {
			user.Membership.SubscriptionModel = *selectedModel
		}
	}
	if isSupporter {
		if user.BankAccount.IBAN != "" {
			validateBankAccount(sl)
		}
		return
	}

	if user.Password != "" {
		if err := passwordvalidator.Validate(user.Password, 60); err != nil {
			sl.ReportError(user.Password, translatePasswordError(err), "password", "insecure", "")
		}
	}
	// Validate User > 18 years old
	if user.DateOfBirth.After(time.Now().AddDate(-18, 0, 0)) {
		sl.ReportError(user.DateOfBirth, "user.user", "user.dateofbirth", "age", "")
	}
	validateMembership(sl)

	if isSuper {
		return
	}

	validateBankAccount(sl)
	if user.Licence != nil {
		validateDriverslicence(sl)
	}
}

func translatePasswordError(err error) string {
	errMsg := err.Error()
	// Translate each part of the error message
	translatedMsg := errMsg
	for eng, translated := range passwordErrorTranslations {
		translatedMsg = strings.Replace(translatedMsg, eng, translated, -1)
	}

	return strings.Replace(translatedMsg, ",", "", -1)
}
