<?php

namespace Limb_Chatbot\Includes\AI_Providers\Open_Ai\Services;

use Limb_Chatbot\Includes\Data_Objects\AI_Model;
use Limb_Chatbot\Includes\Data_Objects\Message;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Services\Helper;

/**
 * Class Message_Service
 *
 * Prepares message payloads for sending to OpenAI's Assistant APIs by formatting mixed content types
 * like plain text and image attachments according to the capabilities of the selected model.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Open_Ai\Services
 * @since 1.0.0
 */
class Message_Service {

	/**
	 * Transforms a message object into a structured array suitable for OpenAI API requests.
	 *
	 * If the message includes attachments (like images), it will verify if the selected model supports
	 * multimodal inputs (e.g., vision). Throws an exception if unsupported image content is present.
	 *
	 * @param Message   $message The message to prepare.
	 * @param AI_Model  $model   The AI model used to validate feature support (e.g., images).
	 *
	 * @return array Returns an array with the message `role` and `content` prepared for OpenAI.
	 * @throws Exception If the model does not support images but an image is included in the message.
	 * @since 1.0.0
	 */
	public function prepare_message( Message $message, AI_Model $model ) {
		$content = Helper::maybe_json_decode( $message->get_content() );
		if ( is_array( $content ) ) {
			foreach ( $content as $index => &$part ) {
				if ( $part['type'] === Message::CONTENT_TYPE_PARAMETER || $part['type'] === Message::CONTENT_TYPE_SLACK_CONNECTION ) {
					unset( $content[ $index ] ); // Remove it entirely
					continue;
				}

				if ( $part['type'] === 'text' ) {
					if ( count( $content ) === 1 ) {
						// Plain text content case
						$content = $part['text']['value'];
						break;
					} else {
						$part['text'] = $part['text']['value'];
					}
				} elseif ( $part['type'] === 'attachment' && Helper::is_image_mime_type( $part['attachment']['mime_type'] ) ) {
					if ( ! $model->has_modality( 'image' ) ) {
						throw new Exception( Error_Codes::NOT_SUPPORTED, __( 'Does not support images', 'limb-chatbot' ) );
					}
					$part['type']             = 'image_url';
					$part['image_url']['url'] = $part['attachment']['value'];
					unset( $part['attachment'] );
				} elseif ( $part['type'] === Message::CONTENT_TYPE_ACTION_SUBMISSION ) {
					$part['type'] = 'text';
					$part['text'] = $part[ Message::CONTENT_TYPE_ACTION_SUBMISSION ]['message'] ?? 'Action submitted';
					unset( $part[ Message::CONTENT_TYPE_ACTION_SUBMISSION ] );
				} elseif ( $part['type'] === Message::CONTENT_TYPE_ACTION_CANCELLATION ) {
					$part['type'] = 'text';
					$part['text'] = ! empty( $part[ Message::CONTENT_TYPE_ACTION_CANCELLATION ]['text'] )
						? $part[ Message::CONTENT_TYPE_ACTION_CANCELLATION ]['text']
						: __( 'Cancel submission of this action', 'limb-chatbot' );
					unset( $part[ Message::CONTENT_TYPE_ACTION_CANCELLATION ] );
				} elseif ($part['type'] === Message::CONTENT_TYPE_LIVE_AGENT_DISCONNECTION){
					$part['type'] = 'text';
					$part['text'] = ! empty( $part[ Message::CONTENT_TYPE_LIVE_AGENT_DISCONNECTION ]['text'] )
						? $part[ Message::CONTENT_TYPE_LIVE_AGENT_DISCONNECTION ]['text']
						: __( 'Disconnect from live agent', 'limb-chatbot' );
					unset( $part[ Message::CONTENT_TYPE_LIVE_AGENT_DISCONNECTION ] );
				}
			}
		}

		return array(
			'role'    => $message->get_role(),
			'content' => $content,
		);
	}
}