package security

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base32"
	"encoding/hex"
	"fmt"
	"strings"
)

func GenerateRecoveryCodes(count int) ([]string, error) {
	if count <= 0 {
		count = 10
	}
	codes := make([]string, 0, count)
	for len(codes) < count {
		raw := make([]byte, 10)
		if _, err := rand.Read(raw); err != nil {
			return nil, err
		}
		encoded := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(raw)
		codes = append(codes, formatRecoveryCode(encoded))
	}
	return codes, nil
}

func RecoveryCodeHash(code string) string {
	sum := sha256.Sum256([]byte(normalizeRecoveryCode(code)))
	return hex.EncodeToString(sum[:])
}

func ChallengeHash(challenge string) string {
	sum := sha256.Sum256([]byte(strings.TrimSpace(challenge)))
	return hex.EncodeToString(sum[:])
}

func normalizeRecoveryCode(code string) string {
	code = strings.ToUpper(strings.TrimSpace(code))
	code = strings.ReplaceAll(code, "-", "")
	code = strings.ReplaceAll(code, " ", "")
	return code
}

func formatRecoveryCode(encoded string) string {
	encoded = strings.ToUpper(strings.TrimSpace(encoded))
	if len(encoded) < 16 {
		return encoded
	}
	return fmt.Sprintf("%s-%s-%s-%s", encoded[0:4], encoded[4:8], encoded[8:12], encoded[12:16])
}
