<?php

namespace Limb_Chatbot\Includes\AI_Providers\Gemini\Services;

use Limb_Chatbot\Includes\Data_Objects\Chatbot;
use Limb_Chatbot\Includes\Data_Objects\Message;
use Limb_Chatbot\Includes\AI_Providers\Gemini\Utilities\Token_Utility;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Interfaces\Token_Calculator_Interface;

/**
 * Class Token_Calculator
 *
 * Calculates the token usage of a given message for the Gemini AI provider.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Gemini\Services
 * @since 1.0.0
 */
class Token_Calculator implements Token_Calculator_Interface {

	/**
	 * The message for which to calculate tokens.
	 *
	 * @var Message
	 * @since 1.0.0
	 */
	protected Message $message;

	/**
	 * Optional chatbot context, used for token calculation.
	 *
	 * @var Chatbot|null
	 * @since 1.0.0
	 */
	protected ?Chatbot $chatbot = null;

	/**
	 * Constructor.
	 *
	 * @param  Message  $message  The message to calculate tokens for.
	 * @param  Chatbot|null  $chatbot  Optional chatbot context.
	 *
	 * @since 1.0.0
	 */
	public function __construct( Message $message, ?Chatbot $chatbot = null ) {
		$this->message = $message;
		$this->chatbot = $chatbot;
	}

	/**
	 * Calculate the total number of tokens used by the message.
	 *
	 * @return int Total token count.
	 *
	 * @throws Exception If token count cannot be determined due to technical errors.
	 * @since 1.0.0
	 */
	public function calculate(): int {
		$response = ( new Token_Utility( $this->message, $this->chatbot ) )->count();
		if ( ! empty( $response->totalTokens ) ) {
			return $response->totalTokens;
		}
		throw new Exception( Error_Codes::TECHNICAL_ERROR, __( 'Technical error', 'limb-chatbot' ) );
	}
}