You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: users_add.go
    path of file: ./repos/photoprism/internal/commands
    
    the code of the file until where you have to start completion: package commands

import (
	"errors"
	"fmt"

	"github.com/manifoldco/promptui"
	"github.com/urfave/cli"

	"github.com/photoprism/photoprism/internal/config"
	"github.com/photoprism/photoprism/internal/entity"
	"github.com/photoprism/photoprism/internal/form"
	"github.com/photoprism/photoprism/pkg/clean"
	"github.com/photoprism/photoprism/pkg/txt"
)

// UsersAddCommand configures the command name, flags, and action.
var UsersAddCommand = cli.Command{
	Name:      "add",
	Usage:     "Creates a new user account",
	ArgsUsage: "[username]",
	Flags:     UserFlags,
	Action:    usersAddAction,
}

// usersAddAction adds a new user account.
func usersAddAction(ctx *cli.Context) error {
	return CallWithDependencies(ctx, func(conf *config.Config) error {
		conf.MigrateDb(false, nil)

		frm := form.NewUserFromCli(ctx)

		interactive := true

		if frm.UserName != "" && frm.Password != "" {
			log.Debugf("user will be added in non-interactive mode")
			interactive = false
		}

		if interactive && frm.UserName == "" {
			prompt := promptui.Prompt{
				Label: "Username",
			}

			
    
func usersAddAction(ctx *cli.Context) error {
	return CallWithDependencies(ctx, func(conf *config.Config) error {
		conf.MigrateDb(false, nil)

		frm := form.NewUserFromCli(ctx)

		interactive := true

		if frm.UserName != "" && frm.Password != "" {
			log.Debugf("user will be added in non-interactive mode")
			interactive = false
		}

		if interactive && frm.UserName == "" {
			prompt := promptui.Prompt{
				Label: "Username",
			}

			res, err := prompt.Run()

			if err != nil {
				return err
			}

			frm.UserName = clean.Username(res)
		}

		// Check if account exists but is deleted.
		if frm.UserName == "" {
			return fmt.Errorf("username is required")
		} else if m := entity.FindUserByName(frm.UserName); m != nil {
			if !m.IsDeleted() {
				return fmt.Errorf("user already exists")
			}

			prompt := promptui.Prompt{
				Label:     fmt.Sprintf("Restore user %s?", m.String()),
				IsConfirm: true,
			}

			if _, err := prompt.Run(); err != nil {
				return fmt.Errorf("user already exists")
			}

			if err := m.RestoreFromCli(ctx, frm.Password); err != nil {
				return err
			}

			log.Infof("user %s has been restored", m.String())

			return nil
		}

		if interactive && frm.UserEmail == "" {
			prompt := promptui.Prompt{
				Label: "Email",
			}

			res, err := prompt.Run()

			if err != nil {
				return err
			}

			frm.UserEmail = clean.Email(res)
		}

		if interactive && len([]rune(ctx.String("password"))) < entity.PasswordLength {
			validate := func(input string) error {
				if len([]rune(input)) < entity.PasswordLength {
					return fmt.Errorf("password must have at least %d characters", entity.PasswordLength)
				} else if len(input) > txt.ClipPassword {
					return fmt.Errorf("password must have less than %d characters", txt.ClipPassword)
				}
				return nil
			}
			prompt := promptui.Prompt{
				Label:    "Password",
				Validate: validate,
				Mask:     '*',
			}
			resPasswd, err := prompt.Run()
			if err != nil {
				return err
			}
			validateRetype := func(input string) error {
				if input != resPasswd {
					return errors.New("passwords do not match")
				}
				return nil
			}
			confirm := promptui.Prompt{
				Label:    "Retype Password",
				Validate: validateRetype,
				Mask:     '*',
			}
			resConfirm, err := confirm.Run()
			if err != nil {
				return err
			}
			if resConfirm != resPasswd {
				return errors.New("password is invalid, please try again")
			} else {
				frm.Password = resPasswd
			}
		}

		if err := entity.AddUser(frm); err != nil {
			return err
		}

		return nil
	})
}