"""Reversible, URL-safe encryption for numeric IDs embedded in emailed deep
links (e.g. the JD approval "View JD" button), so raw primary keys aren't
exposed/guessable in a URL that may be forwarded outside the org.

Same Fernet-based approach as apps/llm/crypto.py, keyed off a dedicated
setting with a SECRET_KEY-derived fallback for dev.
"""
import base64
import hashlib

from django.conf import settings
from cryptography.fernet import Fernet, InvalidToken


def _fernet() -> Fernet:
    key = getattr(settings, "ID_ENCRYPTION_KEY", "") or ""
    if key:
        return Fernet(key.encode() if isinstance(key, str) else key)
    # Fallback: derive a stable 32-byte urlsafe key from SECRET_KEY (dev
    # convenience) — distinct from other derived keys via the suffix.
    digest = hashlib.sha256(f"{settings.SECRET_KEY}::id-encryption".encode()).digest()
    return Fernet(base64.urlsafe_b64encode(digest))


def encrypt_id(value) -> str:
    """Encrypt an integer ID into an opaque, URL-safe token.

    Trailing '=' padding is stripped since some email clients mangle it in
    query strings; decrypt_id() restores it before decoding.
    """
    if value is None:
        return ""
    token = _fernet().encrypt(str(value).encode()).decode()
    return token.rstrip("=")


def decrypt_id(token: str):
    """Decrypt a token produced by encrypt_id() back to an int.

    Returns None (never raises) if the token is missing, tampered with, or
    otherwise invalid — callers should treat that the same as "not found".
    """
    if not token:
        return None
    padded = token + "=" * (-len(token) % 4)
    try:
        raw = _fernet().decrypt(padded.encode()).decode()
        return int(raw)
    except (InvalidToken, ValueError):
        return None


# ---------------------------------------------------------------------------
# Short, reversible, obfuscated code for SHORT public URLs (e.g. WhatsApp job
# links). Not cryptographically strong like encrypt_id — it just hides the
# sequential id and stays ~5-7 chars so the URL is short and shareable.
# ---------------------------------------------------------------------------
_SC_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
_SC_MASK = 0x5F3A7C31
_SC_OFFSET = 1_000_000


def short_encode_id(value) -> str:
    try:
        n = int(value)
    except (TypeError, ValueError):
        return ""
    n = (n ^ _SC_MASK) + _SC_OFFSET
    if n <= 0:
        return "0"
    out = ""
    while n > 0:
        n, r = divmod(n, 62)
        out = _SC_ALPHABET[r] + out
    return out


def short_decode_id(code: str):
    if not code:
        return None
    try:
        n = 0
        for ch in code:
            n = n * 62 + _SC_ALPHABET.index(ch)
        val = (n - _SC_OFFSET) ^ _SC_MASK
        return val if val >= 0 else None
    except ValueError:
        return None
