<?php

declare(strict_types=1);

namespace Drupal\flowdrop\DTO\ConfigEdit;

/**
 * Value object for config edit API endpoints.
 *
 * Represents the API endpoints for CRUD operations on dynamically managed
 * configuration entities. This allows the frontend to programmatically
 * create, read, update, and delete configuration entities associated
 * with a node.
 */
final class ConfigEditApiEndpoints {

  /**
   * Constructs a ConfigEditApiEndpoints.
   *
   * @param string|null $create
   *   URL for creating new configuration (POST).
   * @param string|null $read
   *   URL template for reading configuration (GET).
   *   Supports template variables like {id}.
   * @param string|null $update
   *   URL template for updating configuration (PATCH/PUT).
   *   Supports template variables like {id}.
   * @param string|null $delete
   *   URL template for deleting configuration (DELETE).
   *   Supports template variables like {id}.
   * @param array<string, string> $custom
   *   Additional custom endpoints (e.g., "eventTypes" => "/api/event-types").
   */
  public function __construct(
    public readonly ?string $create = NULL,
    public readonly ?string $read = NULL,
    public readonly ?string $update = NULL,
    public readonly ?string $delete = NULL,
    public readonly array $custom = [],
  ) {}

  /**
   * 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 {
    // Extract standard CRUD endpoints.
    $create = $data["create"] ?? NULL;
    $read = $data["read"] ?? NULL;
    $update = $data["update"] ?? NULL;
    $delete = $data["delete"] ?? NULL;

    // Everything else goes into custom.
    $custom = array_diff_key($data, [
      "create" => TRUE,
      "read" => TRUE,
      "update" => TRUE,
      "delete" => TRUE,
    ]);

    return new self(
      create: $create,
      read: $read,
      update: $update,
      delete: $delete,
      custom: $custom,
    );
  }

  /**
   * Converts the object to an array suitable for JSON serialization.
   *
   * @return array<string, mixed>
   *   The array representation.
   */
  public function toArray(): array {
    $result = [];

    if ($this->create !== NULL) {
      $result["create"] = $this->create;
    }
    if ($this->read !== NULL) {
      $result["read"] = $this->read;
    }
    if ($this->update !== NULL) {
      $result["update"] = $this->update;
    }
    if ($this->delete !== NULL) {
      $result["delete"] = $this->delete;
    }

    // Merge custom endpoints.
    return array_merge($result, $this->custom);
  }

}
