<?php
/**
 * ===========================================
 * FLOWBOT DCI - API ROUTER
 * ===========================================
 * API-002: Routes requests to versioned API controllers
 * Handles version negotiation and backward compatibility
 */

declare(strict_types=1);

namespace FlowbotDCI\Api;

use FlowbotDCI\Api\v1\ApiController as V1Controller;
use FlowbotDCI\Services\CircuitBreaker;
use FlowbotDCI\Services\RetryManager;

class ApiRouter
{
    // Supported API versions
    const SUPPORTED_VERSIONS = ['1'];
    const DEFAULT_VERSION = '1';
    const LATEST_VERSION = '1';

    private string $processId;
    private ?CircuitBreaker $circuitBreaker = null;
    private ?RetryManager $retryManager = null;

    public function __construct(string $processId)
    {
        $this->processId = $processId;
    }

    /**
     * Set circuit breaker instance
     */
    public function setCircuitBreaker(CircuitBreaker $cb): self
    {
        $this->circuitBreaker = $cb;
        return $this;
    }

    /**
     * Set retry manager instance
     */
    public function setRetryManager(RetryManager $rm): self
    {
        $this->retryManager = $rm;
        return $this;
    }

    /**
     * Route API request
     * @param string $version API version (e.g., '1', 'v1', 'latest')
     * @param string $action API action
     * @param array $params Request parameters
     * @return array Response data
     */
    public function route(string $version, string $action, array $params = []): array
    {
        // Normalize version
        $version = $this->normalizeVersion($version);

        // Validate version
        if (!$this->isValidVersion($version)) {
            return $this->versionError($version);
        }

        // Get controller for version
        $controller = $this->getController($version);

        if ($controller === null) {
            return $this->versionError($version);
        }

        // Inject dependencies
        if ($this->circuitBreaker) {
            $controller->setCircuitBreaker($this->circuitBreaker);
        }
        if ($this->retryManager) {
            $controller->setRetryManager($this->retryManager);
        }

        // Handle request
        return $controller->handle($action, $params);
    }

    /**
     * Handle legacy API request (no version specified)
     * Routes to default version
     */
    public function handleLegacy(string $action, array $params = []): array
    {
        return $this->route(self::DEFAULT_VERSION, $action, $params);
    }

    /**
     * Get list of supported versions
     */
    public function getSupportedVersions(): array
    {
        return self::SUPPORTED_VERSIONS;
    }

    /**
     * Normalize version string
     * Handles: '1', 'v1', 'V1', 'latest'
     */
    private function normalizeVersion(string $version): string
    {
        $version = strtolower(trim($version));

        // Handle 'latest'
        if ($version === 'latest') {
            return self::LATEST_VERSION;
        }

        // Remove 'v' prefix if present
        if (str_starts_with($version, 'v')) {
            $version = substr($version, 1);
        }

        // Extract major version only
        $parts = explode('.', $version);
        return $parts[0];
    }

    /**
     * Check if version is valid
     */
    private function isValidVersion(string $version): bool
    {
        return in_array($version, self::SUPPORTED_VERSIONS);
    }

    /**
     * Get controller for version
     */
    private function getController(string $version): ?object
    {
        switch ($version) {
            case '1':
                return new V1Controller($this->processId);
            // Future versions:
            // case '2':
            //     return new V2Controller($this->processId);
            default:
                return null;
        }
    }

    /**
     * Generate version error response
     */
    private function versionError(string $version): array
    {
        return [
            'success' => false,
            'error' => [
                'message' => "API version '$version' is not supported",
                'code' => 400,
                'supported_versions' => self::SUPPORTED_VERSIONS,
                'latest_version' => self::LATEST_VERSION,
            ],
            'meta' => [
                'timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
            ],
            'http_code' => 400,
        ];
    }

    /**
     * Parse API path
     * Handles: /api/v1/progress, /api/progress (legacy)
     * @return array ['version' => string, 'action' => string]
     */
    public static function parsePath(string $path): array
    {
        $path = trim($path, '/');
        $parts = explode('/', $path);

        // Remove 'api' prefix if present
        if (!empty($parts) && $parts[0] === 'api') {
            array_shift($parts);
        }

        // Check for version
        $version = self::DEFAULT_VERSION;
        if (!empty($parts) && preg_match('/^v?\d+$/i', $parts[0])) {
            $version = array_shift($parts);
        }

        // Get action
        $action = !empty($parts) ? $parts[0] : 'progress';

        return [
            'version' => $version,
            'action' => $action,
        ];
    }

    /**
     * Send JSON response
     */
    public static function sendResponse(array $response): void
    {
        $httpCode = $response['http_code'] ?? 200;
        unset($response['http_code']);

        http_response_code($httpCode);
        header('Content-Type: application/json; charset=utf-8');
        header('X-API-Version: ' . self::LATEST_VERSION);
        header('Cache-Control: no-cache, no-store, must-revalidate');

        echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    }
}
