<?php

declare(strict_types=1);

namespace Tests\Framework\StaticSite;

use App\Framework\Attributes\StaticPage;
use App\Framework\Router\HttpRouter;
use App\Framework\Router\Route;
use App\Framework\Router\RouteCollection;
use App\Framework\StaticSite\StaticPageCollector;
use PHPUnit\Framework\TestCase;

class StaticPageCollectorTest extends TestCase
{
    public function testCollectStaticPages(): void
    {
        // Controller-Klasse mit StaticPage-Attribut simulieren
        $controllerClass = 'TestStaticPageController';
        $this->createTestControllerClass($controllerClass);

        // Testdaten vorbereiten
        $routes = [
            new Route(path: '/', controller: $controllerClass, action: 'indexAction', methods: ['GET']),
            new Route(path: '/about', controller: $controllerClass, action: 'aboutAction', methods: ['GET']),
            new Route(path: '/contact', controller: $controllerClass, action: 'contactAction', methods: ['GET']),
            new Route(path: '/api/data', controller: 'ApiController', action: 'getData', methods: ['GET']),
        ];

        $routeCollection = $this->createMock(RouteCollection::class);
        $routeCollection->method('getAll')->willReturn($routes);

        $router = $this->createMock(HttpRouter::class);
        $router->method('getRoutes')->willReturn($routeCollection);

        // StaticPageCollector initialisieren
        $collector = new StaticPageCollector($router);

        // Statische Seiten sammeln
        $staticPages = $collector->collectStaticPages();

        // Prüfen, ob die richtigen Seiten gesammelt wurden
        $this->assertContains('/', $staticPages);
        $this->assertContains('/about', $staticPages);
        $this->assertNotContains('/contact', $staticPages); // Kein StaticPage-Attribut
        $this->assertNotContains('/api/data', $staticPages); // Anderer Controller ohne StaticPage-Attribut
    }

    public function testCollectAllGetRoutes(): void
    {
        // Testdaten vorbereiten
        $routes = [
            new Route(path: '/', controller: 'TestController', action: 'index', methods: ['GET']),
            new Route(path: '/about', controller: 'TestController', action: 'about', methods: ['GET']),
            new Route(path: '/contact', controller: 'TestController', action: 'contact', methods: ['POST']),
            new Route(path: '/api/data', controller: 'ApiController', action: 'getData', methods: ['GET']),
        ];

        $routeCollection = $this->createMock(RouteCollection::class);
        $routeCollection->method('getAll')->willReturn($routes);

        $router = $this->createMock(HttpRouter::class);
        $router->method('getRoutes')->willReturn($routeCollection);

        // StaticPageCollector initialisieren
        $collector = new StaticPageCollector($router);

        // Alle GET-Routen sammeln
        $allGetRoutes = $collector->collectAllGetRoutes();

        // Prüfen, ob die richtigen Seiten gesammelt wurden
        $this->assertContains('/', $allGetRoutes);
        $this->assertContains('/about', $allGetRoutes);
        $this->assertContains('/api/data', $allGetRoutes);
        $this->assertNotContains('/contact', $allGetRoutes); // POST-Route sollte nicht enthalten sein
    }

    /**
     * Erstellt eine temporäre Controller-Klasse mit StaticPage-Attributen für Tests
     */
    private function createTestControllerClass(string $className): void
    {
        if (class_exists($className)) {
            return;
        }

        $code = <<<EOT
        class {$className} {
            #[\App\Framework\Attributes\StaticPage]
            public function indexAction() {}

            #[\App\Framework\Attributes\StaticPage(outputPath: 'custom-about')]
            public function aboutAction() {}

            // Keine StaticPage-Annotation
            public function contactAction() {}
        }
        EOT;

        eval($code);
    }
}
