package main

import (
	"bytes"
	"fmt"
	"math/rand"

	pwgen "github.com/sethvargo/go-password/password"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/crypto/ssh/terminal"
)

type PasswordParam struct {
	Password               string `name:"password" help:"The password to be set. Empty to prompt."`
	GeneratePassword       bool   `name:"generate-password" help:"If set, the password is auto generated."`
	GeneratePasswordLength int    `name:"password-length" help:"If generate-password is set, this specified the length of the generated password." default:"32"`
}

func (p *PasswordParam) acquirePassword() (string, error) {
	if p.GeneratePassword {
		// math.rand is not secure. For determining the number of digits in a password
		// it should suffice, though. Beware that we expect here that we at least initialized
		// the seed somewhere.
		pw, err := pwgen.Generate(p.GeneratePasswordLength, rand.Intn(p.GeneratePasswordLength/2), 0, false, true)
		if err != nil {
			return "", fmt.Errorf("cannot generate password: %w", err)
		}

		p.Password = pw

		fmt.Printf("Password generated: %s\n", p.Password)
	}

	if p.Password == "" {
		fmt.Printf("Enter password: ")
		bytePassword, err := terminal.ReadPassword(0)
		if err != nil {
			fmt.Println()
			return "", fmt.Errorf("error reading password: %w", err)
		}
		fmt.Printf("\nRepeat password: ")
		bytePasswordRepeat, err := terminal.ReadPassword(0)
		if err != nil {
			fmt.Println()
			return "", fmt.Errorf("error reading password: %w", err)
		}
		fmt.Println()

		if !bytes.Equal(bytePassword, bytePasswordRepeat) {
			return "", fmt.Errorf("passwords do not match")
		}

		p.Password = string(bytePassword)
	}

	if p.Password == "" {
		return "", fmt.Errorf("empty password supplied")
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(p.Password), 0)
	if err != nil {
		return "", fmt.Errorf("cannot hash password: %w", err)
	}

	return string(hash), nil
}
