"""Symmetric encryption helpers for the cTrader token vault.

The forwarder and any external consumer share the same secret string
(CTRADER_TOKEN_SECRET). Tokens are encrypted with Fernet (AES-128-CBC + HMAC)
and stored in the database.

Requirements: cryptography (already in requirements.txt)
"""

from __future__ import annotations

import base64
import hashlib
import json
from typing import Any

from cryptography.fernet import Fernet, InvalidToken


def _derive_fernet(secret: str) -> Fernet:
    """Derive a valid Fernet key from any non-empty secret string."""
    if not secret:
        raise RuntimeError("CTRADER_TOKEN_SECRET is not configured")
    key = base64.urlsafe_b64encode(hashlib.sha256(secret.encode("utf-8")).digest())
    return Fernet(key)


def encrypt_payload(secret: str, payload: dict[str, Any]) -> str:
    """Encrypt a JSON payload with Fernet and return a url-safe token string.

    Raises RuntimeError if ``secret`` is missing or invalid.
    """
    f = _derive_fernet(secret)
    data = json.dumps(payload, default=str).encode("utf-8")
    return f.encrypt(data).decode("utf-8")


def decrypt_payload(secret: str, encrypted: str) -> dict[str, Any]:
    """Decrypt a Fernet token back to a dict.

    Raises RuntimeError if ``secret`` is missing or invalid.
    """
    f = _derive_fernet(secret)
    try:
        data = f.decrypt(encrypted.encode("utf-8"))
    except InvalidToken as exc:
        raise RuntimeError("Invalid token or wrong CTRADER_TOKEN_SECRET") from exc
    return json.loads(data.decode("utf-8"))
