package accountservice

import (
	"context"

	"github.com/tech/sendico/pkg/auth"
	"github.com/tech/sendico/pkg/auth/management"
	"github.com/tech/sendico/pkg/db"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/model"
	accountserviceimp "github.com/tech/sendico/server/interface/accountservice/internal"
	"github.com/tech/sendico/server/interface/middleware"
	"go.mongodb.org/mongo-driver/v2/bson"
)

// AccountService defines all account-related workflows.
type AccountService interface {
	// ValidateAccount will:
	//   1) check it's completeness
	//   2) hash password
	//   3) prepare verification token
	ValidateAccount(
		acct *model.Account,
	) error

	// ValidatePassword will:
	//   1) check passsword conformance
	ValidatePassword(
		password string,
		oldPassword *string,
	) error

	// ResetPassword will:
	//   1) generate reset password token
	ResetPassword(
		ctx context.Context,
		acct *model.Account,
	) (verificationToken string, err error)

	// CreateAccount will:
	//   1) create the account
	//   2) add it to the org’s member list
	//   3) assign the given role description to it
	CreateAccount(
		ctx context.Context,
		org *model.Organization,
		acct *model.Account,
		roleDescID bson.ObjectID,
	) (verificationToken string, err error)

	VerifyAccount(
		ctx context.Context,
		acct *model.Account,
	) (verificationToken string, err error)

	JoinOrganization(
		ctx context.Context,
		org *model.Organization,
		acct *model.Account,
		roleDescID bson.ObjectID,
	) error

	UpdateLogin(
		ctx context.Context,
		acct *model.Account,
		newLogin string,
	) (verificationToken string, err error)

	// DeleteAccount deletes the account and removes it from the org.
	DeleteAccount(
		ctx context.Context,
		org *model.Organization,
		accountRef bson.ObjectID,
	) error

	// RemoveAccountFromOrganization just drops it from the member slice.
	RemoveAccountFromOrganization(
		ctx context.Context,
		org *model.Organization,
		accountRef bson.ObjectID,
	) error

	DeleteOrganization(
		ctx context.Context,
		org *model.Organization,
	) error

	// DeleteAll deletes both the organization and the account.
	DeleteAll(
		ctx context.Context,
		org *model.Organization,
		accountRef bson.ObjectID,
	) error
}

func NewAccountService(
	logger mlogger.Logger,
	dbf db.Factory,
	enforcer auth.Enforcer,
	roleManeger management.Role,
	config *middleware.PasswordConfig,
) (AccountService, error) {
	return accountserviceimp.NewAccountService(logger, dbf, enforcer, roleManeger, config)
}
