<?php

declare( strict_types=1 );

namespace Simplyin\Simplyin_W_Plugin\Tests\Unit;

use PHPUnit\Framework\TestCase;
use Simplyin\Simplyin_W_Plugin\Helper\Secret_Cipher;

/**
 * At-rest secret encryption: round-trip, idempotency, legacy-plaintext
 * backward-compat, and tamper resistance. A key is available because the WordPress
 * secret constants are defined below (mirroring wp-config.php).
 */
final class Secret_Cipher_Test extends TestCase {

	public static function setUpBeforeClass(): void {
		parent::setUpBeforeClass();
		if ( ! defined( 'AUTH_KEY' ) ) {
			define( 'AUTH_KEY', 'unit-test-auth-key-0123456789abcdef0123456789abcdef' );
		}
		if ( ! defined( 'SECURE_AUTH_KEY' ) ) {
			define( 'SECURE_AUTH_KEY', 'unit-test-secure-auth-key-fedcba9876543210fedcba98' );
		}
	}

	public function test_round_trip_seals_and_recovers_the_secret(): void {
		if ( ! function_exists( 'sodium_crypto_secretbox' ) ) {
			$this->markTestSkipped( 'libsodium is required to exercise Secret_Cipher.' );
		}

		$plain  = "-----BEGIN PRIVATE KEY-----\nMIIabc+/=payload\n-----END PRIVATE KEY-----\n";
		$sealed = Secret_Cipher::encrypt( $plain );

		$this->assertTrue( Secret_Cipher::is_encrypted( $sealed ) );
		$this->assertNotSame( $plain, $sealed );
		$this->assertStringNotContainsString( 'BEGIN PRIVATE KEY', $sealed );
		$this->assertSame( $plain, Secret_Cipher::decrypt( $sealed ) );
	}

	public function test_encrypt_is_idempotent(): void {
		$sealed = Secret_Cipher::encrypt( 'secret-value' );

		$this->assertSame( $sealed, Secret_Cipher::encrypt( $sealed ) );
	}

	public function test_empty_stays_empty(): void {
		$this->assertSame( '', Secret_Cipher::encrypt( '' ) );
	}

	public function test_legacy_plaintext_passes_through_decrypt(): void {
		// Existing installs store the secret in plaintext (no prefix) until the migration runs;
		// decrypt() must return it unchanged so nothing breaks before/after the upgrade.
		$this->assertFalse( Secret_Cipher::is_encrypted( 'legacy-plaintext-secret' ) );
		$this->assertSame( 'legacy-plaintext-secret', Secret_Cipher::decrypt( 'legacy-plaintext-secret' ) );
	}

	public function test_tampered_ciphertext_returns_empty(): void {
		if ( ! function_exists( 'sodium_crypto_secretbox' ) ) {
			$this->markTestSkipped( 'libsodium is required to exercise Secret_Cipher.' );
		}

		$sealed   = Secret_Cipher::encrypt( 'authentic' );
		$last     = substr( $sealed, -1 );
		$tampered = substr( $sealed, 0, -1 ) . ( 'A' === $last ? 'B' : 'A' );

		$this->assertSame( '', Secret_Cipher::decrypt( $tampered ) );
	}
}
