<?php
if (count(get_included_files()) === 1) {
    http_response_code(403);
    exit('Forbidden');
}

/**
 * TokenCrypto — cifra/descifra tokens con AES-256-GCM.
 * Requiere TOKEN_ENCRYPTION_KEY en .env: base64 de 32 bytes.
 * Generar: php -r "echo base64_encode(random_bytes(32));"
 */
class TokenCrypto {
    private const CIPHER = 'aes-256-gcm';
    private const IV_LEN = 12;   // 96-bit nonce (recomendado para GCM)
    private const TAG_LEN = 16;  // 128-bit auth tag

    public static function encrypt(string $plaintext): string {
        $key = self::key();
        $iv  = random_bytes(self::IV_LEN);
        $tag = '';
        $ct  = openssl_encrypt($plaintext, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv, $tag, '', self::TAG_LEN);
        if ($ct === false) {
            throw new RuntimeException('TokenCrypto: encryption failed');
        }
        // Formato: iv(12) || tag(16) || ciphertext
        return base64_encode($iv . $tag . $ct);
    }

    public static function decrypt(string $encrypted): string {
        $key = self::key();
        $raw = base64_decode($encrypted, true);
        if ($raw === false || strlen($raw) <= self::IV_LEN + self::TAG_LEN) {
            throw new RuntimeException('TokenCrypto: invalid ciphertext');
        }
        $iv  = substr($raw, 0, self::IV_LEN);
        $tag = substr($raw, self::IV_LEN, self::TAG_LEN);
        $ct  = substr($raw, self::IV_LEN + self::TAG_LEN);
        $pt  = openssl_decrypt($ct, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv, $tag);
        if ($pt === false) {
            throw new RuntimeException('TokenCrypto: decryption failed (token corrupted or wrong key)');
        }
        return $pt;
    }

    private static function key(): string {
        $b64 = getenv('TOKEN_ENCRYPTION_KEY');
        if (!$b64) {
            throw new RuntimeException('TOKEN_ENCRYPTION_KEY not set in .env');
        }
        $key = base64_decode($b64, true);
        if ($key === false || strlen($key) !== 32) {
            throw new RuntimeException('TOKEN_ENCRYPTION_KEY must be 32 raw bytes, base64-encoded');
        }
        return $key;
    }
}
