"""API key generation and hashing.

A key looks like ``lg_<43 url-safe chars>`` (a 256-bit random token). Only a keyed
HMAC-SHA256 digest and a short non-secret prefix are stored; the plaintext is
shown to the caller exactly once. The HMAC is peppered with the server secret, so
a database leak alone cannot be used to recover or verify keys, and it stays
deterministic so lookups by digest still work.
"""

from __future__ import annotations

import hashlib
import hmac
import secrets
from dataclasses import dataclass

from legate.config import get_settings

KEY_PREFIX = "lg_"


@dataclass(frozen=True)
class GeneratedApiKey:
    plaintext: str
    prefix: str
    hashed_key: str


def hash_api_key(plaintext: str) -> str:
    pepper = get_settings().legate_secret_key.encode("utf-8")
    return hmac.new(pepper, plaintext.encode("utf-8"), hashlib.sha256).hexdigest()


def generate_api_key() -> GeneratedApiKey:
    plaintext = KEY_PREFIX + secrets.token_urlsafe(32)
    # Display prefix: scheme + first 6 chars of the random body.
    prefix = plaintext[: len(KEY_PREFIX) + 6]
    return GeneratedApiKey(
        plaintext=plaintext,
        prefix=prefix,
        hashed_key=hash_api_key(plaintext),
    )
