import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend

class Encriptar_fernet:
    @staticmethod
    def _derivar_clave(password: str, salt: bytes) -> bytes:
        """
        Deriva una clave segura a partir de la contraseña y el salt usando PBKDF2HMAC.
        """
        kdf = PBKDF2HMAC(
            algorithm=hashes.SHA256(),
            length=32,
            salt=salt,
            iterations=100_000,
            backend=default_backend()
        )
        return base64.urlsafe_b64encode(kdf.derive(password.encode()))

    @classmethod
    def encriptar(cls, texto: str, password: str) -> bytes:
        """
        Encripta un texto con una clave derivada de la contraseña + salt aleatorio.
        El salt es embebido al inicio del token cifrado.
        """
        salt = os.urandom(16)  # 128 bits de salt aleatorio
        key = cls._derivar_clave(password, salt)
        fernet = Fernet(key)
        token = fernet.encrypt(texto.encode('utf-8'))
        return salt + token  # Embebemos el salt al principio

    @classmethod
    def desencriptar(cls, token_con_salt: bytes, password: str) -> str:
        """
        Extrae el salt del token, deriva la clave, y desencripta el texto.
        """
        salt = token_con_salt[:16]
        token = token_con_salt[16:]
        key = cls._derivar_clave(password, salt)
        fernet = Fernet(key)
        return fernet.decrypt(token).decode('utf-8')
