package models

import (
	"time"

	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/domain/user"
)

// UserByDate represents the users_by_date table
// Query pattern: List users sorted by creation date
// Primary key: ((tenant_id, created_date), id) - composite partition key + clustering
type UserByDate struct {
	TenantID    string `db:"tenant_id"`    // Multi-tenant isolation (partition key part 1)
	CreatedDate string `db:"created_date"` // Format: YYYY-MM-DD (partition key part 2)
	ID          string `db:"id"`           // Clustering column
	Email       string `db:"email"`
	FirstName   string `db:"first_name"`
	LastName    string `db:"last_name"`
	Name        string `db:"name"`
	LexicalName string `db:"lexical_name"`
	Timezone    string `db:"timezone"`
	Role        int   `db:"role"`
	Status      int   `db:"status"`

	// Profile data fields (flattened)
	Phone                                          string `db:"phone"`
	Country                                        string `db:"country"`
	Region                                         string `db:"region"`
	City                                           string `db:"city"`
	PostalCode                                     string `db:"postal_code"`
	AddressLine1                                   string `db:"address_line1"`
	AddressLine2                                   string `db:"address_line2"`
	HasShippingAddress                             bool   `db:"has_shipping_address"`
	ShippingName                                   string `db:"shipping_name"`
	ShippingPhone                                  string `db:"shipping_phone"`
	ShippingCountry                                string `db:"shipping_country"`
	ShippingRegion                                 string `db:"shipping_region"`
	ShippingCity                                   string `db:"shipping_city"`
	ShippingPostalCode                             string `db:"shipping_postal_code"`
	ShippingAddressLine1                           string `db:"shipping_address_line1"`
	ShippingAddressLine2                           string `db:"shipping_address_line2"`
	ProfileTimezone                                string `db:"profile_timezone"`
	AgreeTermsOfService                            bool   `db:"agree_terms_of_service"`
	AgreePromotions                                bool   `db:"agree_promotions"`
	AgreeToTrackingAcrossThirdPartyAppsAndServices bool   `db:"agree_to_tracking_across_third_party_apps_and_services"`

	// Security data fields (flattened)
	PasswordHashAlgorithm      string    `db:"password_hash_algorithm"`
	PasswordHash               string    `db:"password_hash"`
	WasEmailVerified           bool      `db:"was_email_verified"`
	Code                       string    `db:"code"`
	CodeType                   string    `db:"code_type"`
	CodeExpiry                 time.Time `db:"code_expiry"`
	OTPEnabled                 bool      `db:"otp_enabled"`
	OTPVerified                bool      `db:"otp_verified"`
	OTPValidated               bool      `db:"otp_validated"`
	OTPSecret                  string    `db:"otp_secret"`
	OTPAuthURL                 string    `db:"otp_auth_url"`
	OTPBackupCodeHash          string    `db:"otp_backup_code_hash"`
	OTPBackupCodeHashAlgorithm string    `db:"otp_backup_code_hash_algorithm"`

	// Metadata fields (flattened)
	// CWE-359: Encrypted IP addresses for GDPR compliance
	CreatedFromIPAddress    string    `db:"created_from_ip_address"`   // Encrypted with go-ipcrypt
	CreatedFromIPTimestamp  time.Time `db:"created_from_ip_timestamp"` // For 90-day expiration tracking
	CreatedByUserID         string    `db:"created_by_user_id"`
	CreatedByName           string    `db:"created_by_name"`
	ModifiedFromIPAddress   string    `db:"modified_from_ip_address"`   // Encrypted with go-ipcrypt
	ModifiedFromIPTimestamp time.Time `db:"modified_from_ip_timestamp"` // For 90-day expiration tracking
	ModifiedByUserID        string    `db:"modified_by_user_id"`
	ModifiedAt              time.Time `db:"modified_at"`
	ModifiedByName          string    `db:"modified_by_name"`
	LastLoginAt             time.Time `db:"last_login_at"`

	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

// ToUser converts table model to domain entity
func (u *UserByDate) ToUser() *user.User {
	return &user.User{
		ID:          u.ID,
		Email:       u.Email,
		FirstName:   u.FirstName,
		LastName:    u.LastName,
		Name:        u.Name,
		LexicalName: u.LexicalName,
		Timezone:    u.Timezone,
		Role:        u.Role,
		Status:      u.Status,

		ProfileData: &user.UserProfileData{
			Phone:                u.Phone,
			Country:              u.Country,
			Region:               u.Region,
			City:                 u.City,
			PostalCode:           u.PostalCode,
			AddressLine1:         u.AddressLine1,
			AddressLine2:         u.AddressLine2,
			HasShippingAddress:   u.HasShippingAddress,
			ShippingName:         u.ShippingName,
			ShippingPhone:        u.ShippingPhone,
			ShippingCountry:      u.ShippingCountry,
			ShippingRegion:       u.ShippingRegion,
			ShippingCity:         u.ShippingCity,
			ShippingPostalCode:   u.ShippingPostalCode,
			ShippingAddressLine1: u.ShippingAddressLine1,
			ShippingAddressLine2: u.ShippingAddressLine2,
			Timezone:             u.ProfileTimezone,
			AgreeTermsOfService:  u.AgreeTermsOfService,
			AgreePromotions:      u.AgreePromotions,
			AgreeToTrackingAcrossThirdPartyAppsAndServices: u.AgreeToTrackingAcrossThirdPartyAppsAndServices,
		},

		SecurityData: &user.UserSecurityData{
			PasswordHashAlgorithm:      u.PasswordHashAlgorithm,
			PasswordHash:               u.PasswordHash,
			WasEmailVerified:           u.WasEmailVerified,
			Code:                       u.Code,
			CodeType:                   u.CodeType,
			CodeExpiry:                 u.CodeExpiry,
			OTPEnabled:                 u.OTPEnabled,
			OTPVerified:                u.OTPVerified,
			OTPValidated:               u.OTPValidated,
			OTPSecret:                  u.OTPSecret,
			OTPAuthURL:                 u.OTPAuthURL,
			OTPBackupCodeHash:          u.OTPBackupCodeHash,
			OTPBackupCodeHashAlgorithm: u.OTPBackupCodeHashAlgorithm,
		},

		Metadata: &user.UserMetadata{
			CreatedFromIPAddress:    u.CreatedFromIPAddress,
			CreatedFromIPTimestamp:  u.CreatedFromIPTimestamp,
			CreatedByUserID:         u.CreatedByUserID,
			CreatedAt:               u.CreatedAt,
			CreatedByName:           u.CreatedByName,
			ModifiedFromIPAddress:   u.ModifiedFromIPAddress,
			ModifiedFromIPTimestamp: u.ModifiedFromIPTimestamp,
			ModifiedByUserID:        u.ModifiedByUserID,
			ModifiedAt:              u.ModifiedAt,
			ModifiedByName:          u.ModifiedByName,
			LastLoginAt:             u.LastLoginAt,
		},

		TenantID:  u.TenantID,
		CreatedAt: u.CreatedAt,
		UpdatedAt: u.UpdatedAt,
	}
}

// FromUserByDate converts domain entity to table model
func FromUserByDate(tenantID string, u *user.User) *UserByDate {
	userByDate := &UserByDate{
		TenantID:    tenantID,
		CreatedDate: u.CreatedAt.Format("2006-01-02"),
		ID:          u.ID,
		Email:       u.Email,
		FirstName:   u.FirstName,
		LastName:    u.LastName,
		Name:        u.Name,
		LexicalName: u.LexicalName,
		Timezone:    u.Timezone,
		Role:        u.Role,
		Status:      u.Status,
		CreatedAt:   u.CreatedAt,
		UpdatedAt:   u.UpdatedAt,
	}

	// Map ProfileData if present
	if u.ProfileData != nil {
		userByDate.Phone = u.ProfileData.Phone
		userByDate.Country = u.ProfileData.Country
		userByDate.Region = u.ProfileData.Region
		userByDate.City = u.ProfileData.City
		userByDate.PostalCode = u.ProfileData.PostalCode
		userByDate.AddressLine1 = u.ProfileData.AddressLine1
		userByDate.AddressLine2 = u.ProfileData.AddressLine2
		userByDate.HasShippingAddress = u.ProfileData.HasShippingAddress
		userByDate.ShippingName = u.ProfileData.ShippingName
		userByDate.ShippingPhone = u.ProfileData.ShippingPhone
		userByDate.ShippingCountry = u.ProfileData.ShippingCountry
		userByDate.ShippingRegion = u.ProfileData.ShippingRegion
		userByDate.ShippingCity = u.ProfileData.ShippingCity
		userByDate.ShippingPostalCode = u.ProfileData.ShippingPostalCode
		userByDate.ShippingAddressLine1 = u.ProfileData.ShippingAddressLine1
		userByDate.ShippingAddressLine2 = u.ProfileData.ShippingAddressLine2
		userByDate.ProfileTimezone = u.ProfileData.Timezone
		userByDate.AgreeTermsOfService = u.ProfileData.AgreeTermsOfService
		userByDate.AgreePromotions = u.ProfileData.AgreePromotions
		userByDate.AgreeToTrackingAcrossThirdPartyAppsAndServices = u.ProfileData.AgreeToTrackingAcrossThirdPartyAppsAndServices
	}

	// Map SecurityData if present
	if u.SecurityData != nil {
		userByDate.PasswordHashAlgorithm = u.SecurityData.PasswordHashAlgorithm
		userByDate.PasswordHash = u.SecurityData.PasswordHash
		userByDate.WasEmailVerified = u.SecurityData.WasEmailVerified
		userByDate.Code = u.SecurityData.Code
		userByDate.CodeType = u.SecurityData.CodeType
		userByDate.CodeExpiry = u.SecurityData.CodeExpiry
		userByDate.OTPEnabled = u.SecurityData.OTPEnabled
		userByDate.OTPVerified = u.SecurityData.OTPVerified
		userByDate.OTPValidated = u.SecurityData.OTPValidated
		userByDate.OTPSecret = u.SecurityData.OTPSecret
		userByDate.OTPAuthURL = u.SecurityData.OTPAuthURL
		userByDate.OTPBackupCodeHash = u.SecurityData.OTPBackupCodeHash
		userByDate.OTPBackupCodeHashAlgorithm = u.SecurityData.OTPBackupCodeHashAlgorithm
	}

	// Map Metadata if present
	if u.Metadata != nil {
		userByDate.CreatedFromIPAddress = u.Metadata.CreatedFromIPAddress
		userByDate.CreatedFromIPTimestamp = u.Metadata.CreatedFromIPTimestamp
		userByDate.CreatedByUserID = u.Metadata.CreatedByUserID
		userByDate.CreatedByName = u.Metadata.CreatedByName
		userByDate.ModifiedFromIPAddress = u.Metadata.ModifiedFromIPAddress
		userByDate.ModifiedFromIPTimestamp = u.Metadata.ModifiedFromIPTimestamp
		userByDate.ModifiedByUserID = u.Metadata.ModifiedByUserID
		userByDate.ModifiedAt = u.Metadata.ModifiedAt
		userByDate.ModifiedByName = u.Metadata.ModifiedByName
		userByDate.LastLoginAt = u.Metadata.LastLoginAt
	}

	return userByDate
}
