package webshared

import (
	"slices"
	"time"

	"git.mstar.dev/mstar/linstrom/shared"
	"git.mstar.dev/mstar/linstrom/storage-new/models"
)

// Web/json representation of a user
type User struct {
	// ---- Section public data ----
	// All data here will always be included, even if empty,
	// in which case it will be marked as null instead of omitted

	ID               string     `json:"id"`
	CreatedAt        time.Time  `json:"created_at"`
	ServerId         uint       `json:"server_id"`
	Displayname      string     `json:"displayname"`
	Description      string     `json:"description"`
	IsBot            bool       `json:"is_bot"`
	IconId           *string    `json:"icon_id"`
	BackgroundId     *string    `json:"background_id"`
	BannerId         *string    `json:"banner_id"`
	Indexable        bool       `json:"indexable"`
	PublicKey        []byte     `json:"public_key"`
	RestrictedFollow bool       `json:"restricted_follow"`
	Location         *string    `json:"location"`
	Birthday         *time.Time `json:"birthday"`

	// ---- Section Debug data ----
	// All these entries should only be available
	// for the debug server and should be cleared
	// before serving on the public server.
	// Every debug field must be omitempty
	Verified             *bool `json:"verified,omitempty"`
	FinishedRegistration *bool `json:"finished_registration,omitempty"`
}

// Compiler assertations for interface implementations
var _ shared.Santisable = &User{}
var _ shared.Clonable = &User{}

func (u *User) Sanitize() {
	u.Verified = nil
	u.FinishedRegistration = nil
}

func (u *User) Clone() shared.Clonable {
	user := *u
	if u.IconId != nil {
		tmp := *u.IconId
		user.IconId = &tmp
	}
	if u.BackgroundId != nil {
		tmp := *u.BackgroundId
		user.BackgroundId = &tmp
	}
	if u.BannerId != nil {
		tmp := *u.BannerId
		user.BannerId = &tmp
	}
	if u.Location != nil {
		tmp := *u.Location
		user.Location = &tmp
	}
	if u.Birthday != nil {
		tmp := *u.Birthday
		user.Birthday = &tmp
	}
	if u.Verified != nil {
		tmp := *u.Verified
		user.Verified = &tmp
	}
	if u.FinishedRegistration != nil {
		tmp := *u.FinishedRegistration
		user.FinishedRegistration = &tmp
	}
	user.PublicKey = slices.Clone(u.PublicKey)
	return &user
}

func (u *User) FromModel(m *models.User) {
	u.ID = m.ID
	u.CreatedAt = m.CreatedAt
	u.ServerId = m.ServerId
	u.Displayname = m.DisplayName
	u.IsBot = m.IsBot
	if m.IconId.Valid {
		u.IconId = &m.IconId.String
	}
	if m.BackgroundId.Valid {
		u.BackgroundId = &m.IconId.String
	}
	if m.BannerId.Valid {
		u.BannerId = &m.IconId.String
	}
	u.Indexable = m.Indexable
	u.PublicKey = append(u.PublicKey, m.PublicKey...)
	u.RestrictedFollow = m.RestrictedFollow
	if m.Location.Valid {
		u.Location = &m.Location.String
	}
	if m.Birthday.Valid {
		u.Birthday = &m.Birthday.Time
	}
	u.Verified = &m.Verified
	u.FinishedRegistration = &m.FinishedRegistration
}
