<?php

declare(strict_types=1);

namespace Drupal\flowdrop\DTO\Reason;

/**
 * A single tool-aware reasoning request.
 *
 * The provider-neutral input to
 * ChatReasonerInterface::reason(): the
 * conversation to reason over, the tools the model may call (native ToolBinding
 * definitions — {name, description, input_schema}), and the sampling controls.
 * It carries no `drupal/ai` types, so core depends on nothing contrib.
 *
 * @api
 */
final class ReasonRequest {

  /**
   * Constructs a ReasonRequest.
   *
   * @param array<int, \Drupal\flowdrop\DTO\Reason\ReasonMessage> $messages
   *   The conversation to reason over (system turns in the history are ignored;
   *   the system prompt is passed separately).
   * @param array<int, array<string, mixed>> $tools
   *   Tool definitions the model may call, each {name, description,
   *   input_schema} — the native ToolBinding::toDefinition() shape.
   * @param string $model
   *   Explicit model id, or '' to resolve via the operation type / role.
   * @param string $operationType
   *   The operation type or model role to resolve the model through when no
   *   explicit model is given (default 'chat').
   * @param float $temperature
   *   Sampling temperature.
   * @param int $maxTokens
   *   Maximum tokens to generate.
   * @param string $systemPrompt
   *   Instructions for the agent (role, tool guidance, stop conditions).
   */
  public function __construct(
    private readonly array $messages,
    private readonly array $tools = [],
    private readonly string $model = '',
    private readonly string $operationType = 'chat',
    private readonly float $temperature = 0.0,
    private readonly int $maxTokens = 1024,
    private readonly string $systemPrompt = '',
  ) {}

  /**
   * The conversation to reason over.
   *
   * @return array<int, \Drupal\flowdrop\DTO\Reason\ReasonMessage>
   *   The messages.
   */
  public function getMessages(): array {
    return $this->messages;
  }

  /**
   * The tool definitions the model may call.
   *
   * @return array<int, array<string, mixed>>
   *   Each definition is {name, description, input_schema}.
   */
  public function getTools(): array {
    return $this->tools;
  }

  /**
   * The explicit model id.
   *
   * @return string
   *   The model id, or '' to resolve via the operation type / role.
   */
  public function getModel(): string {
    return $this->model;
  }

  /**
   * The operation type / model role used when no explicit model is given.
   *
   * @return string
   *   The operation type or role id.
   */
  public function getOperationType(): string {
    return $this->operationType;
  }

  /**
   * The sampling temperature.
   *
   * @return float
   *   The temperature.
   */
  public function getTemperature(): float {
    return $this->temperature;
  }

  /**
   * The maximum tokens to generate.
   *
   * @return int
   *   The token cap.
   */
  public function getMaxTokens(): int {
    return $this->maxTokens;
  }

  /**
   * The system prompt.
   *
   * @return string
   *   The instructions for the agent.
   */
  public function getSystemPrompt(): string {
    return $this->systemPrompt;
  }

}
