"""
Patient portal PIN utilities.

- 6-character alphanumeric PINs from an unambiguous alphabet (no 0/O/1/I).
- bcrypt hash (`pin_hash`) is the login credential check.
- Fernet-encrypted copy (`portal_pin_enc`) allows displaying the CURRENT pin
  on bill receipts and signed reports. Key derived from the app JWT secret —
  no extra env configuration, never exposed via API except at issue time.
"""

import base64
import hashlib
import secrets

from cryptography.fernet import Fernet, InvalidToken

from app.config import settings

PIN_ALPHABET = "ABCDEFGHJKMNPQRSTUVWXYZ23456789"
PIN_LENGTH = 6


def generate_pin() -> str:
    """Generate a random 6-character alphanumeric portal PIN."""
    return "".join(secrets.choice(PIN_ALPHABET) for _ in range(PIN_LENGTH))


def _fernet() -> Fernet:
    digest = hashlib.sha256(settings.JWT_SECRET_KEY.encode("utf-8")).digest()
    return Fernet(base64.urlsafe_b64encode(digest))


def encrypt_pin(plain_pin: str) -> str:
    """Reversibly encrypt the current PIN for display purposes."""
    return _fernet().encrypt(plain_pin.encode("utf-8")).decode("ascii")


def decrypt_pin(enc_pin: str | None) -> str | None:
    """Recover the current PIN for receipts/reports. None when absent/broken."""
    if not enc_pin:
        return None
    try:
        return _fernet().decrypt(enc_pin.encode("ascii")).decode("utf-8")
    except (InvalidToken, ValueError):
        return None
