<?php
/**
 * Copilot Utility for DeepSeek AI Provider.
 *
 * Provides AI-assisted features like Q&A generation, conversation analysis,
 * and action parameter collection using the DeepSeek Chat Completion API.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Deep_Seek\Utilities
 * @since  1.0.9
 */

namespace Limb_Chatbot\Includes\AI_Providers\Deep_Seek\Utilities;

use Limb_Chatbot\Includes\AI_Providers\Deep_Seek\Deep_Seek;
use Limb_Chatbot\Includes\AI_Providers\Deep_Seek\Endpoints\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;

/**
 * Class Copilot_Utility
 *
 * Utility class for managing copilot operations using the DeepSeek provider.
 * Provides methods for AI-assisted features that require simple text generation.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Deep_Seek\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.0
	 */
	public ?Config $config;

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

	/**
	 * Timeout duration in seconds for API requests.
	 *
	 * @var int|null
	 * @since 1.0.0
	 */
	public ?int $timeout = 60;

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

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

	/**
	 * Constructor.
	 *
	 * Initializes the utility with a global utility instance, sets the default config if missing,
	 * and initializes the chat completion endpoint.
	 *
	 * @param Global_Utility $global_utility Global copilot utility instance.
	 *
	 * @since 1.0.0
	 */
	public function __construct( Global_Utility $global_utility ) {
		$this->global_utility = $global_utility;

		// Set default config if not provided.
		if ( is_null( $this->global_utility->config ) ) {
			$this->config = Config::where( array(
				'default'    => true,
				'related_to' => Deep_Seek::class,
			) )->first();
		} else {
			$this->config = $this->global_utility->config;
		}

		$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.0
	 */
	public function get_config(): ?Config {
		return $this->config;
	}

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

	/**
	 * Determines if vector search is applicable for the given messages.
	 *
	 * Sends a collection of messages to the AI model to determine if
	 * RAG context retrieval would be beneficial for the response.
	 *
	 * @param Collection|array $messages Messages or collection of messages to process.
	 *
	 * @return Message The AI-generated response message.
	 * @throws Exception If the request fails.
	 * @since  1.0.0
	 */
	public function is_vector_search_applicable( $messages ): Message {
		return $this->endpoint->is_vector_search_applicable( $messages );
	}

	/**
	 * Analyzes a single conversation turn using the configured endpoint.
	 *
	 * @param Collection|array $messages Array of Message objects representing the current conversation turn.
	 *
	 * @return array The result of the analysis from the endpoint as JSON.
	 * @throws Exception If the request fails.
	 * @since  1.0.0
	 */
	public function analyze_turn( $messages ): array {
		// Use a smaller model for cost efficiency if available.
		$this->ai_model = AI_Model::find_by_name( 'deepseek-chat' ) ?? null;

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

	/**
	 * Generates a question for data collection during action parameter gathering.
	 *
	 * 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 Collection|array $messages Collection of Message objects for the AI.
	 *
	 * @return Message The generated text response.
	 * @throws Exception If the request fails.
	 * @since  1.0.0
	 */
	public function generate_data_collect_question( $messages, $stream = false ): Message {
		return $this->endpoint->generate_data_collect_question( $messages, $stream );
	}

	/**
	 * Generates a success message for action completion.
	 *
	 * Creates a warm, celebratory message for users after they complete an action.
	 * Delegates to the endpoint to call the AI provider.
	 *
	 * @param Collection|array $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.0
	 */
	public function generate_action_success_message( $messages, $stream = false ): Message {
		return $this->endpoint->generate_action_success_message( $messages, $stream );
	}

	/**
	 * Generates an action success message with extracted variables context.
	 *
	 * Creates a beautiful success message that includes information from extracted variables.
	 *
	 * @param Collection|array $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.0
	 */
	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 ) {
		return $this->endpoint->rerank( $messages );
	}


	public function generate_json_message_for_rerank( $messages ) {
		return $this->endpoint->generate_rerank_json_message( $messages );
	}

	public function generate_json_message( $messages ) {
		return $this->endpoint->generate_json_message($messages);
	}
}

