<?php

declare(strict_types=1);

namespace App\Framework\Router;

use App\Framework\Core\DynamicRoute;

/**
 * Value Object representing compiled route data for optimized routing
 */
final readonly class RouteData
{
    /**
     * @param DynamicRoute $route The original dynamic route
     * @param array<string, int> $paramMap Parameter name to regex group index mapping
     * @param int $routeGroupIndex Index of the route's capture group in combined regex
     * @param string $batch Batch name for complexity grouping ('simple', 'medium', 'complex')
     * @param string $regex Pre-compiled individual regex for this route
     */
    public function __construct(
        public DynamicRoute $route,
        public array $paramMap,
        public int $routeGroupIndex,
        public string $batch,
        public string $regex
    ) {
    }

    /**
     * Create RouteData from array (for backward compatibility)
     * @param array{route: DynamicRoute, paramMap: array<string, int>, routeGroupIndex: int, batch: string, regex: string} $data
     */
    public static function fromArray(array $data): self
    {
        return new self(
            route: $data['route'],
            paramMap: $data['paramMap'],
            routeGroupIndex: $data['routeGroupIndex'],
            batch: $data['batch'],
            regex: $data['regex']
        );
    }

    /**
     * Convert to array (for serialization/caching)
     * @return array{route: DynamicRoute, paramMap: array<string, int>, routeGroupIndex: int, batch: string, regex: string}
     */
    public function toArray(): array
    {
        return [
            'route' => $this->route,
            'paramMap' => $this->paramMap,
            'routeGroupIndex' => $this->routeGroupIndex,
            'batch' => $this->batch,
            'regex' => $this->regex,
        ];
    }

    /**
     * Extract parameter values from regex matches
     * @param array<int|string, string> $matches
     * @return array<string, string>
     */
    public function extractParameterValues(array $matches): array
    {
        $params = [];
        foreach ($this->paramMap as $paramName => $matchIndex) {
            if (isset($matches[$matchIndex]) && $matches[$matchIndex] !== '') {
                $params[$paramName] = $matches[$matchIndex];
            }
        }

        return $params;
    }

    /**
     * Check if this route should match based on the regex matches
     * @param array<int|string, string> $matches
     */
    public function shouldMatch(array $matches): bool
    {
        return isset($matches[$this->routeGroupIndex]) && $matches[$this->routeGroupIndex] !== '';
    }

    /**
     * Get the route's complexity level
     */
    public function getComplexity(): string
    {
        return $this->batch;
    }

    /**
     * Get the number of parameters this route expects
     */
    public function getParameterCount(): int
    {
        return count($this->paramMap);
    }

    /**
     * Get parameter names
     * @return array<string>
     */
    public function getParameterNames(): array
    {
        return array_keys($this->paramMap);
    }

    /**
     * Check if this route has a specific parameter
     */
    public function hasParameter(string $paramName): bool
    {
        return isset($this->paramMap[$paramName]);
    }
}
