// codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/domain/user/model.go
package user

import (
	"time"

	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/domain/crypto"
	"github.com/gocql/gocql"
)

const (
	UserStatusActive   = 1   // User is active and can log in.
	UserStatusLocked   = 50  // User account is locked, typically due to too many failed login attempts.
	UserStatusArchived = 100 // User account is archived and cannot log in.

	UserRoleRoot       = 1 // Root user, has all permissions
	UserRoleCompany    = 2 // Company user, has permissions for company-related operations
	UserRoleIndividual = 3 // Individual user, has permissions for individual-related operations

	UserProfileVerificationStatusUnverified         = 1 // The user's profile has not yet been submitted for verification.
	UserProfileVerificationStatusSubmittedForReview = 2 // The user's profile has been submitted and is awaiting review.
	UserProfileVerificationStatusApproved           = 3 // The user's profile has been approved.
	UserProfileVerificationStatusRejected           = 4 // The user's profile has been rejected.

	// StorePendingStatus indicates this store needs to be reviewed by CPS and approved / rejected.
	StorePendingStatus  = 1 // Store is pending review.
	StoreActiveStatus   = 2 // Store is active and can be used.
	StoreRejectedStatus = 3 // Store has been rejected.
	StoreErrorStatus    = 4 // Store has encountered an error.
	StoreArchivedStatus = 5 // Store has been archived.

	EstimatedSubmissionsPerMonth1To10   = 1 // Estimated submissions per month: 1 to 10
	EstimatedSubmissionsPerMonth10To25  = 2 // Estimated submissions per month: 10 to 25
	EstimatedSubmissionsPerMonth25To50  = 3 // Estimated submissions per month: 25 to 50
	EstimatedSubmissionsPerMonth50To10  = 4 // Estimated submissions per month: 50 to 100
	EstimatedSubmissionsPerMonth100Plus = 5 // Estimated submissions per month: 100+

	HasOtherGradingServiceYes = 1 // Has other grading service: Yes
	HasOtherGradingServiceNo  = 2 // Has other grading service: No
	RequestWelcomePackageYes  = 1 // Request welcome package: Yes
	RequestWelcomePackageNo   = 2 // Request welcome package: No

	SpecialCollection040001 = 1

	UserCodeTypeEmailVerification = "email_verification"
	UserCodeTypePasswordReset     = "password_reset"
)

type UserProfileData struct {
	Phone                                          string `bson:"phone" json:"phone,omitempty"`
	Country                                        string `bson:"country" json:"country,omitempty"`
	Region                                         string `bson:"region" json:"region,omitempty"`
	City                                           string `bson:"city" json:"city,omitempty"`
	PostalCode                                     string `bson:"postal_code" json:"postal_code,omitempty"`
	AddressLine1                                   string `bson:"address_line1" json:"address_line1,omitempty"`
	AddressLine2                                   string `bson:"address_line2" json:"address_line2,omitempty"`
	HasShippingAddress                             bool   `bson:"has_shipping_address" json:"has_shipping_address,omitempty"`
	ShippingName                                   string `bson:"shipping_name" json:"shipping_name,omitempty"`
	ShippingPhone                                  string `bson:"shipping_phone" json:"shipping_phone,omitempty"`
	ShippingCountry                                string `bson:"shipping_country" json:"shipping_country,omitempty"`
	ShippingRegion                                 string `bson:"shipping_region" json:"shipping_region,omitempty"`
	ShippingCity                                   string `bson:"shipping_city" json:"shipping_city,omitempty"`
	ShippingPostalCode                             string `bson:"shipping_postal_code" json:"shipping_postal_code,omitempty"`
	ShippingAddressLine1                           string `bson:"shipping_address_line1" json:"shipping_address_line1,omitempty"`
	ShippingAddressLine2                           string `bson:"shipping_address_line2" json:"shipping_address_line2,omitempty"`
	Timezone                                       string `bson:"timezone" json:"timezone"`
	AgreeTermsOfService                            bool   `bson:"agree_terms_of_service" json:"agree_terms_of_service,omitempty"`
	AgreePromotions                                bool   `bson:"agree_promotions" json:"agree_promotions,omitempty"`
	AgreeToTrackingAcrossThirdPartyAppsAndServices bool   `bson:"agree_to_tracking_across_third_party_apps_and_services" json:"agree_to_tracking_across_third_party_apps_and_services,omitempty"`

	// Email share notification preferences
	ShareNotificationsEnabled *bool `bson:"share_notifications_enabled" json:"share_notifications_enabled,omitempty"`
}

type UserSecurityData struct {
	WasEmailVerified bool `bson:"was_email_verified" json:"was_email_verified,omitempty"`

	Code       string    `bson:"code,omitempty" json:"code,omitempty"`
	CodeType   string    `bson:"code_type,omitempty" json:"code_type,omitempty"` // -- 'email_verification' or 'password_reset'
	CodeExpiry time.Time `bson:"code_expiry,omitempty" json:"code_expiry"`

	// --- E2EE Related ---
	PasswordSalt []byte `json:"password_salt" bson:"password_salt"`
	// KDFParams stores the key derivation function parameters used to derive the user's password hash.
	KDFParams                         crypto.KDFParams                         `json:"kdf_params" bson:"kdf_params"`
	EncryptedMasterKey                crypto.EncryptedMasterKey                `json:"encrypted_master_key" bson:"encrypted_master_key"`
	PublicKey                         crypto.PublicKey                         `json:"public_key" bson:"public_key"`
	EncryptedPrivateKey               crypto.EncryptedPrivateKey               `json:"encrypted_private_key" bson:"encrypted_private_key"`
	EncryptedRecoveryKey              crypto.EncryptedRecoveryKey              `json:"encrypted_recovery_key" bson:"encrypted_recovery_key"`
	MasterKeyEncryptedWithRecoveryKey crypto.MasterKeyEncryptedWithRecoveryKey `json:"master_key_encrypted_with_recovery_key" bson:"master_key_encrypted_with_recovery_key"`
	EncryptedChallenge                []byte                                   `json:"encrypted_challenge,omitempty" bson:"encrypted_challenge,omitempty"`
	VerificationID                    string                                   `json:"verification_id" bson:"verification_id"`

	// Track KDF upgrade status
	LastPasswordChange   time.Time `json:"last_password_change" bson:"last_password_change"`
	KDFParamsNeedUpgrade bool      `json:"kdf_params_need_upgrade" bson:"kdf_params_need_upgrade"`

	// Key rotation tracking fields
	CurrentKeyVersion int                       `json:"current_key_version" bson:"current_key_version"`
	LastKeyRotation   *time.Time                `json:"last_key_rotation,omitempty" bson:"last_key_rotation,omitempty"`
	KeyRotationPolicy *crypto.KeyRotationPolicy `json:"key_rotation_policy,omitempty" bson:"key_rotation_policy,omitempty"`

	// OTPEnabled controls whether we force 2FA or not during login.
	OTPEnabled bool `bson:"otp_enabled" json:"otp_enabled"`

	// OTPVerified indicates user has successfully validated their opt token afer enabling 2FA thus turning it on.
	OTPVerified bool `bson:"otp_verified" json:"otp_verified"`

	// OTPValidated automatically gets set as `false` on successful login and then sets `true` once successfully validated by 2FA.
	OTPValidated bool `bson:"otp_validated" json:"otp_validated"`

	// OTPSecret the unique one-time password secret to be shared between our
	// backend and 2FA authenticator sort of apps that support `TOPT`.
	OTPSecret string `bson:"otp_secret" json:"-"`

	// OTPAuthURL is the URL used to share.
	OTPAuthURL string `bson:"otp_auth_url" json:"-"`

	// OTPBackupCodeHash is the one-time use backup code which resets the 2FA settings and allow the user to setup 2FA from scratch for the user.
	OTPBackupCodeHash string `bson:"otp_backup_code_hash" json:"-"`

	// OTPBackupCodeHashAlgorithm tracks the hashing algorithm used.
	OTPBackupCodeHashAlgorithm string `bson:"otp_backup_code_hash_algorithm" json:"-"`

	// Email change verification fields
	PendingEmail       string    `bson:"pending_email,omitempty" json:"pending_email,omitempty"`             // New email pending verification
	PendingEmailCode   string    `bson:"pending_email_code,omitempty" json:"pending_email_code,omitempty"`   // Verification code for new email (sensitive, stored internally but never exposed in API responses)
	PendingEmailExpiry time.Time `bson:"pending_email_expiry,omitempty" json:"pending_email_expiry,omitempty"` // When verification expires
}

type UserMetadata struct {
	CreatedFromIPAddress  string     `bson:"created_from_ip_address" json:"created_from_ip_address"`
	CreatedByUserID       gocql.UUID `bson:"created_by_user_id" json:"created_by_user_id"`
	CreatedAt             time.Time  `bson:"created_at" json:"created_at"`
	CreatedByName         string     `bson:"created_by_name" json:"created_by_name"`
	ModifiedFromIPAddress string     `bson:"modified_from_ip_address" json:"modified_from_ip_address"`
	ModifiedByUserID      gocql.UUID `bson:"modified_by_user_id" json:"modified_by_user_id"`
	ModifiedAt            time.Time  `bson:"modified_at" json:"modified_at"`
	ModifiedByName        string     `bson:"modified_by_name" json:"modified_by_name"`
	LastLoginAt           time.Time  `json:"last_login_at" bson:"last_login_at"`
}

type User struct {
	ID           gocql.UUID        `bson:"_id" json:"id"`
	Email        string            `bson:"email" json:"email"`
	FirstName    string            `bson:"first_name" json:"first_name"`
	LastName     string            `bson:"last_name" json:"last_name"`
	Name         string            `bson:"name" json:"name"`
	LexicalName  string            `bson:"lexical_name" json:"lexical_name"`
	Role         int8              `bson:"role" json:"role"`
	Status       int8              `bson:"status" json:"status"`
	Timezone     string            `bson:"timezone" json:"timezone"`
	ProfileData  *UserProfileData  `bson:"profile_data" json:"profile_data"`
	SecurityData *UserSecurityData `bson:"security_data" json:"security_data"`
	Metadata     *UserMetadata     `bson:"metadata" json:"metadata"`
	CreatedAt    time.Time         `bson:"created_at" json:"created_at"`
	ModifiedAt   time.Time         `bson:"modified_at" json:"modified_at"`
}
