<?php

namespace EasyLinkAutomations\Auth;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * AES-256-CBC encryption service for credential storage.
 *
 * Uses the WordPress AUTH_KEY constant as the encryption key, which is
 * unique per WordPress installation and defined in wp-config.php.
 */
final class EncryptionService
{
    private const CIPHER = 'aes-256-cbc';

    /**
     * Encrypt an associative array of credential data.
     *
     * @param array $data The credential data to encrypt
     *
     * @return string Base64-encoded ciphertext with prepended IV
     */
    public static function encrypt(array $data): string
    {
        $json = wp_json_encode($data);
        $key  = self::deriveKey();

        $ivLength = openssl_cipher_iv_length(self::CIPHER);
        $iv       = openssl_random_pseudo_bytes($ivLength);

        $encrypted = openssl_encrypt($json, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv);

        if ($encrypted === false) {
            return '';
        }

        // Prepend IV to ciphertext so we can extract it during decryption
        return base64_encode($iv . $encrypted);
    }

    /**
     * Decrypt a base64-encoded ciphertext back to an array.
     *
     * @param string $encrypted The encrypted string from encrypt()
     *
     * @return array The decrypted credential data, or empty array on failure
     */
    public static function decrypt(string $encrypted): array
    {
        if (empty($encrypted)) {
            return [];
        }

        $raw = base64_decode($encrypted, true);
        if ($raw === false) {
            // Fallback: might be plain JSON from before encryption was added
            $legacy = json_decode($encrypted, true);

            return is_array($legacy) ? $legacy : [];
        }

        $key      = self::deriveKey();
        $ivLength = openssl_cipher_iv_length(self::CIPHER);

        if (strlen($raw) <= $ivLength) {
            return [];
        }

        $iv         = substr($raw, 0, $ivLength);
        $ciphertext = substr($raw, $ivLength);

        $decrypted = openssl_decrypt($ciphertext, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv);

        if ($decrypted === false) {
            // Fallback: might be plain JSON from before encryption was added
            $legacy = json_decode($encrypted, true);

            return is_array($legacy) ? $legacy : [];
        }

        $data = json_decode($decrypted, true);

        return is_array($data) ? $data : [];
    }

    /**
     * Derive a 32-byte encryption key from the WordPress AUTH_KEY.
     *
     * Uses SHA-256 hash to ensure consistent 32-byte key length regardless
     * of the AUTH_KEY length.
     */
    private static function deriveKey(): string
    {
        $source = defined('AUTH_KEY') ? AUTH_KEY : 'easylink-automations-fallback-key';

        return hash('sha256', $source, true);
    }
}
