// This file is part of the happyDomain (R) project.
// Copyright (c) 2020-2024 happyDomain
// Authors: Pierre-Olivier Mercier, et al.
//
// This program is offered under a commercial and under the AGPL license.
// For commercial licensing, contact us at <contact@happydomain.org>.
//
// For AGPL licensing:
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

package happydns

import (
	"io"
	"time"
)

// User represents an account.
type User struct {
	// Id is the User's identifier.
	Id Identifier `json:"id" swaggertype:"string" binding:"required" readonly:"true"`

	// Email is the User's login and means of contact.
	Email string `json:"email" binding:"required"`

	// CreatedAt is the time when the User logs in for the first time.
	CreatedAt time.Time `json:"created_at" format:"date-time" binding:"required" readonly:"true"`

	// LastSeen is the time when the User used happyDNS for the last time (in a 12h frame).
	LastSeen time.Time `json:"last_seen" format:"date-time" binding:"required" readonly:"true"`

	// Settings holds the settings for an account.
	Settings UserSettings `json:"settings" binding:"required"`

	// Quota holds admin-controlled limits for the account. It is never
	// writable through the user-facing API; only the admin API can update it.
	Quota UserQuota `json:"quota"`
}

func (u *User) GetUserId() Identifier {
	return u.Id
}

func (u *User) GetEmail() string {
	return u.Email
}

func (u *User) JoinNewsletter() bool {
	return false
}

type UserUsecase interface {
	ChangeUserSettings(*User, UserSettings) error
	CreateUser(UserInfo) (*User, error)
	DeleteUser(Identifier) error
	GenerateUserAvatar(*User, int, io.Writer) error
	GetUser(Identifier) (*User, error)
	GetUserByEmail(string) (*User, error)
	UpdateUser(Identifier, func(*User)) (*User, error)
}

// AdminUserUsecase exposes administrative user operations that bypass the
// caller-scoped checks of UserUsecase. Admin callers can create/replace any
// user, list every user, wipe the user table, and force-delete users that
// the standard DeleteUser refuses to remove (e.g. locally-authenticated
// accounts which are otherwise expected to delete themselves).
type AdminUserUsecase interface {
	ListAllUsers() ([]*User, error)
	CreateOrUpdateUser(*User) error
	ClearUsers() error
	DeleteUserByID(Identifier) error
}
