<?php

namespace Limb_Chatbot\Includes\AI_Providers\Claude\Utilities;

use Limb_Chatbot\Includes\AI_Providers\Claude\Claude;
use Limb_Chatbot\Includes\AI_Providers\Claude\Endpoints\Chat_Completion\Chat_Completion_Endpoint;
use Limb_Chatbot\Includes\Data_Objects\AI_Model;
use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\Data_Objects\Message;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Services\Collection;
use Limb_Chatbot\Includes\Utilities\Copilot_Utility as Global_Utility;

/**
 * Utility class for managing copilot operations using the Claude AI provider.
 *
 * Provides methods for generating AI-powered questions and messages
 * in the context of chatbot actions and data collection.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Claude\Utilities
 * @since 1.0.9
 */
class Copilot_Utility {

	/**
	 * Configuration object associated with this utility.
	 *
	 * May be null if no configuration is found or set.
	 *
	 * @var Config|null
	 * @since 1.0.9
	 */
	public ?Config $config;

	/**
	 * Global copilot utility instance for shared operations.
	 *
	 * @var Global_Utility
	 * @since 1.0.9
	 */
	public Global_Utility $global_utility;

	/**
	 * Timeout duration in seconds for the request.
	 *
	 * @var int|null
	 * @since 1.0.9
	 */
	public ?int $timeout = 60;

	/**
	 * AI model to use for copilot operations.
	 *
	 * @var AI_Model|null
	 * @since 1.0.9
	 */
	public ?AI_Model $ai_model = null;

	/**
	 * Endpoint instance handling API calls.
	 *
	 * @var Chat_Completion_Endpoint
	 * @since 1.0.9
	 */
	public Chat_Completion_Endpoint $endpoint;

	/**
	 * Constructor.
	 *
	 * Initializes the utility with a global utility instance, sets the default config if missing,
	 * and initializes the messages endpoint.
	 *
	 * @param  Global_Utility  $global_utility  Global copilot utility instance.
	 *
	 * @since 1.0.9
	 */
	public function __construct( Global_Utility $global_utility ) {
		$this->global_utility = $global_utility;
		if ( is_null( $this->global_utility->config ) ) {
			$this->config = Config::where( array( 'default' => true, 'related_to' => Claude::$id ) )->first();
		} else {
			$this->config = $this->global_utility->config;
		}
		$this->ai_model = $this->global_utility->ai_model;
		$this->endpoint = new Chat_Completion_Endpoint( $this );
	}

	/**
	 * Returns the configuration object used by this utility.
	 *
	 * @return Config|null Configuration object or null if not set.
	 * @since 1.0.9
	 */
	public function get_config(): ?Config {
		return $this->config;
	}

	/**
	 * Timeout duration in seconds for the copilot operation.
	 *
	 * @return int|null
	 * @since 1.0.9
	 */
	public function get_timeout(): ?int {
		return $this->timeout;
	}

	/**
	 * Get the AI model.
	 *
	 * @return AI_Model|null
	 * @since 1.0.9
	 */
	public function get_ai_model(): ?AI_Model {
		return $this->ai_model ?? $this->global_utility->ai_model;
	}

	/**
	 * Proxy method to check if vector search is applicable.
	 *
	 * @param  mixed  $messages  Messages or collection of messages to process.
	 *
	 * @return Message The result from the endpoint.
	 * @throws Exception If the request fails.
	 * @since 1.0.9
	 */
	public function is_vector_search_applicable( $messages ) {
		return $this->endpoint->is_vector_search_applicable( $messages );
	}

	/**
	 * Analyze a single conversation turn using the configured endpoint.
	 *
	 * @param  array  $messages  Array of Message objects representing the current conversation turn.
	 *
	 * @return array The result of the analysis from the endpoint.
	 * @throws Exception If the request fails.
	 * @since 1.0.9
	 */
	public function analyze_turn( $messages ) {
		return $this->endpoint->analyze_turn( $messages );
	}

	/**
	 * Generate simple text response from AI using the configured endpoint.
	 *
	 * This method is used to generate straightforward text responses based on
	 * the provided messages. It extracts just the text content from the AI's response.
	 *
	 * @param  mixed  $messages  Collection or array of Message objects for the AI.
	 *
	 * @return Message The generated text response.
	 * @throws Exception If the request fails.
	 * @since 1.0.9
	 */
	public function generate_data_collect_question( $messages, $stream = false ): Message {
		return $this->endpoint->generate_data_collect_question( $messages, $stream );
	}

	/**
	 * Generate a beautiful success message for action completion.
	 *
	 * Generates a warm, celebratory message based on the action context.
	 * Delegates to the endpoint to call the AI provider.
	 *
	 * @param  Collection  $messages  Collection of Message objects with system and user prompts.
	 *
	 * @return Message The generated success message.
	 * @throws Exception If message generation fails.
	 * @since 1.0.9
	 */
	public function generate_action_success_message( $messages, $stream = false ): Message {
		return $this->endpoint->generate_action_success_message( $messages, $stream );
	}

	/**
	 * Generate action success message with extracted variables context.
	 *
	 * Creates a beautiful success message that includes information from extracted variables.
	 *
	 * @param  Collection  $messages  Collection of Message objects with context and variables.
	 *
	 * @return Message The generated success message with extracted variables.
	 * @throws Exception If message generation fails.
	 * @since 1.0.9
	 */
	public function generate_action_success_message_with_context( $messages, $stream = false ): Message {
		return $this->endpoint->generate_action_success_message( $messages, $stream );
	}

	/**
	 * Rerank a list of messages using the configured endpoint.
	 *
	 * This method sends the messages to the endpoint for reranking based on relevance or other criteria.
	 *
	 * @param  array  $messages  Array of Message objects to be reranked.
	 *
	 * @return null|Message The reranked list of messages from the endpoint.
	 * @throws Exception If the request fails.
	 * @since 1.0.9
	 */
	public function rerank( $messages ) {
		$this->ai_model = AI_Model::find_by_name( 'claude-haiku-4-5' ) ?? null;

		return $this->endpoint->rerank( $messages );
	}
}

