<?php
/**
 * Advanced Encryption (AES-256-GCM) - System Level
 */

declare(strict_types=1);

namespace App\Core;

final class Encryption
{
    private const CIPHER = 'aes-256-gcm';

    /**
     * Encrypts data using the system's ENCRYPTION_KEY from .env
     */
    public static function encrypt(string $data): string
    {
        $key = env('ENCRYPTION_KEY');
        if (!$key) {
            throw new \RuntimeException('ENCRYPTION_KEY is missing from .env');
        }

        $encryptionKey = hash('sha256', $key, true);
        $iv = random_bytes(openssl_cipher_iv_length(self::CIPHER));
        
        $tag = '';
        $ciphertext = openssl_encrypt($data, self::CIPHER, $encryptionKey, OPENSSL_RAW_DATA, $iv, $tag);

        if ($ciphertext === false) {
            throw new \RuntimeException('Encryption failed');
        }

        return base64_encode($iv . $tag . $ciphertext);
    }

    /**
     * Decrypts AES-256-GCM encrypted data using the system's ENCRYPTION_KEY
     */
    public static function decrypt(string $encryptedData): string|false
    {
        $key = env('ENCRYPTION_KEY');
        if (!$key) {
            throw new \RuntimeException('ENCRYPTION_KEY is missing from .env');
        }

        // Handle common prefixing issues or trailing whitespace
        $encryptedData = trim($encryptedData);
        if (str_starts_with($encryptedData, '==')) {
            $encryptedData = substr($encryptedData, 2);
        }

        $encryptionKey = hash('sha256', $key, true);
        $decoded = base64_decode($encryptedData, true);
        
        if ($decoded === false) {
            error_log("ENCRYPTION ERROR: Invalid base64 data provided for decryption.");
            return false;
        }

        $ivLength = openssl_cipher_iv_length(self::CIPHER);
        $tagLength = 16;

        if (strlen($decoded) < $ivLength + $tagLength) {
            // This is likely legacy unencrypted data, return false silently
            return false;
        }

        $iv = substr($decoded, 0, $ivLength);
        $tag = substr($decoded, $ivLength, $tagLength);
        $ciphertext = substr($decoded, $ivLength + $tagLength);

        $result = openssl_decrypt($ciphertext, self::CIPHER, $encryptionKey, OPENSSL_RAW_DATA, $iv, $tag);
        
        if ($result === false) {
            error_log("ENCRYPTION ERROR: openssl_decrypt failed. Key might be wrong or data corrupted.");
        }

        return $result;
    }
}
