<?php

declare(strict_types=1);

namespace Instinctor\Core;


if (!defined('ABSPATH')) exit;
use Instinctor\Core\Router\DriverInterface;
use Instinctor\Core\Router\WordPressDriver;
use Instinctor\Core\Router\StandaloneDriver;

/**
 * Router — static facade over the active routing driver.
 *
 * Driver selection:
 *   INSTINCTOR_ENV = 'wordpress'   → WordPressDriver  (default)
 *   INSTINCTOR_ENV = 'standalone'  → StandaloneDriver (stub until M11)
 *
 * REST routes:
 *   Router::rest('GET', '/products', [$this, 'getProducts'])
 *   Router::rest('POST', '/products', [$this, 'createProduct'], ['permission_callback' => [$this, 'canManage']])
 *   Router::restRaw('/products', $wpStyleArgsArray)   // migration helper, preserves WP permission_callback
 *
 * Frontend named routes:
 *   Router::add('shop',     '/shop',             [$this, 'renderShop'])
 *   Router::add('product',  '/shop/:slug',        [$this, 'renderProduct'])
 *   Router::add('account',  '/account/:section',  [$this, 'renderAccount'], ['auth'])
 *   Router::add('checkout', '/checkout',          [$this, 'renderCheckout'])
 *
 * URL generation:
 *   Router::url('product', ['slug' => 'my-product'])  // → https://example.com/shop/my-product
 *
 * REST base URL:
 *   Router::restBase()  // → https://example.com/wp-json/instinctor/v1
 */
class Router
{
    private static ?DriverInterface $driver = null;

    public static function driver(): DriverInterface
    {
        if (self::$driver === null) {
            self::$driver = self::makeDriver();
        }
        return self::$driver;
    }

    public static function setDriver(DriverInterface $driver): void
    {
        self::$driver = $driver;
    }

    private static function makeDriver(): DriverInterface
    {
        $env = defined('INSTINCTOR_ENV') ? INSTINCTOR_ENV : 'wordpress';
        return match ($env) {
            'standalone' => new StandaloneDriver(),
            default      => new WordPressDriver(),
        };
    }

    // -------------------------------------------------------------------------
    // Static API
    // -------------------------------------------------------------------------

    /**
     * Register a REST route.
     *
     * @param string   $method   HTTP method(s): 'GET', 'POST', 'PUT', 'DELETE', 'GET,POST'
     * @param string   $path     Path relative to namespace, e.g. '/products' or '/products/(?P<id>\d+)'
     * @param callable $handler  Request handler
     * @param array    $options  Optional: ['permission_callback' => ..., 'auth' => bool, 'args' => [...]]
     */
    public static function rest(string $method, string $path, callable $handler, array $options = []): void
    {
        self::driver()->rest($method, $path, $handler, $options);
    }

    /**
     * Register a REST route using the full WP-style args array.
     * Migration helper — preserves existing permission_callback logic as-is.
     *
     * Router::restRaw('/products', [
     *     ['methods' => 'GET', 'callback' => ..., 'permission_callback' => ...],
     *     ['methods' => 'POST', 'callback' => ..., 'permission_callback' => ...],
     * ]);
     */
    public static function restRaw(string $path, array $args): void
    {
        self::driver()->restRaw($path, $args);
    }

    /**
     * Register a named frontend route.
     *
     * @param string   $name       Route name (used for URL generation)
     * @param string   $pattern    URL pattern, e.g. '/shop/:slug'
     * @param callable $handler    Called with extracted params array
     * @param array    $middleware Middleware: 'auth', 'admin', 'nonce:action_name'
     */
    public static function add(string $name, string $pattern, callable $handler, array $middleware = []): void
    {
        self::driver()->add($name, $pattern, $handler, $middleware);
    }

    /**
     * Dispatch the current request. Called by template_redirect on WP.
     */
    public static function dispatch(): void
    {
        self::driver()->dispatch();
    }

    /**
     * Generate a URL for a named route.
     *
     * @param string $name   Route name
     * @param array  $params Parameter substitutions, e.g. ['slug' => 'my-product']
     */
    public static function url(string $name, array $params = []): string
    {
        return self::driver()->url($name, $params);
    }

    /**
     * REST API base URL including namespace.
     * e.g. https://example.com/wp-json/instinctor/v1
     */
    public static function restBase(): string
    {
        return self::driver()->restBase();
    }
}
