<?php

namespace MintyPHP\Tests\Service\Settings;

use MintyPHP\Repository\Settings\SettingRepositoryInterface;
use MintyPHP\Service\Settings\SettingsApiPolicyGateway;
use MintyPHP\Service\Settings\SettingsMetadataGateway;
use PHPUnit\Framework\TestCase;

class SettingsApiPolicyGatewayTest extends TestCase
{
    public function testSetApiTokenDefaultTtlDaysRejectsAboveCurrentMax(): void
    {
        $settings = $this->createMock(SettingRepositoryInterface::class);
        $settings->method('getValue')->willReturnCallback(static function (string $key): ?string {
            if ($key === 'api_token_max_ttl_days') {
                return '30';
            }
            return null;
        });
        $settings->expects($this->never())->method('set');

        $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings));
        $this->assertFalse($gateway->setApiTokenDefaultTtlDays(31));
    }

    public function testSetApiTokenMaxTtlDaysUpdatesDefaultWhenNeeded(): void
    {
        $settings = $this->createMock(SettingRepositoryInterface::class);
        $settings->method('getValue')->willReturnCallback(static function (string $key): ?string {
            if ($key === 'api_token_default_ttl_days') {
                return '365';
            }
            return null;
        });

        $calls = [];
        $settings->expects($this->exactly(2))
            ->method('set')
            ->willReturnCallback(static function (string $key, ?string $value, ?string $description) use (&$calls): bool {
                $calls[] = [$key, $value, $description];
                return true;
            });

        $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings));
        $this->assertTrue($gateway->setApiTokenMaxTtlDays(120));
        $this->assertSame(
            [
                ['api_token_default_ttl_days', '120', 'setting.api_token_default_ttl_days'],
                ['api_token_max_ttl_days', '120', 'setting.api_token_max_ttl_days'],
            ],
            $calls
        );
    }

    public function testSetApiCorsAllowedOriginsRejectsInvalidOrigins(): void
    {
        $settings = $this->createMock(SettingRepositoryInterface::class);
        $settings->expects($this->never())->method('set');

        $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings));
        $this->assertFalse($gateway->setApiCorsAllowedOrigins("https://ok.example\njavascript:alert(1)"));
    }

    public function testCorsOriginsRoundtripNormalizesAndDeduplicates(): void
    {
        $settings = $this->createMock(SettingRepositoryInterface::class);
        $stored = null;
        $settings->expects($this->once())
            ->method('set')
            ->willReturnCallback(static function (string $key, ?string $value) use (&$stored): bool {
                if ($key === 'api_cors_allowed_origins') {
                    $stored = $value;
                }
                return true;
            });
        $settings->method('getValue')->willReturnCallback(static function (string $key) use (&$stored): ?string {
            if ($key === 'api_cors_allowed_origins') {
                return $stored;
            }
            return null;
        });

        $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings));
        $this->assertTrue($gateway->setApiCorsAllowedOrigins("https://a.example,https://a.example/\nhttps://b.example:443"));
        $this->assertSame(['https://a.example', 'https://b.example'], $gateway->getApiCorsAllowedOrigins());
        $this->assertSame("https://a.example\nhttps://b.example", $gateway->getApiCorsAllowedOriginsText());
    }
}
