<?php
/**
 * Symmetric encryption for stored API credentials.
 *
 * Cipher: AES-256-CBC. Key: SHA-256 of `wp_salt('auth')` so it's exactly 32 bytes.
 * IV: 16 random bytes per encryption, prepended to the ciphertext. The whole
 * thing is base64-encoded before storage so it survives any character-set
 * surprises in the options table.
 *
 * If openssl is missing we degrade to plaintext-but-base64 so the plugin
 * still functions on broken hosts rather than fatal-erroring at the buyer.
 *
 * @package FindAstra
 */

defined( 'ABSPATH' ) || exit;

final class FindAstra_Crypto {

	private const CIPHER = 'aes-256-cbc';

	public static function available(): bool {
		return function_exists( 'openssl_encrypt' ) && in_array( self::CIPHER, openssl_get_cipher_methods(), true );
	}

	private static function key(): string {
		return hash( 'sha256', (string) wp_salt( 'auth' ), true );
	}

	public static function encrypt( string $plain ): string {
		if ( '' === $plain ) {
			return '';
		}
		if ( ! self::available() ) {
			return 'plain:' . base64_encode( $plain );
		}
		$iv = random_bytes( 16 );
		$ct = openssl_encrypt( $plain, self::CIPHER, self::key(), OPENSSL_RAW_DATA, $iv );
		if ( false === $ct ) {
			return 'plain:' . base64_encode( $plain );
		}
		return 'v1:' . base64_encode( $iv . $ct );
	}

	public static function decrypt( string $stored ): string {
		if ( '' === $stored ) {
			return '';
		}
		if ( str_starts_with( $stored, 'plain:' ) ) {
			return (string) base64_decode( substr( $stored, 6 ), true );
		}
		if ( ! str_starts_with( $stored, 'v1:' ) ) {
			return $stored;
		}
		if ( ! self::available() ) {
			return '';
		}
		$blob = base64_decode( substr( $stored, 3 ), true );
		if ( false === $blob || strlen( $blob ) < 17 ) {
			return '';
		}
		$iv = substr( $blob, 0, 16 );
		$ct = substr( $blob, 16 );
		$pt = openssl_decrypt( $ct, self::CIPHER, self::key(), OPENSSL_RAW_DATA, $iv );
		return false === $pt ? '' : $pt;
	}

	public static function mask( string $secret, int $keep = 4 ): string {
		if ( '' === $secret ) {
			return '';
		}
		$len = strlen( $secret );
		if ( $len <= $keep ) {
			return str_repeat( '•', $len );
		}
		return str_repeat( '•', max( 4, $len - $keep ) ) . substr( $secret, -$keep );
	}
}
