<?php

namespace Limb_Chatbot\Includes\AI_Providers\Open_Ai\Utilities;

use Limb_Chatbot\Includes\AI_Providers\Open_Ai\Endpoints\Model_Endpoint;
use Limb_Chatbot\Includes\AI_Providers\Open_Ai\Open_Ai;
use Limb_Chatbot\Includes\Data_Objects\AI_Model;
use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Utilities\AI_Model_Utility as Global_Utility;

/**
 * Class AI_Model_Utility
 *
 * Handles AI model-related operations (list, retrieve, delete) for OpenAI integration.
 * Acts as a utility wrapper around Model_Endpoint with context-aware configuration.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Open_Ai\Utilities
 * @since 1.0.0
 */
class AI_Model_Utility {

	/**
	 * Global utility instance holding context (model, config, etc.)
	 *
	 * @var Global_Utility
	 * @since 1.0.0
	 */
	public Global_Utility $global_utility;

	/**
	 * API endpoint handler for AI model operations.
	 *
	 * @var Model_Endpoint
	 * @since 1.0.0
	 */
	public Model_Endpoint $endpoint;

	/**
	 * The current model associated with the utility context.
	 *
	 * @var AI_Model|null
	 * @since 1.0.0
	 */
	public ?AI_Model $model;

	/**
	 * OpenAI API configuration object (e.g., API key, settings).
	 *
	 * @var Config|null
	 * @since 1.0.0
	 */
	public ?Config $config = null;

	/**
	 * HTTP request timeout in seconds.
	 *
	 * @var int|null
	 * @since 1.0.0
	 */
	public ?int $timeout = 60;

	/**
	 * AI_Model_Utility constructor.
	 *
	 * Initializes the utility with global context, loads the config if not set,
	 * and instantiates the related API endpoint.
	 *
	 * @param Global_Utility $global_utility Global utility object containing model and config.
	 * @since 1.0.0
	 */
	public function __construct( Global_Utility $global_utility ) {
		$this->global_utility = $global_utility;
		if ( is_null( $this->global_utility->config ) ) {
			$this->config = Config::where( [ 'default' => true, 'related_to' => Open_Ai::class ] )->first();
		}
		$this->endpoint = new Model_Endpoint( $this );
		$this->model    = $this->global_utility->model;
	}

	/**
	 * Deletes the current AI model using the associated API endpoint.
	 *
	 * @return bool True if deletion was successful, false otherwise.
	 * @throws Exception If model is not defined.
	 * @since 1.0.0
	 */
	public function delete(): bool {
		if ( is_null( $this->model ) ) {
			throw new Exception( Error_Codes::DATA_INVALID_AI_MODEL_ARGUMENT, __( 'Model is missing', 'limb-chatbot' ) );
		}

		return $this->endpoint->delete( $this->model );
	}

	/**
	 * Lists all available AI models via the OpenAI API.
	 *
	 * @return array The list of available AI models.
	 * @throws Exception
	 * @since 1.0.0
	 */
	public function list() {
		return $this->endpoint->list();
	}

	/**
	 * Retrieves detailed information about the current model.
	 *
	 * @return AI_Model Retrieved model details.
	 * @throws Exception If model is not defined.
	 * @since 1.0.0
	 */
	public function retrieve(): AI_Model {
		if ( is_null( $this->model ) ) {
			throw new Exception( Error_Codes::DATA_INVALID_AI_MODEL_ARGUMENT, __( 'Model is missing', 'limb-chatbot' ) );
		}

		return $this->endpoint->retrieve( $this->model );
	}

	/**
	 * Gets the timeout value for OpenAI requests.
	 *
	 * @return int|null Timeout in seconds.
	 * @since 1.0.0
	 */
	public function get_timeout(): ?int {
		return $this->timeout;
	}

	/**
	 * Gets the configuration object used for OpenAI API authentication.
	 *
	 * @return Config|null Configuration object.
	 * @since 1.0.0
	 */
	public function get_config(): ?Config {
		return $this->config;
	}
}