<?php

namespace App;

use App\Utils\Debug;
use Cocur\Slugify\Slugify;

class Router {
    private $routes = array();
    private $match;
    private $requestUrl;
    private $config;


    /**
     * Maps a URL pattern to a target controller/action with a specific HTTP method
     *
     * @param string $method The HTTP method
     * @param string $url The URL pattern to match
     * @param string $target The target controller/action that should handle the route
     * @return void
     */
    public function map(string $method, string $url, string $target): void {
        $url = preg_replace('/\{([a-zA-Z0-9_]+)\}/', '(?P<\1>[a-zA-Z0-9_-]+)', $url);
        $this->routes[] = array($method, '#^' . $url . '$#', $target);
    }

    /**
     * Matches the current request against defined routes and returns the target and parameters.
     *
     * @param array $config The configuration array
     * @return array|false Returns an array containing the target and parameters
     */
    public function match(array $config): array|false {
        $requestMethod = $_SERVER['REQUEST_METHOD'];
        $this->requestUrl = $requestUrl = strtok($_SERVER['REQUEST_URI'], '?');

        parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $extraParams);

        foreach ($this->routes as $route) {
            list($method, $url, $target) = $route;

            if ($requestMethod === $method) {
                if (preg_match($url, $requestUrl, $params)) {
                    $slug = new Slugify();
                    if ($requestUrl === '/') {
                        $requestUrl = 'home';
                    }
                    $params = array_filter($params, 'is_string', ARRAY_FILTER_USE_KEY);
                    $params['requestUrl'] = $requestUrl;
                    $params['cacheName'] = $slug->slugify($requestUrl . '_' . implode('-', $extraParams)) . '.html';
                    $params['type'] = $this->getType($target);
                    $params['config'] = $config;
                    $params['extraParams'] = $extraParams;
                    $this->match['requestUrl'] = $requestUrl;
                    $this->match = array('target' => $target, 'params' => $params);
                    return $this->match;
                }
            }
        }
        return false;
    }

    /**
     * Retrieves the type of the target by extracting and normalizing its name
     *
     * @param string $target The fully qualified name of the target
     * @return string The lowercase name of the target without its namespace
     */
    private function getType(string $target): string {
        return strtolower(basename(str_replace('\\', '/', $target)));
    }

    /**
     * Renders the content by invoking the matched target's index method
     *
     * @return string The rendered content as a string
     */
    public function render(): string {
        $target = $this->match['target'];
        $params = [$this->match['params']];
        $author = $params[0]['config']['author'];
        $siteName = $params[0]['config']['siteName'];
        $navLinks = $params[0]['config']['navLinks'];
        $className = '\\' . $target;
        $controller_instance = new $className();
        $content = call_user_func_array(array($controller_instance, 'index'), $params);
        $title = $controller_instance->title();
        ob_start();
        require_once __DIR__ . '/../template/bone.php';

        $contentFinal = ob_get_contents();
        ob_end_clean();
        return $contentFinal;
    }
}