// Package codes implements the activation-code lifecycle:
// batch generation, card-store webhook ingestion, idempotent redemption,
// subscription extension, and CSV export.
//
// Security invariant: plaintext codes are NEVER written to the database or
// to any log.  The database stores only SHA-256(canonical_plaintext).
// Plaintext appears exactly once: in the batch-generation response / CSV export.
package codes

import (
	"errors"

	"github.com/wangjia/pangolin/server/internal/idgen"
)

// GenerateCode generates a single random activation code in canonical Crockford
// Base32 form (15 random data chars + 1 check char = 16 chars total).
// It delegates to idgen.GenerateCode which uses crypto/rand.
func GenerateCode() (string, error) {
	return idgen.GenerateCode()
}

// Canonicalize converts an activation-code string into canonical form:
// uppercase, with I/L→1 and O→0 substitutions applied.
// Hyphens and spaces are stripped before validation.
// Returns an error if the string contains characters outside the normalised
// Crockford alphabet, if the length is not exactly 16, or if the check character
// is incorrect.
func Canonicalize(code string) (string, error) {
	return idgen.CanonicalizeCode(code)
}

// Hash returns the hex-encoded SHA-256 of the canonical plaintext code.
// This is the value stored in the database; the plaintext is never stored.
func Hash(canonical string) string {
	return idgen.HashCode(canonical)
}

// ErrDuplicate is returned by the batch generator when a generated code
// already exists in the database (hash collision).  The caller should retry.
var ErrDuplicate = errors.New("codes: duplicate code hash")
