package domain

import (
	"time"

	"github.com/google/uuid"
)

// UserStatus represents the status of a user account
type UserStatus string

const (
	UserStatusActive    UserStatus = "active"
	UserStatusInactive  UserStatus = "inactive"
	UserStatusSuspended UserStatus = "suspended"
	UserStatusPending   UserStatus = "pending"
)

// UserRole represents the role of a user
type UserRole string

const (
	UserRoleAdmin     UserRole = "admin"
	UserRoleUser      UserRole = "user"
	UserRoleModerator UserRole = "moderator"
	UserRoleViewer    UserRole = "viewer"
)

// User represents a user in the system
type User struct {
	ID          uuid.UUID `json:"id" db:"id"`
	Email       string    `json:"email" validate:"required,email,max=255" db:"email"`
	FirstName   string    `json:"first_name" validate:"required,min=1,max=100" db:"first_name"`
	LastName    string    `json:"last_name" validate:"required,min=1,max=100" db:"last_name"`
	DisplayName *string   `json:"display_name,omitempty" validate:"omitempty,max=200" db:"display_name"`
	Avatar      *string   `json:"avatar,omitempty" validate:"omitempty,url,max=500" db:"avatar"`
	Role        UserRole  `json:"role" validate:"required,oneof=admin user moderator viewer" db:"role"`
	Status      UserStatus `json:"status" validate:"required,oneof=active inactive suspended pending" db:"status"`
	LastLoginAt *time.Time `json:"last_login_at,omitempty" db:"last_login_at"`
	
	// Security fields
	PasswordHash               string     `json:"-" db:"password_hash"`                                  // Hidden from JSON
	PasswordSalt               string     `json:"-" db:"password_salt"`                                  // Hidden from JSON
	EmailVerified             bool       `json:"email_verified" db:"email_verified"`
	EmailVerificationToken    *string    `json:"-" db:"email_verification_token"`                     // Hidden from JSON
	EmailVerificationExpiresAt *time.Time `json:"-" db:"email_verification_expires_at"`               // Hidden from JSON
	PasswordResetToken        *string    `json:"-" db:"password_reset_token"`                         // Hidden from JSON
	PasswordResetExpiresAt    *time.Time `json:"-" db:"password_reset_expires_at"`                   // Hidden from JSON
	FailedLoginAttempts       int        `json:"-" db:"failed_login_attempts"`                        // Hidden from JSON
	LockedUntil               *time.Time `json:"-" db:"locked_until"`                                 // Hidden from JSON
	TwoFactorEnabled          bool       `json:"two_factor_enabled" db:"two_factor_enabled"`
	TwoFactorSecret           *string    `json:"-" db:"two_factor_secret"`                            // Hidden from JSON
	TwoFactorBackupCodes      []string   `json:"-" db:"two_factor_backup_codes"`                      // Hidden from JSON
	LastPasswordChange        *time.Time `json:"last_password_change,omitempty" db:"last_password_change"`
	
	CreatedAt   time.Time `json:"created_at" db:"created_at"`
	UpdatedAt   time.Time `json:"updated_at" db:"updated_at"`
	CreatedBy   string    `json:"created_by" validate:"required" db:"created_by"`
	UpdatedBy   string    `json:"updated_by" validate:"required" db:"updated_by"`
}

// UserProfile represents extended user profile information
type UserProfile struct {
	UserID      uuid.UUID              `json:"user_id" db:"user_id"`
	Bio         string                 `json:"bio,omitempty" validate:"omitempty,max=1000" db:"bio"`
	Location    string                 `json:"location,omitempty" validate:"omitempty,max=200" db:"location"`
	Website     string                 `json:"website,omitempty" validate:"omitempty,url,max=500" db:"website"`
	Timezone    string                 `json:"timezone,omitempty" validate:"omitempty,max=50" db:"timezone"`
	Language    string                 `json:"language,omitempty" validate:"omitempty,max=10" db:"language"`
	Preferences map[string]interface{} `json:"preferences,omitempty" db:"preferences"`
	CreatedAt   time.Time              `json:"created_at" db:"created_at"`
	UpdatedAt   time.Time              `json:"updated_at" db:"updated_at"`
}

// UserSession represents a user session
type UserSession struct {
	ID        uuid.UUID `json:"id" db:"id"`
	UserID    uuid.UUID `json:"user_id" validate:"required" db:"user_id"`
	Token     string    `json:"-" db:"token"` // Hidden from JSON
	IPAddress string    `json:"ip_address" validate:"required" db:"ip_address"`
	UserAgent string    `json:"user_agent" validate:"required" db:"user_agent"`
	ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
	CreatedAt time.Time `json:"created_at" db:"created_at"`
	LastUsedAt time.Time `json:"last_used_at" db:"last_used_at"`
}

// CreateUserRequest represents a request to create a new user
type CreateUserRequest struct {
	Email            string   `json:"email" validate:"required,email,max=255"`
	FirstName        string   `json:"first_name" validate:"required,min=1,max=100"`
	LastName         string   `json:"last_name" validate:"required,min=1,max=100"`
	DisplayName      *string  `json:"display_name,omitempty" validate:"omitempty,max=200"`
	Avatar           *string  `json:"avatar,omitempty" validate:"omitempty,url,max=500"`
	Role             UserRole `json:"role" validate:"required,oneof=admin user moderator viewer"`
	Status           UserStatus `json:"status" validate:"omitempty,oneof=active inactive suspended pending"`
	Password         *string  `json:"password,omitempty" validate:"omitempty,min=8,max=128"`
	SendWelcomeEmail bool     `json:"send_welcome_email" validate:"omitempty"`
}

// UpdateUserRequest represents a request to update an existing user
type UpdateUserRequest struct {
	Email       *string     `json:"email,omitempty" validate:"omitempty,email,max=255"`
	FirstName   *string     `json:"first_name,omitempty" validate:"omitempty,min=1,max=100"`
	LastName    *string     `json:"last_name,omitempty" validate:"omitempty,min=1,max=100"`
	DisplayName *string     `json:"display_name,omitempty" validate:"omitempty,max=200"`
	Avatar      *string     `json:"avatar,omitempty" validate:"omitempty,url,max=500"`
	Role        *UserRole   `json:"role,omitempty" validate:"omitempty,oneof=admin user moderator viewer"`
	Status      *UserStatus `json:"status,omitempty" validate:"omitempty,oneof=active inactive suspended pending"`
}

// UpdateUserProfileRequest represents a request to update user profile
type UpdateUserProfileRequest struct {
	Bio         *string                 `json:"bio,omitempty" validate:"omitempty,max=1000"`
	Location    *string                 `json:"location,omitempty" validate:"omitempty,max=200"`
	Website     *string                 `json:"website,omitempty" validate:"omitempty,url,max=500"`
	Timezone    *string                 `json:"timezone,omitempty" validate:"omitempty,max=50"`
	Language    *string                 `json:"language,omitempty" validate:"omitempty,max=10"`
	Preferences *map[string]interface{} `json:"preferences,omitempty"`
}

// ListUsersRequest represents a request to list users with filters
type ListUsersRequest struct {
	Status   *UserStatus `json:"status,omitempty" validate:"omitempty,oneof=active inactive suspended pending"`
	Role     *UserRole   `json:"role,omitempty" validate:"omitempty,oneof=admin user moderator viewer"`
	Search   string      `json:"search,omitempty" validate:"omitempty,max=255"`
	Limit    int         `json:"limit,omitempty" validate:"omitempty,min=1,max=100"`
	Offset   int         `json:"offset,omitempty" validate:"omitempty,min=0"`
	OrderBy  string      `json:"order_by,omitempty" validate:"omitempty,oneof=created_at updated_at email first_name last_name"`
	OrderDir string      `json:"order_dir,omitempty" validate:"omitempty,oneof=asc desc"`
}

// ListUsersResponse represents a response for listing users
type ListUsersResponse struct {
	Users      []User `json:"users"`
	Total      int    `json:"total"`
	Limit      int    `json:"limit"`
	Offset     int    `json:"offset"`
	HasMore    bool   `json:"has_more"`
}

// PasswordResetToken represents a password reset token
type PasswordResetToken struct {
	ID        uuid.UUID  `json:"id" db:"id"`
	UserID    uuid.UUID  `json:"user_id" db:"user_id"`
	Token     string     `json:"-" db:"token"` // Hidden from JSON
	ExpiresAt time.Time  `json:"expires_at" db:"expires_at"`
	UsedAt    *time.Time `json:"used_at,omitempty" db:"used_at"`
	CreatedAt time.Time  `json:"created_at" db:"created_at"`
	IPAddress *string    `json:"ip_address,omitempty" db:"ip_address"`
	UserAgent *string    `json:"user_agent,omitempty" db:"user_agent"`
}

// EmailVerificationToken represents an email verification token
type EmailVerificationToken struct {
	ID        uuid.UUID  `json:"id" db:"id"`
	UserID    uuid.UUID  `json:"user_id" db:"user_id"`
	Token     string     `json:"-" db:"token"` // Hidden from JSON
	Email     string     `json:"email" db:"email"`
	ExpiresAt time.Time  `json:"expires_at" db:"expires_at"`
	UsedAt    *time.Time `json:"used_at,omitempty" db:"used_at"`
	CreatedAt time.Time  `json:"created_at" db:"created_at"`
	IPAddress *string    `json:"ip_address,omitempty" db:"ip_address"`
	UserAgent *string    `json:"user_agent,omitempty" db:"user_agent"`
}

// LoginAttempt represents a login attempt record
type LoginAttempt struct {
	ID            uuid.UUID  `json:"id" db:"id"`
	Email         string     `json:"email" db:"email"`
	IPAddress     string     `json:"ip_address" db:"ip_address"`
	UserAgent     *string    `json:"user_agent,omitempty" db:"user_agent"`
	Success       bool       `json:"success" db:"success"`
	FailureReason *string    `json:"failure_reason,omitempty" db:"failure_reason"`
	AttemptedAt   time.Time  `json:"attempted_at" db:"attempted_at"`
	SessionID     *string    `json:"session_id,omitempty" db:"session_id"`
}

// TwoFactorRecoveryCode represents a 2FA recovery code
type TwoFactorRecoveryCode struct {
	ID       uuid.UUID  `json:"id" db:"id"`
	UserID   uuid.UUID  `json:"user_id" db:"user_id"`
	CodeHash string     `json:"-" db:"code_hash"` // Hidden from JSON
	UsedAt   *time.Time `json:"used_at,omitempty" db:"used_at"`
	CreatedAt time.Time `json:"created_at" db:"created_at"`
}

// AuthContext represents the authentication context for a request
type AuthContext struct {
	UserID      string            `json:"user_id"`
	Email       string            `json:"email"`
	Role        UserRole          `json:"role"`
	Permissions []string          `json:"permissions"`
	Claims      map[string]string `json:"claims"`
}

// Authentication Request/Response Types

// LoginRequest represents a login request
type LoginRequest struct {
	Email      string  `json:"email" validate:"required,email"`
	Password   string  `json:"password" validate:"required"`
	TwoFactorCode *string `json:"two_factor_code,omitempty" validate:"omitempty,len=6"`
	RememberMe bool    `json:"remember_me"`
}

// LoginResponse represents a login response
type LoginResponse struct {
	User               *User   `json:"user,omitempty"`
	Token              string  `json:"token"`
	ExpiresAt          time.Time `json:"expires_at"`
	RequiresTwoFactor  bool    `json:"requires_two_factor"`
	TwoFactorTempToken *string `json:"two_factor_temp_token,omitempty"`
}

// RegisterRequest represents a user registration request
type RegisterRequest struct {
	Email     string `json:"email" validate:"required,email,max=255"`
	Password  string `json:"password" validate:"required,min=8,max=128"`
	FirstName string `json:"first_name" validate:"required,min=1,max=100"`
	LastName  string `json:"last_name" validate:"required,min=1,max=100"`
	DisplayName *string `json:"display_name,omitempty" validate:"omitempty,max=200"`
}

// RegisterResponse represents a registration response
type RegisterResponse struct {
	User    *User  `json:"user"`
	Message string `json:"message"`
}

// ForgotPasswordRequest represents a forgot password request
type ForgotPasswordRequest struct {
	Email string `json:"email" validate:"required,email"`
}

// ResetPasswordRequest represents a reset password request
type ResetPasswordRequest struct {
	Token    string `json:"token" validate:"required"`
	Password string `json:"password" validate:"required,min=8,max=128"`
}

// ChangePasswordRequest represents a change password request
type ChangePasswordRequest struct {
	CurrentPassword string `json:"current_password" validate:"required"`
	NewPassword     string `json:"new_password" validate:"required,min=8,max=128"`
}

// VerifyEmailRequest represents an email verification request
type VerifyEmailRequest struct {
	Token string `json:"token" validate:"required"`
}

// ResendVerificationRequest represents a resend verification request
type ResendVerificationRequest struct {
	Email string `json:"email" validate:"required,email"`
}

// SetupTwoFactorResponse represents the response when setting up 2FA
type SetupTwoFactorResponse struct {
	Secret        string   `json:"secret"`
	QRCodeURL     string   `json:"qr_code_url"`
	BackupCodes   []string `json:"backup_codes"`
}

// EnableTwoFactorRequest represents a request to enable 2FA
type EnableTwoFactorRequest struct {
	Code string `json:"code" validate:"required,len=6"`
}

// DisableTwoFactorRequest represents a request to disable 2FA
type DisableTwoFactorRequest struct {
	Password string `json:"password" validate:"required"`
	Code     *string `json:"code,omitempty" validate:"omitempty,len=6"`
}

// ValidateTwoFactorRequest represents a 2FA validation request
type ValidateTwoFactorRequest struct {
	TempToken string `json:"temp_token" validate:"required"`
	Code      string `json:"code" validate:"required,len=6"`
}

// SessionInfo represents session information
type SessionInfo struct {
	ID         uuid.UUID `json:"id"`
	IPAddress  string    `json:"ip_address"`
	UserAgent  string    `json:"user_agent"`
	CreatedAt  time.Time `json:"created_at"`
	LastUsedAt time.Time `json:"last_used_at"`
	ExpiresAt  time.Time `json:"expires_at"`
	IsCurrent  bool      `json:"is_current"`
}

// ListSessionsResponse represents a list of user sessions
type ListSessionsResponse struct {
	Sessions []SessionInfo `json:"sessions"`
}