"""PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0. RFC 7636 compliant."""

import base64
import hashlib
import secrets
import string

# Unreserved characters per RFC 7636
_UNRESERVED = string.ascii_letters + string.digits + "-._~"


def generate_code_verifier(length: int = 64) -> str:
    """Generate a cryptographically random code verifier (43-128 characters).

    Uses unreserved characters per RFC 7636: [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
    """
    return "".join(secrets.choice(_UNRESERVED) for _ in range(length))


def generate_code_challenge(verifier: str) -> str:
    """Generate a code challenge from a code verifier using S256 method.

    SHA-256 hash of the verifier, base64url-encoded (no padding).
    """
    digest = hashlib.sha256(verifier.encode("ascii")).digest()
    return base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
