<?php

namespace Limb_Chatbot\Includes\Services;

use Exception;
use Limb_Chatbot\Includes\Data_Objects\Chat;
use Limb_Chatbot\Includes\Data_Objects\Chatbot;
use Limb_Chatbot\Includes\Data_Objects\Message;
use Limb_Chatbot\Includes\Utilities\Copilot_Utility;

/**
 * Service class for managing per-chat language metadata.
 *
 * Encapsulates reading and writing the detected user language for a chat so
 * other services (system message generators, copilot utilities, etc.) can
 * reuse a single, stable source of truth.
 *
 * @since 1.0.8
 */
class Chat_Language_Service {

	/**
	 * Meta key used to persist chat language information.
	 *
	 * @var string
	 * @since 1.0.8
	 */
	const META_KEY = 'language';

	/**
	 * Detect the primary language of a user message text.
	 *
	 * This method is intentionally lightweight and does not call any external
	 * services. It relies on Unicode script inspection and, if ambiguous,
	 * falls back to the site locale. The result can be filtered externally.
	 *
	 * @param  Chatbot  $chatbot
	 * @param  Chat  $chat
	 * @param  Message  $message
	 *
	 * @return void Array with 'code' and 'label', or null if detection fails.
	 * @since 1.0.8
	 */
	public static function detect_language( Chatbot $chatbot, Chat $chat, Message $message ) {
		try {
			if ( $message->get_role() !== Message::ROLE_USER ) {
				return;
			}
			$text = trim( $message->extract_text() );
			if ( $text === '' ) {
				return;
			}

			$copilot_utility = new Copilot_Utility( $chatbot->get_ai_model(), $chatbot->get_config() );

			$language_message = $copilot_utility->detect_language( $text );
			if ( $language_message instanceof Message ) {
				$language = trim( $language_message->extract_text() );
				$chat->update_meta( self::META_KEY, $language );
			}
		} catch ( Exception $e ) {
			Helper::log( $e );

			return;
		}
	}

	/**
	 * Appends a language-specific directive to the system message.
	 *
	 * This directive instructs the AI to always respond in the user's preferred
	 * language, which is previously detected and stored in chat meta. If the
	 * language is not available or no active chat is present, the system message
	 * is returned unchanged.
	 *
	 * @param  string  $system_message  The original system message provided by the AI generator.
	 *
	 * @return string  The updated system message including the language directive.
	 *
	 * @since 1.0.8
	 */
	public function add_language_directive( string $system_message ): string {
		// Get current chat from context
		$chat = Chat_Context::instance()->get_chat();

		if ( ! $chat instanceof Chat ) {
			return $system_message; // no active chat → do nothing
		}

		// Get stored language meta
		$language = $this->get_language( $chat );

		if ( empty( $language ) ) {
			return $system_message; // language not detected → do nothing
		}

		// Build directive text
		$directive = sprintf(
			"\n\n[LANGUAGE DIRECTIVE]\nThe user's preferred language is **%s**.\n" .
			"Respond in this language unless explicitly asked otherwise.\n",
			esc_html( $language )
		);

		/**
		 * Allow 3rd parties to extend or override the language directive.
		 */
		$directive = apply_filters( 'lbaic_language_directive', $directive, $language, $chat );

		// Append directive to existing system message
		return rtrim( $system_message ) . "\n" . $directive;
	}

	/**
	 * Retrieve the stored language information for a chat.
	 * or null if no language meta is stored.
	 *
	 * @param  Chat  $chat  Chat instance.
	 *
	 * @return array|null
	 * @since 1.0.8
	 */
	public function get_language( Chat $chat ): ?string {
		return $chat->get_meta( self::META_KEY );
	}

	/**
	 * Appends a language-specific directive to the system message.
	 *
	 * This directive instructs the AI to always respond in the user's preferred
	 * language, which is previously detected and stored in chat meta. If the
	 * language is not available or no active chat is present, the system message
	 * is returned unchanged.
	 *
	 * @param  string  $system_message  The original system message provided by the AI generator.
	 *
	 * @return string  The updated system message including the language directive.
	 *
	 * @since 1.0.8
	 */
	public function add_main_language_directive( string $system_message ): string {
		// Get current chat from context
		$chat = Chat_Context::instance()->get_chat();

		if ( ! $chat instanceof Chat ) {
			return $system_message; // no active chat → do nothing
		}

		// Get stored language meta
		$language = $this->get_language( $chat );

		if ( empty( $language ) ) {
			return $system_message; // language not detected → do nothing
		}

		$directive = sprintf(
			"\n\n## Language Rules ##\nThe user's preferred language is **%s**.\n" .
			"Respond always in this language unless explicitly asked otherwise.\n" .
			"Translate any internal knowledge into the **%s** language",
			esc_html( $language ),
			esc_html( $language )
		);

		/**
		 * Allow 3rd parties to extend or override the language directive.
		 */
		$directive = apply_filters( 'lbaic_language_directive', $directive, $language, $chat );

		return rtrim( $system_message ) . "\n" . $directive;
	}
}


