<?php

namespace MintyPHP\Tests\Http;

use MintyPHP\Http\RouteCatalog;
use PHPUnit\Framework\TestCase;
use RuntimeException;

final class RouteCatalogTest extends TestCase
{
    /** @var list<string> */
    private array $tempFiles = [];

    /** @var list<string> */
    private array $tempDirs = [];

    protected function tearDown(): void
    {
        foreach ($this->tempFiles as $file) {
            @unlink($file);
        }
        foreach ($this->tempDirs as $dir) {
            @rmdir($dir);
        }
    }

    public function testLoadsCoreRoutesAndPublicPathsFromConfigFile(): void
    {
        $routesFile = $this->createRoutesFile([
            ['path' => 'login', 'target' => 'auth/login', 'public' => true],
            ['path' => 'profile', 'target' => 'account/profile', 'public' => false],
        ]);

        $catalog = RouteCatalog::fromConfigFile($routesFile);

        self::assertSame(
            [
                ['path' => 'login', 'target' => 'auth/login', 'public' => true],
                ['path' => 'profile', 'target' => 'account/profile', 'public' => false],
            ],
            $catalog->coreRoutes()
        );
        self::assertSame(['auth/login', 'login'], $catalog->corePublicPaths());
    }

    public function testThrowsWhenRouteConfigDoesNotReturnArray(): void
    {
        $routesFile = $this->createRawConfigFile("<?php return 'invalid';\n");

        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('must return an array');

        RouteCatalog::fromConfigFile($routesFile);
    }

    public function testThrowsForInvalidRouteShape(): void
    {
        $routesFile = $this->createRoutesFile([
            ['path' => 'login'],
        ]);

        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Invalid route definition');

        RouteCatalog::fromConfigFile($routesFile);
    }

    /**
     * @param list<array<string, mixed>> $routes
     */
    private function createRoutesFile(array $routes): string
    {
        return $this->createRawConfigFile(
            '<?php return ' . var_export($routes, true) . ";\n"
        );
    }

    private function createRawConfigFile(string $contents): string
    {
        $dir = sys_get_temp_dir() . '/route-catalog-test-' . uniqid('', true);
        mkdir($dir, 0777, true);

        $file = $dir . '/routes.php';
        file_put_contents($file, $contents);

        $this->tempFiles[] = $file;
        $this->tempDirs[] = $dir;
        return $file;
    }
}
