<?php
declare(strict_types=1);

namespace Tests\Unit\Core;

use Tests\TestCase;

class RouterTest extends TestCase
{
    private function matchPath(string $routePath, string $requestPath): array|false
    {
        $routePath = '/' . trim($routePath, '/');
        $requestPath = '/' . trim($requestPath, '/');

        if ($routePath === $requestPath) {
            return [];
        }

        $pattern = preg_replace_callback('/\{(\w+)(?::([^}]+))?\}/', function ($matches) {
            $name = $matches[1];
            $constraint = $matches[2] ?? '[^/]+';
            return '(?P<' . $name . '>' . $constraint . ')';
        }, $routePath);

        $pattern = '#^' . $pattern . '$#';

        if (preg_match($pattern, $requestPath, $matches)) {
            $params = [];
            foreach ($matches as $key => $value) {
                if (is_string($key)) {
                    $params[$key] = $value;
                }
            }
            return $params;
        }

        return false;
    }

    public function testExactMatch(): void
    {
        $this->assertSame([], $this->matchPath('/dashboard', '/dashboard'));
    }

    public function testExactMatchWithTrailingSlash(): void
    {
        $this->assertSame([], $this->matchPath('/dashboard/', '/dashboard'));
    }

    public function testNoMatch(): void
    {
        $this->assertFalse($this->matchPath('/dashboard', '/members'));
    }

    public function testSingleParam(): void
    {
        $result = $this->matchPath('/members/{id}', '/members/42');
        $this->assertSame(['id' => '42'], $result);
    }

    public function testParamWithConstraint(): void
    {
        $result = $this->matchPath('/members/{id:\d+}', '/members/42');
        $this->assertSame(['id' => '42'], $result);
    }

    public function testParamConstraintRejects(): void
    {
        $result = $this->matchPath('/members/{id:\d+}', '/members/abc');
        $this->assertFalse($result);
    }

    public function testMultipleParams(): void
    {
        $result = $this->matchPath('/branches/{branch}/members/{id}', '/branches/1/members/42');
        $this->assertSame(['branch' => '1', 'id' => '42'], $result);
    }

    public function testRootPath(): void
    {
        $this->assertSame([], $this->matchPath('/', '/'));
    }

    public function testNestedPathNoMatch(): void
    {
        $this->assertFalse($this->matchPath('/members', '/members/42'));
    }

    public function testParamWithSlug(): void
    {
        $result = $this->matchPath('/reports/{type}', '/reports/daily-summary');
        $this->assertSame(['type' => 'daily-summary'], $result);
    }
}
