<?php
/**
 * Chatbot tool continuation payload builder.
 *
 * @package KimaAI\ChatBot\Tools
 */

declare(strict_types=1);

namespace KimaAI\ChatBot\Tools;

defined('ABSPATH') || exit;

/**
 * Builds provider-specific follow-up payloads after tool output.
 */
final class ToolContinuationBuilder {

  /**
   * Build a non-streaming continuation payload.
   *
   * @param string $provider Active AI provider.
   * @param array $base_payload Original provider payload.
   * @param array $current Current provider response.
   * @param array $outputs Function call output items.
   * @param array $history OpenRouter conversation history.
   * @return array{payload: array, history: array}
   */
  public function build(string $provider, array $base_payload, array $current, array $outputs, array $history = []): array {
    $next = [];

    foreach (['model', 'max_output_tokens', 'temperature', 'top_p', 'text', 'reasoning', 'metadata'] as $key) {
      if (array_key_exists($key, $base_payload)) {
        $next[$key] = $base_payload[$key];
      }
    }

    if (!empty($base_payload['tools'])) {
      $next['tools'] = $base_payload['tools'];
    }

    $next['tool_choice'] = 'auto';

    if (isset($base_payload['parallel_tool_calls'])) {
      $next['parallel_tool_calls'] = $base_payload['parallel_tool_calls'];
    }

    if ($provider === 'openrouter') {
      $history = array_merge(
        $history,
        $this->normalizeContinuationItems($provider, $current['output'] ?? []),
        $this->normalizeContinuationItems($provider, $outputs)
      );

      $next['input'] = $history;

      return [
        'payload' => $next,
        'history' => $history,
      ];
    }

    $next['previous_response_id'] = (string) ($current['id'] ?? '');
    $next['input'] = $this->normalizeContinuationItems($provider, $outputs);

    return [
      'payload' => $next,
      'history' => $history,
    ];
  }

  /**
   * Build a continuation from the current streaming provider payload.
   *
   * @param string $provider Active AI provider.
   * @param array $provider_payload Current provider payload.
   * @param array $completed Completed provider response.
   * @param array $outputs Function call output items.
   * @return array{payload: array, history: array}
   */
  public function buildStreaming(string $provider, array $provider_payload, array $completed, array $outputs): array {
    $next = $provider_payload;

    if ($provider === 'openrouter') {
      $history = array_merge(
        is_array($provider_payload['input'] ?? null) ? $provider_payload['input'] : [],
        $this->normalizeContinuationItems($provider, $completed['output'] ?? []),
        $this->normalizeContinuationItems($provider, $outputs)
      );

      unset($next['previous_response_id']);
      $next['input'] = $history;
    }
    else {
      $history = [];
      $next['previous_response_id'] = (string) ($completed['id'] ?? '');
      $next['input'] = $this->normalizeContinuationItems($provider, $outputs);
    }

    $next['tool_choice'] = 'auto';

    return [
      'payload' => $next,
      'history' => $history,
    ];
  }

  /**
   * Safety: never send synthetic item ids to OpenAI/Ollama continuation input.
   *
   * @param string $provider Active AI provider.
   * @param array $items Response or output items.
   * @return array
   */
  public function normalizeContinuationItems(string $provider, array $items): array {
    $clean = [];

    foreach ($items as $item) {
      if (!is_array($item)) {
        continue;
      }

      if ($provider !== 'openrouter') {
        unset($item['id']);
      }

      $clean[] = $item;
    }

    return $clean;
  }
}
