<?php

namespace MintyPHP\Tests\App\Bootstrap;

use MintyPHP\App\Bootstrap\EnvValidator;
use PHPUnit\Framework\TestCase;

final class EnvValidatorTest extends TestCase
{
    public function testValidateArrayAcceptsValidDevConfiguration(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'dev',
            'APP_DEBUG' => 'true',
            'APP_CRYPTO_KEY' => '',
            'APP_URL' => 'http://localhost:8080',
        ]));

        $this->assertSame([], $errors);
    }

    public function testValidateArrayRequiresAppUrlInDevelopment(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'dev',
            'APP_URL' => '',
        ]));

        $this->assertContains('APP_URL must be set in development', $errors);
    }

    public function testValidateArrayRequiresProductionCryptoKeyAndUrl(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'prod',
            'APP_DEBUG' => 'false',
            'APP_CRYPTO_KEY' => '',
            'APP_URL' => '',
        ]));

        $this->assertContains('APP_URL must be set in production', $errors);
        $this->assertContains('APP_CRYPTO_KEY must be set in production', $errors);
    }

    public function testValidateArrayAcceptsMissingAppUrlInTestEnv(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'test',
            'APP_URL' => '',
        ]));

        $this->assertSame([], $errors);
    }

    public function testValidateArrayRejectsInvalidCryptoKeyFormat(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_CRYPTO_KEY' => 'invalid-key-format',
        ]));

        $this->assertContains('APP_CRYPTO_KEY must be 64-char hex or base64 encoded 32-byte key', $errors);
    }

    public function testValidateArrayAcceptsValidHexCryptoKeyInProduction(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'prod',
            'APP_DEBUG' => 'false',
            'APP_URL' => 'https://example.test',
            'APP_CRYPTO_KEY' => str_repeat('a', 64),
            'TENANT_SCOPE_STRICT' => 'true',
        ]));

        $this->assertSame([], $errors);
    }

    public function testValidateArrayRequiresHttpsAppUrlInProduction(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'prod',
            'APP_DEBUG' => 'false',
            'APP_URL' => 'http://example.test',
            'APP_CRYPTO_KEY' => str_repeat('a', 64),
            'TENANT_SCOPE_STRICT' => 'true',
        ]));

        $this->assertContains('APP_URL must use https in production', $errors);
    }

    public function testValidateArrayRejectsLocalhostAppUrlInProduction(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'prod',
            'APP_DEBUG' => 'false',
            'APP_URL' => 'https://localhost',
            'APP_CRYPTO_KEY' => str_repeat('a', 64),
            'TENANT_SCOPE_STRICT' => 'true',
        ]));

        $this->assertContains('APP_URL must not use localhost or an IP host in production', $errors);
    }

    public function testValidateArrayRejectsIpHostAppUrlInProduction(): void
    {
        $errors = EnvValidator::validateArray($this->baseEnv([
            'APP_ENV' => 'prod',
            'APP_DEBUG' => 'false',
            'APP_URL' => 'https://127.0.0.1',
            'APP_CRYPTO_KEY' => str_repeat('a', 64),
            'TENANT_SCOPE_STRICT' => 'true',
        ]));

        $this->assertContains('APP_URL must not use localhost or an IP host in production', $errors);
    }

    /**
     * @param array<string, string> $override
     * @return array<string, string>
     */
    private function baseEnv(array $override = []): array
    {
        $storagePath = sys_get_temp_dir();

        return array_merge([
            'APP_NAME' => 'CoreCore',
            'APP_ENV' => 'dev',
            'APP_DEBUG' => 'true',
            'APP_TIMEZONE' => 'Europe/Berlin',
            'APP_STORAGE_PATH' => $storagePath,
            'APP_LOCALE' => 'de',
            'APP_LOCALES' => 'de,en',
            'APP_I18N_DOMAIN' => 'default',
            'APP_URL' => 'http://localhost:8080',
            'APP_CRYPTO_KEY' => '',
            'SESSION_NAME' => 'CoreCore',
            'TENANT_SCOPE_STRICT' => 'true',
            'DB_HOST' => 'db',
            'DB_PORT' => '3306',
            'DB_NAME' => 'db',
            'DB_USER' => 'user',
            'DB_PASS' => 'user',
            'CACHE_SERVERS' => 'memcached:11211',
            'FIREWALL_CONCURRENCY' => '10',
            'FIREWALL_SPINLOCK_SECONDS' => '0.15',
            'FIREWALL_INTERVAL_SECONDS' => '300',
            'FIREWALL_CACHE_PREFIX' => 'fw_concurrency_',
            'FIREWALL_REVERSE_PROXY' => 'false',
        ], $override);
    }
}
