<?php

declare(strict_types=1);

namespace App\Framework\StaticSite;

use App\Framework\Attributes\StaticPage;
use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\Router\HttpRouter;
use App\Framework\Router\Route;
use App\Framework\Router\RouteCollection;

class StaticPageCollector
{
    private HttpRouter $router;

    public function __construct(HttpRouter $router)
    {
        $this->router = $router;
    }

    /**
     * Sammelt alle Routen mit dem StaticPage-Attribut
     *
     * @return array Liste aller statischen Seitenrouten
     */
    public function collectStaticPages(): array
    {
        $staticPages = [];
        $routeCollection = $this->router->getRoutes();

        if ($routeCollection instanceof RouteCollection) {
            foreach ($routeCollection->getAll() as $route) {
                if ($this->hasStaticPageAttribute($route->controller, $route->action)) {
                    $staticPages[] = $route->path;
                }
            }
        }

        return $staticPages;
    }

    /**
     * Sammelt alle GET-Routen unabhängig vom StaticPage-Attribut
     *
     * @return array Liste aller GET-Routen
     */
    public function collectAllGetRoutes(): array
    {
        $routes = [];
        $routeCollection = $this->router->getRoutes();

        if ($routeCollection instanceof RouteCollection) {
            foreach ($routeCollection->getAll() as $route) {
                if (in_array('GET', $route->methods)) {
                    $routes[] = $route->path;
                }
            }
        }

        return $routes;
    }

    /**
     * Prüft, ob die Controller-Methode das StaticPage-Attribut hat
     */
    private function hasStaticPageAttribute(string $controllerClass, string $methodName): bool
    {
        if (empty($controllerClass) || ! ClassName::create($controllerClass)->exists() || ! method_exists($controllerClass, $methodName)) {
            return false;
        }

        try {
            $reflectionMethod = new \ReflectionMethod($controllerClass, $methodName);
            $attributes = $reflectionMethod->getAttributes(StaticPage::class);

            return count($attributes) > 0;
        } catch (\ReflectionException $e) {
            return false;
        }
    }

    /**
     * Filtert die Routen nach bestimmten Kriterien
     *
     * @param array $routes Liste der Routen
     * @param array $exclude Pfade, die ausgeschlossen werden sollen
     * @return array Gefilterte Routen
     */
    public function filterRoutes(array $routes, array $exclude = []): array
    {
        return array_filter($routes, function ($route) use ($exclude) {
            // Prüfe, ob Route ausgeschlossen werden soll
            foreach ($exclude as $pattern) {
                if (preg_match($pattern, $route)) {
                    return false;
                }
            }

            // Schließe Routen mit Platzhaltern aus (z.B. /users/{id})
            if (strpos($route, '{') !== false && strpos($route, '}') !== false) {
                return false;
            }

            return true;
        });
    }
}
