<?php

namespace MintyPHP\Tests\Support\Helpers;

use MintyPHP\App\AppContainer;
use MintyPHP\App\Module\ModuleRegistry;
use MintyPHP\Tests\Support\AppContainerIsolationTrait;
use PHPUnit\Framework\TestCase;

class EndpointUrlTest extends TestCase
{
    use AppContainerIsolationTrait;

    protected function tearDown(): void
    {
        $this->restoreAppContainer();
    }

    public function testResolvesSourcePathToTarget(): void
    {
        $this->installRegistryWithRoutes([
            ['path' => 'admin/system-audit/export', 'target' => 'audit/system-audit/export', 'module_id' => 'audit'],
        ]);

        $this->assertStringEndsWith('audit/system-audit/export', endpointUrl('admin/system-audit/export'));
    }

    public function testIdempotentWhenPathEqualsTarget(): void
    {
        $this->installRegistryWithRoutes([
            ['path' => 'helpdesk/domains/export', 'target' => 'helpdesk/domains/export', 'module_id' => 'helpdesk'],
        ]);

        $this->assertStringEndsWith('helpdesk/domains/export', endpointUrl('helpdesk/domains/export'));
    }

    public function testFallsThroughToLurlForUnregisteredPath(): void
    {
        $this->installRegistryWithRoutes([]);

        $this->assertSame(lurl('admin/users/export'), endpointUrl('admin/users/export'));
    }

    public function testIgnoresLeadingSlash(): void
    {
        $this->installRegistryWithRoutes([
            ['path' => 'admin/system-audit/export', 'target' => 'audit/system-audit/export', 'module_id' => 'audit'],
        ]);

        $this->assertSame(
            endpointUrl('admin/system-audit/export'),
            endpointUrl('/admin/system-audit/export')
        );
    }

    public function testDegradesGracefullyWhenRegistryMissing(): void
    {
        $this->pushAppContainer(new AppContainer());

        // No ModuleRegistry registered — endpointUrl() must fall back, not throw.
        $this->assertSame(lurl('some/path'), endpointUrl('some/path'));
    }

    /**
     * @param list<array{path: string, target: string, module_id?: string}> $routes
     */
    private function installRegistryWithRoutes(array $routes): void
    {
        // ModuleRegistry is final and has no public constructor — build via
        // reflection and write the merged-routes field directly. Only used
        // by endpointUrl() via getRoutes(), so that is all we need to stage.
        $registry = (new \ReflectionClass(ModuleRegistry::class))->newInstanceWithoutConstructor();
        $routesProp = (new \ReflectionClass(ModuleRegistry::class))->getProperty('mergedRoutes');
        $routesProp->setValue($registry, $routes);

        $container = new AppContainer();
        $container->set(ModuleRegistry::class, static fn (): ModuleRegistry => $registry);
        $this->pushAppContainer($container);
    }
}
