"""
AES-256-CBC encrypt/decrypt for secrets stored in the `app_secret` table.

Interoperable with the PHP side (utils/secret-crypto.php):
  - key    = SHA-256(passphrase)                      -> 32 bytes (AES-256)
  - iv      = random 16 bytes, per value
  - padding = PKCS7
  - stored  = base64(iv) + ":" + base64(ciphertext)

The passphrase is the deployment secret `SECRETS_ENC_KEY` — the SAME value must
be set in the Python .env and in the PHP config/secrets.config.php.
"""

import os
import base64
import hashlib

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding


def _key_bytes(passphrase: str) -> bytes:
    return hashlib.sha256(passphrase.encode("utf-8")).digest()  # 32 bytes


def encrypt(plaintext: str, passphrase: str) -> str:
    key = _key_bytes(passphrase)
    iv = os.urandom(16)
    padder = padding.PKCS7(128).padder()
    data = padder.update(plaintext.encode("utf-8")) + padder.finalize()
    encryptor = Cipher(algorithms.AES(key), modes.CBC(iv)).encryptor()
    ct = encryptor.update(data) + encryptor.finalize()
    return base64.b64encode(iv).decode() + ":" + base64.b64encode(ct).decode()


def decrypt(stored: str, passphrase: str):
    if not stored or ":" not in stored:
        return None
    iv_b64, ct_b64 = stored.split(":", 1)
    key = _key_bytes(passphrase)
    iv = base64.b64decode(iv_b64)
    ct = base64.b64decode(ct_b64)
    decryptor = Cipher(algorithms.AES(key), modes.CBC(iv)).decryptor()
    padded = decryptor.update(ct) + decryptor.finalize()
    unpadder = padding.PKCS7(128).unpadder()
    return (unpadder.update(padded) + unpadder.finalize()).decode("utf-8")
