package users

import (
	"time"

	"gorm.io/gorm"
)

// UserRoles is stored as JSON array of strings.

// Typescript: type
type UserRoles []string

// Typescript: interface
type User struct {
	ID          int              `json:"id" gorm:"primaryKey"`
	Email       string           `json:"email" gorm:"uniqueIndex;size:255"`
	Name        string           `json:"name" gorm:"size:255"`
	Password    string           `json:"-" gorm:"size:255"`
	Roles       UserRoles        `json:"roles" gorm:"type:text;serializer:json"`
	Types       UserTypes        `json:"types" gorm:"type:text;serializer:json"`
	Status      UserStatus       `json:"status" gorm:"type:text;default:'pending'"`
	ActivatedAt *time.Time       `json:"activatedAt" ts:"type=Date"`
	UUID        string           `json:"uuid" gorm:"size:36"`
	Details     *UserDetails     `json:"details" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
	Preferences *UserPreferences `json:"preferences" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
	Avatar      *string          `json:"avatar" gorm:"size:512"`
	CreatedAt   time.Time        `json:"createdAt" ts:"type=Date"`
	UpdatedAt   time.Time        `json:"updatedAt" ts:"type=Date"`
	DeletedAt   gorm.DeletedAt   `json:"-" gorm:"index" ts:"type=Date"`
}

// UserCreateInput captures the minimal payload to create a user.

// Typescript: interface
type UserCreateInput struct {
	Name        string           `json:"name" validate:"required,min=1,max=255"`
	Email       string           `json:"email" validate:"required,email"`
	Password    string           `json:"password" validate:"required,min=8,max=128"`
	Roles       UserRoles        `json:"roles"`
	Status      UserStatus       `json:"status"`
	Types       UserTypes        `json:"types"`
	Avatar      *string          `json:"avatar"`
	Details     *UserDetails     `json:"details" `
	Preferences *UserPreferences `json:"preferences" `
}

// UserTypes is stored as JSON array (e.g. ["internal","external"]).
type UserTypes []string

// UserProfile is the safe full representation of a user returned by CRUD endpoints.

// Typescript: interface
type UserProfile struct {
	ID          int              `json:"id"`
	Email       string           `json:"email"`
	Name        string           `json:"name"`
	Roles       UserRoles        `json:"roles"`
	Types       UserTypes        `json:"types"`
	Status      UserStatus       `json:"status"`
	ActivatedAt *time.Time       `json:"activatedAt" ts:"type=Date"`
	UUID        string           `json:"uuid"`
	Details     *UserDetails     `json:"details"`
	Preferences *UserPreferences `json:"preferences"`
	Avatar      *string          `json:"avatar"`
	CreatedAt   time.Time        `json:"createdAt" ts:"type=Date"`
	UpdatedAt   time.Time        `json:"updatedAt" ts:"type=Date"`
}

// ToUserProfile maps a User to a full response without exposing the password hash.
func ToUserProfile(u *User) UserProfile {
	if u == nil {
		return UserProfile{}
	}
	return UserProfile{
		ID:          u.ID,
		Email:       u.Email,
		Name:        u.Name,
		Roles:       u.Roles,
		Types:       u.Types,
		Status:      u.Status,
		ActivatedAt: u.ActivatedAt,
		UUID:        u.UUID,
		Details:     u.Details,
		Preferences: u.Preferences,
		Avatar:      u.Avatar,
		CreatedAt:   u.CreatedAt,
		UpdatedAt:   u.UpdatedAt,
	}
}

// UserPreferences holds per-user settings stored as JSON.

// Typescript: interface
type UserPreferences struct {
	ID               int       `json:"id" gorm:"primaryKey"`
	UserID           int       `json:"userId" gorm:"index"`
	UseIdle          bool      `json:"useIdle"`
	IdleTimeout      int       `json:"idleTimeout"`
	UseIdlePassword  bool      `json:"useIdlePassword"`
	IdlePin          string    `json:"idlePin"`
	UseDirectLogin   bool      `json:"useDirectLogin"`
	UseQuadcodeLogin bool      `json:"useQuadcodeLogin"`
	SendNoticesMail  bool      `json:"sendNoticesMail"`
	Language         string    `json:"language"`
	CreatedAt        time.Time `json:"createdAt" ts:"type=Date"`
	UpdatedAt        time.Time `json:"updatedAt" ts:"type=Date"`
}

// UserDetails holds optional profile data.

// Typescript: interface
type UserDetails struct {
	ID        int       `json:"id" gorm:"primaryKey"`
	UserID    int       `json:"userId" gorm:"index"`
	Title     string    `json:"title"`
	FirstName string    `json:"firstName"`
	LastName  string    `json:"lastName"`
	Address   string    `json:"address"`
	City      string    `json:"city"`
	ZipCode   string    `json:"zipCode"`
	Country   string    `json:"country"`
	Phone     string    `json:"phone"`
	CreatedAt time.Time `json:"createdAt" ts:"type=Date"`
	UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"`
}

// UserDetails holds optional profile data.

// Session tracks logins with browser metadata.

type Session struct {
	ID               int            `json:"id" gorm:"primaryKey"`
	UserID           *int           `json:"userId" gorm:"index"`
	Username         string         `json:"username" gorm:"size:255"`
	AccessTokenHash  string         `json:"-" gorm:"size:128;index"`
	RefreshTokenHash string         `json:"-" gorm:"size:128;index"`
	ExpiresAt        time.Time      `json:"expiresAt" ts:"type=Date" gorm:"index"`
	IPAddress        string         `json:"ipAddress" gorm:"size:64"`
	UserAgent        string         `json:"userAgent" gorm:"size:512"`
	CreatedAt        time.Time      `json:"createdAt" ts:"type=Date"`
	UpdatedAt        time.Time      `json:"updatedAt" ts:"type=Date"`
	DeletedAt        gorm.DeletedAt `json:"-" gorm:"index" `
}

type PasswordResetToken struct {
	ID        int            `json:"id" gorm:"primaryKey"`
	UserID    int            `json:"userId" gorm:"index"`
	TokenHash string         `json:"-" gorm:"size:64;uniqueIndex"`
	ExpiresAt time.Time      `json:"expiresAt" ts:"type=Date" gorm:"index"`
	UsedAt    *time.Time     `json:"usedAt" ts:"type=Date"`
	CreatedAt time.Time      `json:"createdAt" ts:"type=Date"`
	UpdatedAt time.Time      `json:"updatedAt" ts:"type=Date"`
	DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

// UserStatus represents lifecycle state of a user.
type UserStatus string

// Typescript: enum=UserStatus
const (
	UserStatusPending  UserStatus = "pending"
	UserStatusActive   UserStatus = "active"
	UserStatusDisabled UserStatus = "disabled"
)

// Typescript: interface
type LoginRequest struct {
	Username string `json:"username" validate:"required,email"`
	Password string `json:"password" validate:"required,min=8,max=128"`
}

// Typescript: interface
type RefreshRequest struct {
	RefreshToken string `json:"refresh_token"`
}

// Typescript: interface
type ForgotPasswordRequest struct {
	Email string `json:"email" validate:"required,email"`
}

// Typescript: interface
type ResetPasswordRequest struct {
	Token    string `json:"token" validate:"required,min=20,max=255"`
	Password string `json:"password" validate:"required,min=8,max=128"`
}
