<?php
namespace Bot\Services;

use Bot\Config;

/**
 * Provides symmetric encryption helpers for sensitive values such as private
 * keys. Uses AES-256-CBC with per-record IVs and a base64 configuration key.
 */
class EncryptionService
{
    private string $binaryKey;

    public function __construct(?string $base64Key = null)
    {
        $keyMaterial = $base64Key ?? Config::get()->getValue('wallet_encryption_key', '');
        $decoded = base64_decode($keyMaterial, true);
        if ($decoded === false || strlen($decoded) !== 32) {
            throw new \RuntimeException('Invalid WALLET_ENC_KEY_BASE64: expected 32-byte base64 string.');
        }
        $this->binaryKey = $decoded;
    }

    /**
     * Encrypt plaintext and return a base64 payload containing IV + ciphertext.
     */
    public function encrypt(string $plaintext): string
    {
        $iv = random_bytes(16);
        $ciphertext = openssl_encrypt($plaintext, 'AES-256-CBC', $this->binaryKey, OPENSSL_RAW_DATA, $iv);
        if ($ciphertext === false) {
            throw new \RuntimeException('Failed to encrypt value.');
        }
        return base64_encode($iv . $ciphertext);
    }

    /**
     * Decrypt a previously encrypted payload (base64 IV + ciphertext).
     */
    public function decrypt(?string $payload): ?string
    {
        if ($payload === null || $payload === '') {
            return null;
        }
        $binary = base64_decode($payload, true);
        if ($binary === false || strlen($binary) < 17) {
            throw new \RuntimeException('Encrypted payload is malformed.');
        }
        $iv = substr($binary, 0, 16);
        $ciphertext = substr($binary, 16);
        $plaintext = openssl_decrypt($ciphertext, 'AES-256-CBC', $this->binaryKey, OPENSSL_RAW_DATA, $iv);
        if ($plaintext === false) {
            throw new \RuntimeException('Failed to decrypt value.');
        }
        return $plaintext;
    }
}
