<?php

declare(strict_types=1);

namespace Drupal\flowdrop_session\Service;

use Drupal\flowdrop_session\DTO\TurnOptions;
use Drupal\flowdrop_session\DTO\TurnResult;

/**
 * Executes chat turns on a session.
 *
 * THE first-class "chat turn" verb: posts a user message and executes the
 * session's workflow on it, composing SessionService::postMessage() with
 * the existing session execution bookkeeping (chat-input injection,
 * assistant write-back, session status transitions) — no new execution
 * path. This is the single entry point for driving a chat turn; consumers
 * no longer assemble a post-then-reflect dance themselves.
 *
 * Async by default: returns once the turn is scheduled (deferred-sync or
 * queue, per the session's execution mode). Completion is observed via the
 * session turn events, not by polling this result.
 *
 * Access is enforced by the HTTP/route layer that drives a turn (the
 * playground "drive session" access check), not by this service: callers
 * invoking it directly (drush, queue, other modules) are trusted and must
 * have already established the right to execute the session's workflow.
 *
 * @api
 */
interface SessionTurnServiceInterface {

  /**
   * Posts a user message and executes the session's workflow on it.
   *
   * A turn is a serialized unit per session: a second turn while the
   * session is RUNNING is refused. AWAITING_INPUT accepts the next turn —
   * that message is the resume.
   *
   * @param string $sessionId
   *   The session entity id.
   * @param string $content
   *   The user message content.
   * @param \Drupal\flowdrop_session\DTO\TurnOptions $options
   *   Turn options (wait, extra inputs).
   *
   * @return \Drupal\flowdrop_session\DTO\TurnResult
   *   The turn handle. On async paths the status is queued/running and
   *   pipelineId is NULL; with $options->wait the status is the final
   *   stop status and assistantMessageIds is filled.
   *
   * @throws \InvalidArgumentException
   *   If the session does not exist.
   * @throws \RuntimeException
   *   If the session has no associated workflow, or (wait path) the
   *   execution fails — failures propagate, they are not folded into the
   *   result.
   * @throws \Drupal\flowdrop_session\Exception\ConcurrentTurnException
   *   If the session is already running a turn (HTTP: 409).
   */
  public function executeTurn(string $sessionId, string $content, TurnOptions $options = new TurnOptions()): TurnResult;

}
