package models

import (
	"time"

	"github.com/google/uuid"
)

// User represents a user with full authentication support
type User struct {
	ID                  uuid.UUID  `json:"id" db:"id"`
	ExternalID          *string    `json:"external_id,omitempty" db:"external_id"`
	Email               string     `json:"email" db:"email"`
	PasswordHash        *string    `json:"-" db:"password_hash"` // Never exposed in JSON
	Name                *string    `json:"name,omitempty" db:"name"`
	Role                string     `json:"role" db:"role"` // 'user', 'admin', 'super_admin', 'data_protection_officer'
	EmailVerified       bool       `json:"email_verified" db:"email_verified"`
	EmailVerifiedAt     *time.Time `json:"email_verified_at,omitempty" db:"email_verified_at"`
	AccountStatus       string     `json:"account_status" db:"account_status"` // 'active', 'suspended', 'locked'
	LastLoginAt         *time.Time `json:"last_login_at,omitempty" db:"last_login_at"`
	FailedLoginAttempts int        `json:"failed_login_attempts" db:"failed_login_attempts"`
	LockedUntil         *time.Time `json:"locked_until,omitempty" db:"locked_until"`
	CreatedAt           time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt           time.Time  `json:"updated_at" db:"updated_at"`
}

// EmailVerificationToken for email verification
type EmailVerificationToken struct {
	ID        uuid.UUID  `json:"id" db:"id"`
	UserID    uuid.UUID  `json:"user_id" db:"user_id"`
	Token     string     `json:"token" db:"token"`
	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"`
}

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

// UserSession for session management
type UserSession struct {
	ID             uuid.UUID  `json:"id" db:"id"`
	UserID         uuid.UUID  `json:"user_id" db:"user_id"`
	TokenHash      string     `json:"-" db:"token_hash"`
	DeviceInfo     *string    `json:"device_info,omitempty" db:"device_info"`
	IPAddress      *string    `json:"ip_address,omitempty" db:"ip_address"`
	UserAgent      *string    `json:"user_agent,omitempty" db:"user_agent"`
	ExpiresAt      time.Time  `json:"expires_at" db:"expires_at"`
	RevokedAt      *time.Time `json:"revoked_at,omitempty" db:"revoked_at"`
	CreatedAt      time.Time  `json:"created_at" db:"created_at"`
	LastActivityAt time.Time  `json:"last_activity_at" db:"last_activity_at"`
}

// RegisterRequest for user registration
type RegisterRequest struct {
	Email    string  `json:"email" binding:"required,email"`
	Password string  `json:"password" binding:"required,min=8"`
	Name     *string `json:"name"`
}

// LoginRequest for user login
type LoginRequest struct {
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required"`
}

// LoginResponse after successful login
type LoginResponse struct {
	User         User   `json:"user"`
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int    `json:"expires_in"` // seconds
}

// RefreshTokenRequest for token refresh
type RefreshTokenRequest struct {
	RefreshToken string `json:"refresh_token" binding:"required"`
}

// VerifyEmailRequest for email verification
type VerifyEmailRequest struct {
	Token string `json:"token" binding:"required"`
}

// ForgotPasswordRequest for password reset request
type ForgotPasswordRequest struct {
	Email string `json:"email" binding:"required,email"`
}

// ResetPasswordRequest for password reset
type ResetPasswordRequest struct {
	Token       string `json:"token" binding:"required"`
	NewPassword string `json:"new_password" binding:"required,min=8"`
}

// ChangePasswordRequest for changing password
type ChangePasswordRequest struct {
	CurrentPassword string `json:"current_password" binding:"required"`
	NewPassword     string `json:"new_password" binding:"required,min=8"`
}

// UpdateProfileRequest for profile updates
type UpdateProfileRequest struct {
	Name *string `json:"name"`
}

// ========================================
// Two-Factor Authentication (2FA/TOTP)
// ========================================

// UserTOTP stores 2FA TOTP configuration for a user
type UserTOTP struct {
	ID            uuid.UUID  `json:"id" db:"id"`
	UserID        uuid.UUID  `json:"user_id" db:"user_id"`
	Secret        string     `json:"-" db:"secret"`              // Encrypted TOTP secret
	Verified      bool       `json:"verified" db:"verified"`     // Has 2FA been verified/activated
	RecoveryCodes []string   `json:"-" db:"recovery_codes"`      // Encrypted backup codes
	EnabledAt     *time.Time `json:"enabled_at,omitempty" db:"enabled_at"`
	LastUsedAt    *time.Time `json:"last_used_at,omitempty" db:"last_used_at"`
	CreatedAt     time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt     time.Time  `json:"updated_at" db:"updated_at"`
}

// TwoFactorChallenge represents a pending 2FA challenge during login
type TwoFactorChallenge struct {
	ID          uuid.UUID  `json:"id" db:"id"`
	UserID      uuid.UUID  `json:"user_id" db:"user_id"`
	ChallengeID string     `json:"challenge_id" db:"challenge_id"` // Temporary token
	IPAddress   *string    `json:"ip_address,omitempty" db:"ip_address"`
	UserAgent   *string    `json:"user_agent,omitempty" db:"user_agent"`
	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"`
}

// Setup2FAResponse when initiating 2FA setup
type Setup2FAResponse struct {
	Secret        string   `json:"secret"`         // Base32 encoded secret for manual entry
	QRCodeDataURL string   `json:"qr_code"`        // Data URL for QR code image
	RecoveryCodes []string `json:"recovery_codes"` // One-time backup codes
}

// Verify2FARequest for verifying 2FA setup or login
type Verify2FARequest struct {
	Code        string `json:"code" binding:"required"` // 6-digit TOTP code
	ChallengeID string `json:"challenge_id,omitempty"`  // For login flow
}

// TwoFactorLoginResponse when 2FA is required during login
type TwoFactorLoginResponse struct {
	RequiresTwoFactor bool   `json:"requires_two_factor"`
	ChallengeID       string `json:"challenge_id"` // Use this to complete 2FA
	Message           string `json:"message"`
}

// Complete2FALoginRequest to complete login with 2FA
type Complete2FALoginRequest struct {
	ChallengeID string `json:"challenge_id" binding:"required"`
	Code        string `json:"code" binding:"required"` // 6-digit TOTP or recovery code
}

// Disable2FARequest for disabling 2FA
type Disable2FARequest struct {
	Password string `json:"password" binding:"required"` // Require password confirmation
	Code     string `json:"code" binding:"required"`     // Current TOTP code
}

// RecoveryCodeUseRequest for using a recovery code
type RecoveryCodeUseRequest struct {
	ChallengeID  string `json:"challenge_id" binding:"required"`
	RecoveryCode string `json:"recovery_code" binding:"required"`
}

// TwoFactorStatusResponse for checking 2FA status
type TwoFactorStatusResponse struct {
	Enabled            bool       `json:"enabled"`
	Verified           bool       `json:"verified"`
	EnabledAt          *time.Time `json:"enabled_at,omitempty"`
	RecoveryCodesCount int        `json:"recovery_codes_count"`
}

// Verify2FAChallengeRequest for verifying a 2FA challenge during login
type Verify2FAChallengeRequest struct {
	ChallengeID  string `json:"challenge_id" binding:"required"`
	Code         string `json:"code,omitempty"`          // 6-digit TOTP code
	RecoveryCode string `json:"recovery_code,omitempty"` // Alternative: recovery code
}
