<?php

declare(strict_types=1);

namespace Drupal\flowdrop\DTO\ConfigEdit;

/**
 * Value object for dynamic schema endpoint configuration.
 *
 * Represents the configuration for fetching a node's config schema
 * dynamically from a REST endpoint at runtime. This is useful when:
 * - Config options depend on external data (e.g., available models, API keys)
 * - Options change based on user authentication or permissions
 * - Schema needs to be refreshed periodically.
 *
 * @see config-edit.md for full specification
 */
final class DynamicSchemaEndpoint {

  /**
   * Constructs a DynamicSchemaEndpoint.
   *
   * @param string $url
   *   The URL endpoint to fetch the schema from.
   *   Supports template variables like {nodeTypeId}, {instanceId}.
   * @param string $method
   *   HTTP method to use (GET, POST). Defaults to GET.
   * @param array<string, string> $parameterMapping
   *   Maps URL template variables to node data paths.
   *   Example: ["nodeTypeId" => "metadata.id", "instanceId" => "id"].
   * @param array<string, string> $headers
   *   Additional HTTP headers to include in the request.
   * @param bool $cacheSchema
   *   Whether to cache the fetched schema. Default TRUE.
   *   Set to FALSE if schema varies by dynamic parameters.
   * @param int $timeout
   *   Request timeout in milliseconds. Default 10000 (10 seconds).
   */
  public function __construct(
    public readonly string $url,
    public readonly string $method = "GET",
    public readonly array $parameterMapping = [],
    public readonly array $headers = [],
    public readonly bool $cacheSchema = TRUE,
    public readonly int $timeout = 10000,
  ) {}

  /**
   * Creates an instance from an array.
   *
   * @param array<string, mixed> $data
   *   The array data to create the instance from.
   *
   * @return self
   *   The created instance.
   */
  public static function fromArray(array $data): self {
    return new self(
      url: $data["url"] ?? "",
      method: $data["method"] ?? "GET",
      parameterMapping: $data["parameterMapping"] ?? [],
      headers: $data["headers"] ?? [],
      cacheSchema: $data["cacheSchema"] ?? TRUE,
      timeout: $data["timeout"] ?? 10000,
    );
  }

  /**
   * Converts the object to an array suitable for JSON serialization.
   *
   * @return array<string, mixed>
   *   The array representation.
   */
  public function toArray(): array {
    return [
      "url" => $this->url,
      "method" => $this->method,
      "parameterMapping" => $this->parameterMapping,
      "headers" => $this->headers,
      "cacheSchema" => $this->cacheSchema,
      "timeout" => $this->timeout,
    ];
  }

}
