<?php

namespace Limb_Chatbot\Includes\AI_Providers\Grok\Services;

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

/**
 * Class Message_Service
 *
 * Prepares message payloads for sending to xAI's Chat Completions API by formatting
 * content according to xAI's OpenAI-compatible format. Text-only support.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Grok\Services
 * @since 1.0.12
 */
class Message_Service {

	/**
	 * Transforms a message object into a structured array suitable for xAI API requests.
	 *
	 * @param  Message  $message  The message to prepare.
	 * @param  AI_Model  $model  The AI model used to validate feature support.
	 *
	 * @return array|null Returns an array with the message structure or null to skip.
	 * @throws Exception If the model does not support required features.
	 * @since 1.0.12
	 */
	public function prepare_message( Message $message, AI_Model $model ) {
		$role = $message->get_role();

		$content = Helper::maybe_json_decode( $message->get_content() );

		if ( is_array( $content ) ) {
			$processed_content = $this->process_content_array( $content, $model );

			if ( empty( $processed_content ) ) {
				return null;
			}

			return array(
				'role'    => $role,
				'content' => $processed_content,
			);
		}

		return array(
			'role'    => $role,
			'content' => is_string( $content ) ? $content : '',
		);
	}

	/**
	 * Process an array of content blocks.
	 *
	 * @param  array  $content  The content array.
	 * @param  AI_Model  $model  The AI model.
	 *
	 * @return string Processed content as string for xAI.
	 * @since 1.0.12
	 */
	private function process_content_array( array $content, AI_Model $model ): string {
		$text_parts          = array();
		$has_wc_context_text = false;
		$wc_text_parts       = array();

		foreach ( $content as $part ) {
			$type = $part['type'] ?? 'text';

			switch ( $type ) {
				case Message::CONTENT_TYPE_PARAMETER_VALUE:
				case Message::CONTENT_TYPE_PARAMETER:
					$filtered_text = apply_filters(
						"limb_chatbot_message_content_part_{$type}",
						$part['text']['value'] ?? '',
						$part
					);
					$filtered_text = is_string( $filtered_text ) ? trim( $filtered_text ) : '';
					if ( '' !== $filtered_text ) {
						$wc_text_parts[]     = $filtered_text;
						$has_wc_context_text = true;
					}
					break;

				case 'text':
					$text = $part['text']['value'] ?? $part['text'] ?? '';
					if ( ! empty( $text ) ) {
						$text_parts[] = $text;
					}
					break;

				case Message::CONTENT_TYPE_ACTION_SUBMISSION:
					$text_parts[] = $part[ Message::CONTENT_TYPE_ACTION_SUBMISSION ]['message'] ?? 'Action submitted';
					break;

				case Message::CONTENT_TYPE_ACTION_CANCELLATION:
					$text_parts[] = ! empty( $part[ Message::CONTENT_TYPE_ACTION_CANCELLATION ]['text'] )
						? $part[ Message::CONTENT_TYPE_ACTION_CANCELLATION ]['text']
						: __( 'Cancel submission of this action', 'limb-chatbot' );
					break;

				case 'attachment':
					break;

				default:
					if ( isset( $part['content'] ) && is_string( $part['content'] ) ) {
						$text_parts[] = $part['content'];
					}
					break;
			}
		}

		if ( $has_wc_context_text ) {
			return implode( "\n\n", $wc_text_parts );
		}

		return implode( "\n\n", $text_parts );
	}
}
