<?php

namespace MintyPHP\Tests\Service\Auth;

use MintyPHP\Service\Auth\AuthSettingsGateway;
use MintyPHP\Service\Settings\SettingsApiPolicyGateway;
use MintyPHP\Service\Settings\SettingsAppGateway;
use MintyPHP\Service\Settings\SettingsDefaultsGateway;
use MintyPHP\Service\Settings\SettingsLoginPersistenceGateway;
use MintyPHP\Service\Settings\SettingsMicrosoftGateway;
use PHPUnit\Framework\TestCase;

final class AuthSettingsGatewayTest extends TestCase
{
    public function testMicrosoftAccessorsDelegateAndCastToString(): void
    {
        $microsoft = $this->createMock(SettingsMicrosoftGateway::class);
        $microsoft->method('getMicrosoftSharedClientId')->willReturn('client-id');
        $microsoft->method('getMicrosoftSharedClientSecret')->willReturn('secret');
        $microsoft->method('getMicrosoftAuthority')->willReturn('https://login.microsoftonline.com/tenant');

        $gateway = $this->makeGateway(microsoft: $microsoft);

        $this->assertSame('client-id', $gateway->getMicrosoftSharedClientId());
        $this->assertSame('secret', $gateway->getMicrosoftSharedClientSecret());
        $this->assertSame('https://login.microsoftonline.com/tenant', $gateway->getMicrosoftAuthority());
    }

    public function testMicrosoftAccessorsReturnEmptyStringWhenUnconfigured(): void
    {
        $microsoft = $this->createMock(SettingsMicrosoftGateway::class);
        $microsoft->method('getMicrosoftSharedClientId')->willReturn('');
        $microsoft->method('getMicrosoftSharedClientSecret')->willReturn('');
        $microsoft->method('getMicrosoftAuthority')->willReturn('');

        $gateway = $this->makeGateway(microsoft: $microsoft);

        $this->assertSame('', $gateway->getMicrosoftSharedClientId());
        $this->assertSame('', $gateway->getMicrosoftSharedClientSecret());
        $this->assertSame('', $gateway->getMicrosoftAuthority());
    }

    public function testApiTokenTtlAccessorsDelegate(): void
    {
        $apiPolicy = $this->createMock(SettingsApiPolicyGateway::class);
        $apiPolicy->method('getApiTokenMaxTtlDays')->willReturn(90);
        $apiPolicy->method('getApiTokenDefaultTtlDays')->willReturn(30);

        $gateway = $this->makeGateway(apiPolicy: $apiPolicy);

        $this->assertSame(90, $gateway->getApiTokenMaxTtlDays());
        $this->assertSame(30, $gateway->getApiTokenDefaultTtlDays());
    }

    public function testThemeHelpersDelegate(): void
    {
        $app = $this->createMock(SettingsAppGateway::class);
        $app->method('resolveDefaultTheme')->willReturn('light');
        $app->expects($this->once())->method('normalizeTheme')->with('DARK')->willReturn('dark');

        $gateway = $this->makeGateway(app: $app);

        $this->assertSame('light', $gateway->defaultTheme());
        $this->assertSame('dark', $gateway->normalizeTheme('DARK'));
    }

    public function testDefaultsAccessorsCastToInt(): void
    {
        $defaults = $this->createMock(SettingsDefaultsGateway::class);
        $defaults->method('getDefaultRoleId')->willReturn(5);
        $defaults->method('getDefaultDepartmentId')->willReturn(12);

        $gateway = $this->makeGateway(defaults: $defaults);

        $this->assertSame(5, $gateway->getDefaultRoleId());
        $this->assertSame(12, $gateway->getDefaultDepartmentId());
    }

    public function testLoginPersistenceAccessorsDelegate(): void
    {
        $login = $this->createMock(SettingsLoginPersistenceGateway::class);
        $login->method('isMicrosoftAutoRememberDefault')->willReturn(true);
        $login->method('getRememberTokenLifetimeDays')->willReturn(14);

        $gateway = $this->makeGateway(login: $login);

        $this->assertTrue($gateway->isMicrosoftAutoRememberDefault());
        $this->assertSame(14, $gateway->getRememberTokenLifetimeDays());
    }

    private function makeGateway(
        ?SettingsMicrosoftGateway $microsoft = null,
        ?SettingsApiPolicyGateway $apiPolicy = null,
        ?SettingsDefaultsGateway $defaults = null,
        ?SettingsAppGateway $app = null,
        ?SettingsLoginPersistenceGateway $login = null,
    ): AuthSettingsGateway {
        return new AuthSettingsGateway(
            $microsoft ?? $this->createMock(SettingsMicrosoftGateway::class),
            $apiPolicy ?? $this->createMock(SettingsApiPolicyGateway::class),
            $defaults ?? $this->createMock(SettingsDefaultsGateway::class),
            $app ?? $this->createMock(SettingsAppGateway::class),
            $login ?? $this->createMock(SettingsLoginPersistenceGateway::class),
        );
    }
}
