package models

import (
	"database/sql/driver"
	"encoding/json"
	"time"

	"github.com/google/uuid"
)

// ClientUser represents a user belonging to a client
type ClientUser struct {
	ID        uuid.UUID  `json:"id" db:"id"`
	ClientID  string     `json:"client_id" db:"client_id"` // VARCHAR in database to match clients.id

	// Personal Details
	FirstName    *string    `json:"first_name" db:"first_name"`
	LastName     *string    `json:"last_name" db:"last_name"`
	Email        *string    `json:"email" db:"email"`
	Phone        *string    `json:"phone" db:"phone"`
	DateOfBirth  *time.Time `json:"date_of_birth" db:"date_of_birth"`
	Gender       *string    `json:"gender" db:"gender"`
	Address      *string    `json:"address" db:"address"`
	City         *string    `json:"city" db:"city"`
	State        *string    `json:"state" db:"state"`
	Country      *string    `json:"country" db:"country"`
	PostalCode   *string    `json:"postal_code" db:"postal_code"`

	// Authentication
	Username     *string    `json:"username" db:"username"`
	Password     string      `json:"-" db:"password"` // Never return password in JSON

	// Role and Permissions
	Role         *string    `json:"role" db:"role"`
	Permissions  *Permissions `json:"permissions" db:"permissions"`

	// Status
	Status       string     `json:"status" db:"status"`
	IsActive     bool       `json:"is_active" db:"is_active"`
	IsVerified   bool       `json:"is_verified" db:"is_verified"`
	EmailVerifiedAt *time.Time `json:"email_verified_at" db:"email_verified_at"`
	PhoneVerifiedAt *time.Time `json:"phone_verified_at" db:"phone_verified_at"`

	// Profile
	AvatarURL    *string    `json:"avatar_url" db:"avatar_url"`
	Bio          *string    `json:"bio" db:"bio"`
	PreferredLanguage *string `json:"preferred_language" db:"preferred_language"`
	Timezone     *string    `json:"timezone" db:"timezone"`

	// Logs and Tracking
	LastLogin    *time.Time `json:"last_login" db:"last_login"`
	LastLoginIP  *string    `json:"last_login_ip" db:"last_login_ip"`
	LastActivity *time.Time `json:"last_activity" db:"last_activity"`
	LoginCount   int        `json:"login_count" db:"login_count"`
	FailedLoginAttempts int `json:"failed_login_attempts" db:"failed_login_attempts"`
	LockedUntil  *time.Time `json:"locked_until" db:"locked_until"`

	// Audit Fields
	CreatedBy    *uuid.UUID `json:"created_by" db:"created_by"`
	UpdatedBy    *uuid.UUID `json:"updated_by" db:"updated_by"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at" db:"updated_at"`
	DeletedAt    *time.Time `json:"deleted_at" db:"deleted_at"`
}

// Permissions represents user permissions as JSON
type Permissions struct {
	CanManageUsers    bool `json:"can_manage_users"`
	CanManagePackages bool `json:"can_manage_packages"`
	CanManageVouchers bool `json:"can_manage_vouchers"`
	CanViewReports    bool `json:"can_view_reports"`
	CanManagePayments bool `json:"can_manage_payments"`
	CanManageSettings bool `json:"can_manage_settings"`
	CanViewLogs       bool `json:"can_view_logs"`
}

// Value implements the driver.Valuer interface for database storage
func (p *Permissions) Value() (driver.Value, error) {
	if p == nil {
		return nil, nil
	}
	return json.Marshal(p)
}

// Scan implements the sql.Scanner interface for database retrieval
func (p *Permissions) Scan(value interface{}) error {
	if value == nil {
		*p = Permissions{}
		return nil
	}

	bytes, ok := value.([]byte)
	if !ok {
		return json.Unmarshal([]byte(value.(string)), p)
	}

	return json.Unmarshal(bytes, p)
}

// ClientUserInfo represents public user information (without sensitive data)
type ClientUserInfo struct {
	ID        uuid.UUID  `json:"id"`
	ClientID  string     `json:"client_id"` // VARCHAR in database to match clients.id
	FirstName *string    `json:"first_name"`
	LastName  *string    `json:"last_name"`
	Email     *string    `json:"email"`
	Phone     *string    `json:"phone"`
	Username  *string    `json:"username"`
	Role      *string    `json:"role"`
	Status    string     `json:"status"`
	IsActive  bool       `json:"is_active"`
	AvatarURL *string    `json:"avatar_url"`
	LastLogin *time.Time `json:"last_login"`
	CreatedAt time.Time  `json:"created_at"`
}

// CreateClientUserRequest represents the request to create a new client user
type CreateClientUserRequest struct {
	ClientID    string      `json:"client_id" validate:"required"`
	FirstName   *string     `json:"first_name"`
	LastName    *string     `json:"last_name"`
	Email       *string     `json:"email" validate:"omitempty,email"`
	Phone       *string     `json:"phone"`
	Username    *string     `json:"username" validate:"required"`
	Password    string      `json:"password" validate:"required,min=6"`
	Role        *string     `json:"role"`
	Permissions *Permissions `json:"permissions"`
	Status      *string     `json:"status"`
	IsActive    *bool       `json:"is_active"`
}

// UpdateClientUserRequest represents the request to update a client user
type UpdateClientUserRequest struct {
	FirstName   *string     `json:"first_name"`
	LastName    *string     `json:"last_name"`
	Email       *string     `json:"email" validate:"omitempty,email"`
	Phone       *string     `json:"phone"`
	Username    *string     `json:"username"`
	Role        *string     `json:"role"`
	Permissions *Permissions `json:"permissions"`
	Status      *string     `json:"status"`
	IsActive    *bool       `json:"is_active"`
	AvatarURL   *string     `json:"avatar_url"`
	Bio         *string     `json:"bio"`
}

