<?php
/**
 * Message Service for DeepSeek AI Provider.
 *
 * Prepares message payloads for sending to DeepSeek's Chat Completion API
 * by formatting mixed content types according to the API requirements.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Deep_Seek\Services
 * @since  1.0.9
 */

namespace Limb_Chatbot\Includes\AI_Providers\Deep_Seek\Services;

use Limb_Chatbot\Includes\Data_Objects\Message;
use Limb_Chatbot\Includes\Services\Helper;

/**
 * Class Message_Service
 *
 * Transforms Message objects into the format required by DeepSeek's API.
 * DeepSeek API is OpenAI-compatible but text-only (no image/audio support).
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Deep_Seek\Services
 * @since  1.0.9
 */
class Message_Service {

	/**
	 * Transforms a message object into a structured array suitable for DeepSeek API requests.
	 *
	 * DeepSeek API only supports text content, so images and attachments are skipped.
	 * The method extracts text from various content types and formats them appropriately.
	 *
	 * @param Message $message The message to prepare.
	 *
	 * @return array Returns an array with the message `role` and `content` prepared for DeepSeek.
	 * @since  1.0.0
	 */
	public function prepare_message( Message $message ): array {
		$content = Helper::maybe_json_decode( $message->get_content() );

		// If content is already a string, return directly.
		if ( is_string( $content ) ) {
			return array(
				'role'    => $message->get_role(),
				'content' => $content,
			);
		}

		// Process array content - extract text parts only (DeepSeek is text-only).
		if ( is_array( $content ) ) {
			$text_parts = $this->extract_text_from_content( $content );
			$content    = ! empty( $text_parts ) ? implode( "\n", $text_parts ) : '';
		}

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

	/**
	 * Extracts text content from a mixed content array.
	 *
	 * Processes various content types and converts them to plain text.
	 * Skips non-text content types like images and attachments since
	 * DeepSeek API does not support multimodal input.
	 *
	 * @param array $content The content array to process.
	 *
	 * @return array Array of extracted text strings.
	 * @since  1.0.0
	 */
	private function extract_text_from_content( array $content ): array {
		$text_parts = array();

		foreach ( $content as $part ) {
			if ( ! is_array( $part ) || ! isset( $part['type'] ) ) {
				continue;
			}

			$extracted_text = $this->extract_text_from_part( $part );
			if ( ! empty( $extracted_text ) ) {
				$text_parts[] = $extracted_text;
			}
		}

		return $text_parts;
	}

	/**
	 * Extracts text from a single content part based on its type.
	 *
	 * @param array $part The content part to process.
	 *
	 * @return string|null The extracted text or null if not applicable.
	 * @since  1.0.0
	 */
	private function extract_text_from_part( array $part ): ?string {
		switch ( $part['type'] ) {
			case 'text':
				return $part['text']['value'] ?? null;

			case Message::CONTENT_TYPE_ACTION_SUBMISSION:
				return $part[ Message::CONTENT_TYPE_ACTION_SUBMISSION ]['message'] ?? __( 'Action submitted', 'limb-chatbot' );

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

			case Message::CONTENT_TYPE_LIVE_AGENT_DISCONNECTION:
				return ! empty( $part[ Message::CONTENT_TYPE_LIVE_AGENT_DISCONNECTION ]['text'] )
					? $part[ Message::CONTENT_TYPE_LIVE_AGENT_DISCONNECTION ]['text']
					: __( 'Disconnect from live agent', 'limb-chatbot' );

			// Skip these content types - DeepSeek doesn't support them.
			case Message::CONTENT_TYPE_PARAMETER:
			case Message::CONTENT_TYPE_SLACK_CONNECTION:
			case 'attachment':
				return null;

			default:
				return null;
		}
	}
}

