// Package domain holds the core data model types and business rules shared
// across handlers, stores, and workers. It has no Mongo or HTTP dependencies
// beyond bson struct tags.
package domain

import "time"

type Roles struct {
	Admin      bool `bson:"admin" json:"admin"`
	Consultant bool `bson:"consultant" json:"consultant"`
	Developer  bool `bson:"developer" json:"developer"`
}

// Has reports whether the role named r is set. Known names: admin,
// consultant, developer.
func (r Roles) Has(role string) bool {
	switch role {
	case "admin":
		return r.Admin
	case "consultant":
		return r.Consultant
	case "developer":
		return r.Developer
	default:
		return false
	}
}

type LocalAuth struct {
	PasswordHash string `bson:"passwordHash" json:"-"`
	MustChange   bool   `bson:"mustChange" json:"mustChange"`
}

type OIDCAuth struct {
	Issuer  string `bson:"issuer" json:"issuer"`
	Subject string `bson:"subject" json:"subject"`
}

type Auth struct {
	Local *LocalAuth `bson:"local" json:"local,omitempty"`
	OIDC  *OIDCAuth  `bson:"oidc" json:"oidc,omitempty"`
}

type Contact struct {
	Phone    string   `bson:"phone" json:"phone"`
	Location string   `bson:"location" json:"location"`
	Links    []string `bson:"links" json:"links"`
}

type NotificationPrefs struct {
	Email bool `bson:"email" json:"email"`
	InApp bool `bson:"inApp" json:"inApp"`
}

type UserSettings struct {
	Theme             string            `bson:"theme" json:"theme"`
	NavLayout         string            `bson:"navLayout" json:"navLayout"` // "side" (default) | "top"
	Notifications     NotificationPrefs `bson:"notifications" json:"notifications"`
	LeaderboardOptOut bool              `bson:"leaderboardOptOut" json:"leaderboardOptOut"`
}

type User struct {
	ID           string         `bson:"_id" json:"id"`
	Email        string         `bson:"email" json:"email"`
	Name         string         `bson:"name" json:"name"`
	AvatarFileID string         `bson:"avatarFileId,omitempty" json:"avatarFileId,omitempty"`
	Bio          string         `bson:"bio" json:"bio"`
	Contact      Contact        `bson:"contact" json:"contact"`
	Extra        map[string]any `bson:"extra" json:"extra"`
	Roles        Roles          `bson:"roles" json:"roles"`
	Auth         Auth           `bson:"auth" json:"-"`
	Settings     UserSettings   `bson:"settings" json:"settings"`
	Disabled     bool           `bson:"disabled" json:"disabled"`
	LastSeenAt   time.Time      `bson:"lastSeenAt" json:"lastSeenAt"`
	CreatedAt    time.Time      `bson:"createdAt" json:"createdAt"`
	UpdatedAt    time.Time      `bson:"updatedAt" json:"updatedAt"`
	Version      int64          `bson:"version" json:"version"`
}

// MustChangePassword reports whether the user is locked to the
// password-change flow.
func (u *User) MustChangePassword() bool {
	return u.Auth.Local != nil && u.Auth.Local.MustChange
}
