<?php

declare(strict_types=1);

namespace Drupal\flowdrop\Service\Reasoning;

use Drupal\flowdrop\DTO\Reason\ModelChoices;
use Drupal\flowdrop\DTO\Reason\ReasonRequest;
use Drupal\flowdrop\DTO\Reason\ReasonResult;

/**
 * Performs one tool-aware LLM inference for a graph-authored agent.
 *
 * The reasoning boundary of FlowDrop core: the {@see
 * \Drupal\flowdrop_node_processor\Plugin\FlowDropNodeProcessor\Reason} node
 * depends only on this contract and FlowDrop's own DTOs, so core carries NO
 * `drupal/ai` (or any other AI backend) dependency. The concrete binding — e.g.
 * a `drupal/ai`-backed implementation — lives in the module that owns that
 * dependency and is registered as `flowdrop.chat_reasoner`.
 *
 * A backend that translates FlowDrop's neutral message / tool DTOs into a
 * provider's shapes must round-trip them faithfully: a well-formed tool-use /
 * tool-result history in, and either the model's requested tool calls or a
 * final answer out. Buffer repair (ToolPairing) and loop control belong to the
 * caller, not the backend.
 *
 * @api
 */
interface ChatReasonerInterface {

  /**
   * Runs one reasoning step.
   *
   * @param \Drupal\flowdrop\DTO\Reason\ReasonRequest $request
   *   The conversation, tools and sampling controls to reason over.
   *
   * @return \Drupal\flowdrop\DTO\Reason\ReasonResult
   *   What the model wants to do next — tool calls or a final answer.
   *
   * @throws \RuntimeException
   *   When no AI backend / model is available to serve the request.
   */
  public function reason(ReasonRequest $request): ReasonResult;

  /**
   * Describes the model / operation-type choices this backend offers.
   *
   * Lets a reasoning node populate its config schema without importing a
   * backend service. Returns an empty set when no models are configured.
   *
   * @param string $operationType
   *   The operation type to enumerate choices for (default 'chat').
   *
   * @return \Drupal\flowdrop\DTO\Reason\ModelChoices
   *   The available models, default and operation-type / role options.
   */
  public function getModelChoices(string $operationType = 'chat'): ModelChoices;

}
