package responseErrors

import (
	"errors"

	"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
	"github.com/gofiber/fiber/v3"
)

var (
	// Typed errors for request validation and authentication
	ErrInvalidBody      = errors.New("invalid request body")
	ErrNotAuthenticated = errors.New("not authenticated")
	ErrUserNotFound     = errors.New("user not found")
	ErrUserInactive     = errors.New("user account is inactive")
	ErrInvalidToken     = errors.New("invalid token")
	ErrTokenExpired     = errors.New("token has expired")
	ErrTokenRequired    = errors.New("token is required")

	// Typed errors for logging in and registering
	ErrInvalidCredentials    = errors.New("invalid email or password")
	ErrEmailNotVerified      = errors.New("email not verified")
	ErrEmailExists           = errors.New("email already exists")
	ErrFirstLastNameRequired = errors.New("first and last name is required")
	ErrEmailRequired         = errors.New("email is required")
	ErrEmailPasswordRequired = errors.New("email and password are required")
	ErrRefreshTokenRequired  = errors.New("refresh token is required")
	ErrBadLangID             = errors.New("bad language id")
	ErrBadCountryID          = errors.New("bad country id")

	// Typed errors for password reset
	ErrInvalidResetToken     = errors.New("invalid reset token")
	ErrResetTokenExpired     = errors.New("reset token has expired")
	ErrPasswordsDoNotMatch   = errors.New("passwords do not match")
	ErrInvalidPassword       = errors.New("password must be at least 8 characters long and contain at least one lowercase letter, one uppercase letter, and one digit")
	ErrTokenPasswordRequired = errors.New("token and password are required")

	// Typed errors for verification
	ErrInvalidVerificationToken = errors.New("invalid verification token")
	ErrVerificationTokenExpired = errors.New("verification token has expired")

	// Typed errors for product description handler
	ErrBadAttribute   = errors.New("bad or missing attribute value in header")
	ErrBadField       = errors.New("this field can not be updated")
	ErrInvalidXHTML   = errors.New("text is not in xhtml format")
	ErrAIResponseFail = errors.New("AI responded with failure")
	ErrAIBadOutput    = errors.New("AI response does not obey the format")

	// Typed errors for product list handler
	ErrBadPaging = errors.New("bad or missing paging attribute value in header")

	// Typed errors for menu handler
	ErrNoRootFound = errors.New("no root found in categories table")

	// Typed errors for carts handler
	ErrMaxAmtOfCartsReached              = errors.New("maximal amount of carts reached")
	ErrUserHasNoSuchCart                 = errors.New("user does not have cart with given id")
	ErrProductOrItsVariationDoesNotExist = errors.New("product or its variation with given ids does not exist")
)

// Error represents an error with HTTP status code
type Error struct {
	Err    error
	Status int
}

func (e *Error) Error() string {
	return e.Err.Error()
}

func (e *Error) Unwrap() error {
	return e.Err
}

// NewError creates a new typed error
func NewError(err error, status int) *Error {
	return &Error{Err: err, Status: status}
}

// GetErrorCode returns the error code string for HTTP response mapping
func GetErrorCode(c fiber.Ctx, err error) string {
	switch {
	case errors.Is(err, ErrInvalidBody):
		return i18n.T_(c, "error.err_invalid_body")
	case errors.Is(err, ErrInvalidCredentials):
		return i18n.T_(c, "error.err_invalid_credentials")
	case errors.Is(err, ErrNotAuthenticated):
		return i18n.T_(c, "error.err_not_authenticated")
	case errors.Is(err, ErrUserNotFound):
		return i18n.T_(c, "error.err_user_not_found")
	case errors.Is(err, ErrUserInactive):
		return i18n.T_(c, "error.err_user_inactive")
	case errors.Is(err, ErrEmailNotVerified):
		return i18n.T_(c, "error.err_email_not_verified")
	case errors.Is(err, ErrEmailExists):
		return i18n.T_(c, "error.err_email_exists")
	case errors.Is(err, ErrInvalidToken):
		return i18n.T_(c, "error.err_invalid_token")
	case errors.Is(err, ErrTokenExpired):
		return i18n.T_(c, "error.err_token_expired")
	case errors.Is(err, ErrFirstLastNameRequired):
		return i18n.T_(c, "error.err_first_last_name_required")
	case errors.Is(err, ErrEmailRequired):
		return i18n.T_(c, "error.err_email_required")
	case errors.Is(err, ErrEmailPasswordRequired):
		return i18n.T_(c, "error.err_email_password_required")
	case errors.Is(err, ErrTokenRequired):
		return i18n.T_(c, "error.err_token_required")
	case errors.Is(err, ErrRefreshTokenRequired):
		return i18n.T_(c, "error.err_refresh_token_required")
	case errors.Is(err, ErrBadLangID):
		return i18n.T_(c, "error.err_bad_lang_id")
	case errors.Is(err, ErrBadCountryID):
		return i18n.T_(c, "error.err_bad_country_id")

	case errors.Is(err, ErrInvalidResetToken):
		return i18n.T_(c, "error.err_invalid_reset_token")
	case errors.Is(err, ErrResetTokenExpired):
		return i18n.T_(c, "error.err_reset_token_expired")
	case errors.Is(err, ErrPasswordsDoNotMatch):
		return i18n.T_(c, "error.err_passwords_do_not_match")
	case errors.Is(err, ErrInvalidPassword):
		return i18n.T_(c, "error.err_invalid_password")
	case errors.Is(err, ErrTokenPasswordRequired):
		return i18n.T_(c, "error.err_token_password_required")

	case errors.Is(err, ErrInvalidVerificationToken):
		return i18n.T_(c, "error.err_invalid_verification_token")
	case errors.Is(err, ErrVerificationTokenExpired):
		return i18n.T_(c, "error.err_verification_token_expired")

	case errors.Is(err, ErrBadAttribute):
		return i18n.T_(c, "error.err_bad_attribute")
	case errors.Is(err, ErrBadField):
		return i18n.T_(c, "error.err_bad_field")
	case errors.Is(err, ErrInvalidXHTML):
		return i18n.T_(c, "error.err_invalid_html")
	case errors.Is(err, ErrAIResponseFail):
		return i18n.T_(c, "error.err_ai_response_fail")
	case errors.Is(err, ErrAIBadOutput):
		return i18n.T_(c, "error.err_ai_bad_output")

	case errors.Is(err, ErrBadPaging):
		return i18n.T_(c, "error.err_bad_paging")

	case errors.Is(err, ErrNoRootFound):
		return i18n.T_(c, "error.no_root_found")

	case errors.Is(err, ErrMaxAmtOfCartsReached):
		return i18n.T_(c, "error.max_amt_of_carts_reached")
	case errors.Is(err, ErrUserHasNoSuchCart):
		return i18n.T_(c, "error.user_has_no_such_cart")
	case errors.Is(err, ErrProductOrItsVariationDoesNotExist):
		return i18n.T_(c, "error.product_or_its_variation_does_not_exist")

	default:
		return i18n.T_(c, "error.err_internal_server_error")
	}
}

// GetErrorStatus returns the HTTP status code for the given error
func GetErrorStatus(err error) int {
	switch {
	case errors.Is(err, ErrInvalidCredentials),
		errors.Is(err, ErrNotAuthenticated),
		errors.Is(err, ErrInvalidToken),
		errors.Is(err, ErrTokenExpired):
		return fiber.StatusUnauthorized
	case errors.Is(err, ErrInvalidBody),
		errors.Is(err, ErrUserNotFound),
		errors.Is(err, ErrUserInactive),
		errors.Is(err, ErrEmailNotVerified),
		errors.Is(err, ErrFirstLastNameRequired),
		errors.Is(err, ErrEmailRequired),
		errors.Is(err, ErrEmailPasswordRequired),
		errors.Is(err, ErrTokenRequired),
		errors.Is(err, ErrRefreshTokenRequired),
		errors.Is(err, ErrBadLangID),
		errors.Is(err, ErrBadCountryID),
		errors.Is(err, ErrPasswordsDoNotMatch),
		errors.Is(err, ErrTokenPasswordRequired),
		errors.Is(err, ErrInvalidResetToken),
		errors.Is(err, ErrResetTokenExpired),
		errors.Is(err, ErrInvalidVerificationToken),
		errors.Is(err, ErrVerificationTokenExpired),
		errors.Is(err, ErrInvalidPassword),
		errors.Is(err, ErrBadAttribute),
		errors.Is(err, ErrBadField),
		errors.Is(err, ErrInvalidXHTML),
		errors.Is(err, ErrBadPaging),
		errors.Is(err, ErrNoRootFound),
		errors.Is(err, ErrMaxAmtOfCartsReached),
		errors.Is(err, ErrUserHasNoSuchCart),
		errors.Is(err, ErrProductOrItsVariationDoesNotExist):
		return fiber.StatusBadRequest
	case errors.Is(err, ErrEmailExists):
		return fiber.StatusConflict
	case errors.Is(err, ErrAIResponseFail),
		errors.Is(err, ErrAIBadOutput):
		return fiber.StatusServiceUnavailable
	default:
		return fiber.StatusInternalServerError
	}
}
