package auth

import (
	"crypto/rand"
	"math/big"

	"golang.org/x/crypto/bcrypt"
)

const passwordAlphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"

func HashPassword(password string) (string, error) {
	hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", err
	}
	return string(hashed), nil
}

func VerifyPassword(plain string, hashed string) bool {
	return bcrypt.CompareHashAndPassword([]byte(hashed), []byte(plain)) == nil
}

func GeneratePassword(length int) (string, error) {
	if length < 8 {
		length = 14
	}
	for {
		out := make([]byte, length)
		var upper, lower, digit, symbol bool
		for i := range out {
			n, err := rand.Int(rand.Reader, big.NewInt(int64(len(passwordAlphabet))))
			if err != nil {
				return "", err
			}
			ch := passwordAlphabet[n.Int64()]
			out[i] = ch
			switch {
			case ch >= 'A' && ch <= 'Z':
				upper = true
			case ch >= 'a' && ch <= 'z':
				lower = true
			case ch >= '0' && ch <= '9':
				digit = true
			default:
				symbol = true
			}
		}
		if upper && lower && digit && symbol {
			return string(out), nil
		}
	}
}
