<?php

namespace Limb_Chatbot\Includes\AI_Providers\Open_Ai\Utilities;

use Limb_Chatbot\Includes\Data_Objects\Chatbot;
use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\AI_Providers\Open_Ai\Endpoints\Assistant_Endpoint;
use Limb_Chatbot\Includes\Exceptions\Exception;
use ReflectionClass;

/**
 * Class Assistant_Utility
 *
 * Provides utility methods for accessing and modifying assistant-related settings and configuration.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Open_Ai\Utilities
 * @since 1.0.0
 */
class Assistant_Utility {

	/**
	 * The external ID of the assistant (OpenAI assistant ID).
	 *
	 * @var string|null
	 * @since 1.0.0
	 */
	public $assistant_external_id;

	/**
	 * Configuration ID used to retrieve the API key and other settings.
	 *
	 * @var int|string|null
	 * @since 1.0.0
	 */
	public $config_id;

	/**
	 * Default system message for the assistant.
	 *
	 * @var string|null
	 * @since 1.0.0
	 */
	public $system_message;

	/**
	 * The chatbot instance this utility operates on.
	 *
	 * @var Chatbot
	 * @since 1.0.0
	 */
	private Chatbot $chatbot;

	/**
	 * Assistant_Utility constructor.
	 *
	 * Initializes the utility and populates properties from the chatbot.
	 *
	 * @param Chatbot $chatbot The chatbot object with parameters.
	 * @since 1.0.0
	 */
	public function __construct( Chatbot $chatbot ) {
		$this->chatbot = $chatbot;
		$this->populate_properties();
	}


	/**
	 * Populates public properties dynamically using chatbot parameters.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function populate_properties() {
		$reflection = new ReflectionClass( $this );
		$properties = $reflection->getProperties();
		foreach ( $properties as $property ) {
			$property_name = $property->getName();
			if ( ! isset( $this->{$property_name} ) ) {
				$this->{$property_name} = $this->chatbot->get_parameter( $property_name );
			}
		}
	}

	/**
	 * Gets the assistant external ID.
	 *
	 * @return string|null
	 * @since 1.0.0
	 */
	public function get_assistant_external_id() {
		return $this->assistant_external_id;
	}

	/**
	 * Triggers a modification on the assistant via its endpoint.
	 *
	 * @return mixed
	 * @throws Exception
	 * @since 1.0.0
	 */
	public function modify() {
		return $this->get_endpoint_instance()->modify();
	}

	/**
	 * Returns an instance of the Assistant_Endpoint for performing API operations.
	 *
	 * @return Assistant_Endpoint
	 * @since 1.0.0
	 */
	public function get_endpoint_instance() {
		return ( new Assistant_Endpoint( $this ) );
	}

	/**
	 * Retrieves the configuration object associated with this assistant.
	 *
	 * @return Config|null
	 * @since 1.0.0
	 */
	public function get_config() {
		return Config::find( $this->get_config_id() );
	}

	/**
	 * Gets the configuration ID.
	 *
	 * @return int|string|null
	 * @since 1.0.0
	 */
	public function get_config_id() {
		return $this->config_id;
	}

	/**
	 * Gets the timeout value for requests.
	 *
	 * @return int
	 * @since 1.0.0
	 */
	public function get_timeout() {
		return $this->timeout ?? 60;
	}

	/**
	 * Returns the default system message associated with this assistant.
	 *
	 * @return string|null
	 * @since 1.0.0
	 */
	public function get_system_message() {
		return $this->system_message;
	}
}