<?php

namespace MintyPHP\Tests\Service\Settings;

use MintyPHP\Service\Settings\SettingCacheService;
use MintyPHP\Service\Settings\SettingKeys;
use MintyPHP\Service\Settings\SettingsMetadataGateway;
use PHPUnit\Framework\TestCase;

class SettingCacheServiceTest extends TestCase
{
    public function testGetReturnsNullForMissingKey(): void
    {
        $file = $this->tempFilePath();
        file_put_contents($file, "<?php\nreturn ['app_title' => 'Demo'];\n");

        $service = new SettingCacheService($file);
        $this->assertNull($service->get('missing'));
    }

    public function testUpdateWritesAndNormalizesValues(): void
    {
        $file = $this->tempFilePath();
        file_put_contents($file, "<?php\nreturn ['app_title' => 'Old'];\n");

        $service = new SettingCacheService($file);
        $this->assertTrue($service->update([
            'app_title' => 'New',
            'app_locale' => null,
        ]));

        $this->assertSame('New', $service->get('app_title'));
        $this->assertNull($service->get('app_locale'));
    }

    public function testDefaultFilePathUsesStorageRuntimeSettingsFile(): void
    {
        $service = new SettingCacheService();

        $this->assertStringEndsWith('/storage/runtime/settings.php', $service->filePath());
    }

    public function testColdStartHydratesHotPathKeysFromDatabaseAndWritesCacheFile(): void
    {
        $file = $this->tempFilePath();

        $metadataGateway = $this->createMock(SettingsMetadataGateway::class);
        $metadataGateway->expects($this->exactly(3))
            ->method('getValue')
            ->willReturnCallback(static function (string $key): ?string {
                return match ($key) {
                    SettingKeys::APP_TITLE_KEY => 'Demo App',
                    SettingKeys::APP_LOCALE_KEY => 'de',
                    SettingKeys::APP_REGISTRATION_KEY => '0',
                    default => null,
                };
            });

        $service = new SettingCacheService($file, $metadataGateway);
        $this->assertSame('Demo App', $service->get('app_title'));
        $this->assertFileExists($file);

        /** @var array<string, string> $cache */
        $cache = include $file;
        $this->assertSame('de', $cache[SettingKeys::APP_LOCALE_KEY] ?? null);
        $this->assertSame('0', $cache[SettingKeys::APP_REGISTRATION_KEY] ?? null);
    }

    private function tempFilePath(): string
    {
        $dir = sys_get_temp_dir() . '/mintyphp_settings_cache_test_' . bin2hex(random_bytes(6));
        mkdir($dir, 0775, true);
        $file = $dir . '/settings.php';

        $this->addToAssertionCount(1);
        $this->assertDirectoryExists($dir);

        return $file;
    }
}
