<?php

declare(strict_types=1);

namespace ComerciaGlobalPayments\Tests\AddonPayments\SDK\Encryption;

use ComerciaGlobalPayments\AddonPayments\SDK\Encryption\Cypher\Aes256Cbc;
use ComerciaGlobalPayments\AddonPayments\SDK\Encryption\Cypher\Aes256Ecb;
use PHPUnit\Framework\TestCase;
use RuntimeException;

/**
 * Test case for AES-256-CBC and AES-256-ECB encryption methods.
 */
class Aes256Test extends TestCase
{
    /**
     * @covers \ComerciaGlobalPayments\AddonPayments\SDK\Encryption\Cypher\Aes256Cbc
     * @covers \ComerciaGlobalPayments\AddonPayments\SDK\Encryption\Cypher\Aes256Ecb
     * @dataProvider encryptionSampleData
     * @SuppressWarnings(PHPMD.ElseExpression)
     */
    public function testAll(string $text, string $key, $instance): void
    {
        if ($instance instanceof Aes256Cbc) {
            $iniVector = (0 === (random_int(1, 10) % 2)) ? $instance->generateIv() : $instance->generateInsecureIv($instance::IV_LENGTH);
            $encryptedText = $instance->encrypt($text, $key, $iniVector);
            $decryptedText = $instance->decrypt($encryptedText, $key, $iniVector);
        } else {
            $encryptedText = $instance->encrypt($text, $key);
            $decryptedText = $instance->decrypt($encryptedText, $key);
        }
        self::assertEquals($instance::NAME, $instance->getName(), 'Test encryption name');
        self::assertEquals(substr($instance::NAME, 8), $instance->getCanonicalName(), 'Test encryption canonical name');
        self::assertNotEmpty($encryptedText, 'Test encryption returns a value');
        self::assertIsString($encryptedText, 'Tests returned value is a string');
        self::assertEquals($text, $decryptedText, 'Test decrypted text matches original text');
    }

    public function encryptionSampleData(): array
    {
        $dataFile = \dirname(__DIR__, 2).'/fixtures/data/sample.txt';
        if (!is_readable($dataFile)) {
            throw new RuntimeException("The fixtures file '${dataFile}' is missing or cannot be read.");
        }

        $content = file_get_contents($dataFile);
        $lines = array_filter(explode(\PHP_EOL, $content));
        $data = [];
        foreach ($lines as $line) {
            $instance = (0 === (random_int(1, 10) % 2)) ? new Aes256Cbc() : new Aes256Ecb();
            $data[] = [$line, current(explode(' ', trim($line))), $instance];
        }

        return $data;
    }
}
