<?php
// app/http/Router.php

declare(strict_types=1);

namespace ScMedia\Http;

final class Router {
  private array $routes = [];

  public function get(string $path, callable $handler): void {
    $this->routes[] = ['GET', $path, $handler];
  }

  public function post(string $path, callable $handler): void {
    $this->routes[] = ['POST', $path, $handler];
  }

  public function put(string $path, callable $handler): void {
    $this->routes[] = ['PUT', $path, $handler];
  }

  public function delete(string $path, callable $handler): void {
    $this->routes[] = ['DELETE', $path, $handler];
  }

  public function add(string $method, string $path, callable $handler): void {
    $method = strtoupper($method);
    $allowed = ['GET', 'POST', 'PUT', 'DELETE'];
    if (!in_array($method, $allowed, true)) {
      throw new \InvalidArgumentException("Unsupported method: {$method}");
    }
    $this->routes[] = [$method, $path, $handler];
  }

  public function dispatch(string $method, string $uriPath): void {
    foreach ($this->routes as $r) {
      [$m, $p, $h] = $r;
      if ($m !== $method) {
        continue;
      }
      $params = $this->match($p, $uriPath);
      if ($params === null) {
        continue;
      }
      $h($params);
      return;
    }

    if (str_starts_with($uriPath, '/api/')) {
      Response::json([
        'ok' => false,
        'error' => [
          'code' => 'NOT_FOUND',
          'message' => 'Route not found',
        ],
      ], 404);
      return;
    }
    Response::html('<h1>404</h1>', 404);
  }

  private function match(string $pattern, string $path): ?array {
    // Pattern supports: /api/scan-profiles/{id}
    $pParts = explode('/', trim($pattern, '/'));
    $uParts = explode('/', trim($path, '/'));

    if (count($pParts) !== count($uParts)) {
      return null;
    }

    $params = [];
    for ($i = 0; $i < count($pParts); $i++) {
      $pp = $pParts[$i];
      $up = $uParts[$i];

      if (preg_match('/^\{([a-zA-Z0-9_]+)\}$/', $pp, $m)) {
        $params[$m[1]] = $up;
        continue;
      }

      if ($pp !== $up) {
        return null;
      }
    }

    return $params;
  }
}
