package user

// TODO: PQ Q N FUNCIONA??????????????
import (
	"fmt"
	"os"
	"strconv"

	"github.com/spf13/cobra"
	"gitlab.c3sl.ufpr.br/tss24/useradm/model"
)

var BulkCmd = &cobra.Command{
	Use:   "bulk",
	Short: "Create a lot of similar users",
	RunE:  bulkCreate,
}

func init() {
	BulkCmd.Flags().StringP("passwd", "p", "", "Base password, will generate <password>#[1..number]")
	BulkCmd.Flags().StringP("login", "l", "", "Base login, will generate <login>[1..number]")
	BulkCmd.Flags().StringP("expiry", "e", "_", "Accounts' expiry date (format dd.mm.yy)")
	BulkCmd.Flags().StringP("resp", "r", "_", "Person responsible for the accounts")
	BulkCmd.Flags().StringP("group", "g", "", "Base group of the accounts")
	BulkCmd.Flags().IntP("number", "n", 0, "Number of accounts to be created")

	BulkCmd.MarkFlagRequired("login")
	BulkCmd.MarkFlagRequired("passwd")
	BulkCmd.MarkFlagRequired("group")
	BulkCmd.MarkFlagRequired("number")
}

func bulkCreate(cmd *cobra.Command, args []string) error {
	var opts model.Opts
	var users []model.User

	users, err := getUsers()
	if err != nil {
		return err
	}

	err = opts.RetrieveOpts(cmd)
	if err != nil {
		return err
	}

	for i := 1; i <= opts.Number; i++ {
		if loginExists(users, opts.UID+strconv.Itoa(i)) {
			return fmt.Errorf("User found with login %v%v, won't overwrite", opts.UID, i)
		}
	}

	err = validateGID(opts.GID)
	if err != nil {
		return err
	}

	base := model.User{
		GRR:      "_",
		UID:      opts.UID,
		GID:      opts.GID,
		Name:     "_",
		Resp:     opts.Resp,
		Ltype:    "_",
		Shell:    "/bin/bash",
		Status:   "Active",
		Expiry:   opts.Expiry,
		Webdir:   "_",
		Password: opts.Passwd + "#",
	}

	base.Homedir, err = genDirPath("/home", base.GID, base.UID, "")
	if err != nil {
		return err
	}

	base.Nobackup, err = genDirPath("/nobackup", base.GID, base.UID, "")
	if err != nil {
		return err
	}

	i := 1
	success := false

	defer func() {
		if !success {
			fmt.Println("Error found, cleaning up...")
			for ; i > 0; i-- {
				istring := strconv.Itoa(i)
				_ = delKerberosPrincipal(base.UID + istring)
				_ = delUserLDAP(base.UID + istring)
				_ = os.RemoveAll(base.Nobackup + istring)
				_ = os.RemoveAll(base.Homedir + istring)
			}
		}
	}()

	for ; i <= opts.Number; i++ {
		err := createTempUser(base, i)
		if err != nil {
			return err
		}
	}

	success = true
	return nil
}

func createTempUser(base model.User, num int) error {
	var err error
	var groups map[string]string
	numstring := strconv.Itoa(num)

	groups, err = getGroups()
	if err != nil {
		return err
	}

	// gen login
	base.UID = base.UID + numstring

	// gen dn
	base.DN = "uid=" + base.UID + ",ou=usuarios,dc=c3local"

	// no webdir for temps

	// gen home path
	base.Homedir = base.Homedir + numstring

	// gen nobkp path
	base.Nobackup = base.Nobackup + numstring

	// gen password
	base.Password = base.Password + numstring

	// gen gecos
	base.Gecos = genGecos(base)

	// get group id
	base.GIDNumber, err = findGIDNumber(groups, base.GID)
	if err != nil {
		return err
	}

	// gen newuid
	base.UIDNumber, err = getNewUIDNumber()
	if err != nil {
		return err
	}

	fmt.Printf("Pronto para criar:\n%v\n\n", base.FullToString())
	confirmationPrompt(false, "creation")

	// create ldap
	err = addUserLDAP(base)
	if err != nil {
		return err
	}
	// create kerberos
	err = addKerberosPrincipal(base.UID)
	if err != nil {
		return err
	}

	// change pass
	err = modKerberosPassword(base.UID, base.Password)
	if err != nil {
		return err
	}

	// create dirs
	err = createUserDirs(base)
	if err != nil {
		return err
	}

	return nil
}