<?php
namespace Gestoreasy\Core\Security;

class Crypto
{
    private const KEY_ENV = 'CERT_STORE_KEY';

    private static function getMasterKey(): string
    {
        $key = getenv(self::KEY_ENV);
        if (!$key) {
            // Fallback to config array if available
            if (class_exists('Gestoreasy\\Core\\Support\\Config')) {
                $cfg = \Gestoreasy\Core\Support\Config::get(self::KEY_ENV);
                if ($cfg) $key = $cfg;
            }
        }
        if (!$key) {
            throw new \RuntimeException('CERT_STORE_KEY não configurado. Defina no ambiente (.env).');
        }
        // Normalize to binary key material
        $bin = (ctype_xdigit($key) && strlen($key) % 2 === 0) ? hex2bin($key) : $key;
        if (strlen($bin) < 16) {
            throw new \RuntimeException('CERT_STORE_KEY muito curto. Use 32 bytes aleatórios (hex ou binário).');
        }
        return $bin;
    }

    private static function hkdf(string $ikm, string $salt, int $len = 32, string $info = 'cert-store'): string
    {
        // HKDF-SHA256
        $prk = hash_hmac('sha256', $ikm, $salt, true);
        $t = '';
        $okm = '';
        $i = 0;
        while (strlen($okm) < $len) {
            $i++;
            $t = hash_hmac('sha256', $t . $info . chr($i), $prk, true);
            $okm .= $t;
        }
        return substr($okm, 0, $len);
    }

    public static function encryptJson(array $payload): array
    {
        $plaintext = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        if ($plaintext === false) {
            throw new \RuntimeException('Falha ao serializar JSON para criptografia.');
        }
        $salt = random_bytes(16);
        $key = self::hkdf(self::getMasterKey(), $salt, 32);
        $iv = random_bytes(12); // GCM nonce
        $tag = '';
        $cipher = openssl_encrypt($plaintext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
        if ($cipher === false) {
            throw new \RuntimeException('Falha na criptografia AES-GCM.');
        }
        return [
            'cipher' => $cipher,
            'iv' => $iv,
            'tag' => $tag,
            'salt' => $salt,
        ];
    }

    public static function decryptJson(string $cipher, string $iv, string $tag, string $salt): array
    {
        $key = self::hkdf(self::getMasterKey(), $salt, 32);
        $plaintext = openssl_decrypt($cipher, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
        if ($plaintext === false) {
            throw new \RuntimeException('Falha na descriptografia ou tag inválida.');
        }
        $data = json_decode($plaintext, true);
        if (!is_array($data)) {
            throw new \RuntimeException('JSON inválido após descriptografia.');
        }
        return $data;
    }
}