<?php
/**
 * Encryption Manager — AES-256-CBC encrypt/decrypt for sensitive data (Access Tokens).
 *
 * @package CapiFlow
 */

namespace CapiFlow\Core;

defined( 'ABSPATH' ) || exit;

class Encryption {

    /**
     * Cipher method.
     *
     * @var string
     */
    const CIPHER = 'aes-256-cbc';

    /**
     * Get or generate the encryption key.
     *
     * Uses AUTH_KEY from wp-config.php as the base key.
     * Falls back to a stored random key if AUTH_KEY is default/missing.
     *
     * @return string 32-byte key.
     */
    private static function get_key() {
        $base = defined( 'AUTH_KEY' ) && AUTH_KEY !== 'put your unique phrase here'
            ? AUTH_KEY
            : '';

        if ( empty( $base ) ) {
            $stored = get_option( 'capiflow_encryption_key', '' );
            if ( empty( $stored ) ) {
                $stored = bin2hex( random_bytes( 32 ) );
                update_option( 'capiflow_encryption_key', $stored, false );
            }
            $base = $stored;
        }

        return substr( hash( 'sha256', $base ), 0, 32 );
    }

    /**
     * Encrypt a plaintext value.
     *
     * @param string $plaintext Value to encrypt.
     * @return string Base64-encoded cipher text with IV prepended.
     */
    public static function encrypt( $plaintext ) {
        if ( empty( $plaintext ) ) {
            return '';
        }

        $key     = self::get_key();
        $iv_len  = openssl_cipher_iv_length( self::CIPHER );
        $iv      = openssl_random_pseudo_bytes( $iv_len );
        $raw     = openssl_encrypt( $plaintext, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv );

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

        // Prepend IV to cipher text for storage.
        return base64_encode( $iv . $raw ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
    }

    /**
     * Decrypt a cipher text value.
     *
     * @param string $encrypted Base64-encoded cipher text with IV prepended.
     * @return string Decrypted plaintext, or empty string on failure.
     */
    public static function decrypt( $encrypted ) {
        if ( empty( $encrypted ) ) {
            return '';
        }

        $key    = self::get_key();
        $data   = base64_decode( $encrypted, true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode

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

        $iv_len = openssl_cipher_iv_length( self::CIPHER );

        if ( strlen( $data ) <= $iv_len ) {
            return '';
        }

        $iv   = substr( $data, 0, $iv_len );
        $raw  = substr( $data, $iv_len );
        $dec  = openssl_decrypt( $raw, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv );

        return ( false === $dec ) ? '' : $dec;
    }
}
