<?php

namespace Limb_Chatbot\Includes\Utilities;

use Limb_Chatbot\Includes\Data_Objects\AI_Model;
use Limb_Chatbot\Includes\Data_Objects\AI_Model_Meta;
use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Interfaces\Utility_Interface;

/**
 * Class AI_Model_Utility
 *
 * Utility class to handle AI model operations and configuration retrieval.
 *
 * @package Limb_Chatbot\Includes\Utilities
 *
 * @property AI_Model|null $model The AI model instance (optional).
 * @property Config|null $config The configuration related to the AI model (optional).
 * @property string|null $ai_provider_id The AI provider identifier.
 */
class AI_Model_Utility extends Utility implements Utility_Interface {


	/**
	 * The AI model instance.
	 *
	 * @var AI_Model|null
	 */
	public ?AI_Model $model = null;

	/**
	 * The configuration object.
	 *
	 * @var Config|null
	 */
	public ?Config $config = null;

	/**
	 * AI provider identifier string.
	 *
	 * @var string|null
	 */
	public ?string $ai_provider_id;

	/**
	 * Static name of the utility.
	 *
	 * @var string
	 */
	public static string $name = 'Model Utility';

	/**
	 * Constructor.
	 *
	 * Initializes the utility with optional AI model, config, and provider ID.
	 * If $ai_provider_id is null, attempts to set it from the model.
	 * If $config is null, tries to load from AI_Model_Meta based on the model's config_id.
	 *
	 * @param AI_Model|null $model Optional AI model instance.
	 * @param Config|null $config Optional configuration instance.
	 * @param string|null $ai_provider_id Optional AI provider ID.
	 */
	public function __construct( ?Ai_Model $model = null, ?Config $config = null, ?string $ai_provider_id = null ) {
		$this->model          = $model;
		$this->config         = $config;
		$this->ai_provider_id = $ai_provider_id;
		if ( is_null( $this->ai_provider_id ) ) {
			$this->ai_provider_id = $this->model ? $this->model->get_ai_provider_id() : null;
		}
		if ( ! is_null( $config ) ) {
			$this->config = $config;
		}
		if ( is_null( $this->config ) && $this->model ) {
			if ( $config_meta = AI_Model_Meta::where( [ 'ai_model_id' => $this->model->get_id(), 'meta_key' => 'config_id' ] )->first() ) {
				$this->config = Config::find( $config_meta->meta_value );
			}
		}
	}

	/**
	 * Get the AI provider ID.
	 *
	 * @return string|null AI provider identifier or null if not set.
	 */
	public function get_ai_provider_id(): ?string {
		return $this->ai_provider_id;
	}

	/**
	 * Delete the AI model using provider utility.
	 *
	 * @return bool True on successful deletion, false otherwise.
	 * @throws Exception
	 */
	public function delete(): bool {
		return $this->get_ai_provider_utility()->delete();
	}

	/**
	 * Retrieve the AI model using provider utility.
	 *
	 * @return AI_Model The retrieved AI model.
	 * @throws Exception
	 */
	public function retrieve(): AI_Model {
		return $this->get_ai_provider_utility()->retrieve();
	}

	/**
	 * List available AI models using provider utility.
	 *
	 * @return array List of AI models.
	 * @throws Exception
	 */
	public function list(): array {
		return $this->get_ai_provider_utility()->list();
	}

	/**
	 * Get the configuration instance.
	 *
	 * @return Config|null Configuration object or null if not set.
	 */
	public function get_config(): ?Config {
		return $this->config;
	}
}