<?php
/**
 * Actor message preparation before execution.
 *
 * @package Niwa_AI
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Niwa_AI_Admin_Autonomy_Actor_Message_Preparer {
	/** @var object|null */
	private $telegram;

	/** @var array<string,callable> */
	private $callbacks;

	public function __construct( $telegram = null, $callbacks = array() ) {
		$this->telegram  = $telegram;
		$this->callbacks = is_array( $callbacks ) ? $callbacks : array();
	}

	public function prepare( $message ) {
		$message = is_array( $message ) ? $message : array();
		$message = $this->call( 'apply_stock_manager_media_policy', array( $message ), $message );

		$message = $this->apply_skill_import_ref( $message );
		$message = $this->apply_spreadsheet_ref( $message );

		$media_count = isset( $message['media_refs'] ) && is_array( $message['media_refs'] ) ? count( $message['media_refs'] ) : 0;
		for ( $i = 0; $i < $media_count; $i++ ) {
			$voice_ref = $this->call( 'find_first_voice_ref', array( $message ), null );
			if ( null === $voice_ref ) {
				break;
			}
			$prepared = $this->apply_voice_ref( $message, $voice_ref );
			if ( ! empty( $prepared['handled'] ) || empty( $prepared['message'] ) ) {
				return $prepared;
			}
			$message = $prepared['message'];
		}

		return array(
			'success' => true,
			'message' => $message,
		);
	}

	private function apply_skill_import_ref( $message ) {
		$skill_doc_ref = $this->call( 'find_first_skill_document_ref', array( $message ), null );
		if ( null === $skill_doc_ref ) {
			return $message;
		}

		$file_name = (string) ( $skill_doc_ref['file_name'] ?? '' );
		if ( $this->telegram && method_exists( $this->telegram, 'download_inbound_media' ) ) {
			$dl = $this->telegram->download_inbound_media( $skill_doc_ref );
			if ( ! empty( $dl['success'] ) && ! empty( $dl['path'] ) && is_readable( $dl['path'] ) ) {
				$body = @file_get_contents( $dl['path'] );
				if ( false !== $body ) {
					$extension = strtolower( pathinfo( $file_name, PATHINFO_EXTENSION ) );
					if ( 'zip' === $extension ) {
						$message['skill_import_archive_base64'] = base64_encode( (string) $body );
					} else {
						$message['skill_import_content'] = (string) $body;
					}
					$message['skill_import_filename'] = $file_name;
				}
				@unlink( $dl['path'] );
			}
		}

		$current_text    = trim( (string) ( $message['text'] ?? '' ) );
		$current_caption = trim( (string) ( $message['caption'] ?? '' ) );
		if ( '' === $current_text && '' === $current_caption ) {
			$message['text']        = 'Importuj prilozen skill fajl: ' . $file_name;
			$message['remember_as'] = '[skill import: ' . $file_name . ']';
		}

		return $message;
	}

	private function apply_spreadsheet_ref( $message ) {
		$spreadsheet_ref = $this->call( 'find_first_spreadsheet_ref', array( $message ), null );
		if ( null === $spreadsheet_ref ) {
			return $message;
		}

		$message['spreadsheet_file_id']  = (string) $spreadsheet_ref['file_id'];
		$message['spreadsheet_filename'] = (string) ( $spreadsheet_ref['file_name'] ?? '' );
		$current_text = trim( (string) ( $message['text'] ?? '' ) );
		if ( '' === $current_text ) {
			$message['text']        = 'Procitaj prilozen fajl sa cenama: ' . $message['spreadsheet_filename'];
			$message['remember_as'] = '[spreadsheet: ' . $message['spreadsheet_filename'] . ']';
		}

		return $message;
	}

	private function apply_voice_ref( $message, $voice_ref ) {
		$this->send_typing_indicator( $message );

		$voice_result = $this->call( 'transcribe_voice_message', array( $voice_ref ), array() );
		if ( ! empty( $voice_result['success'] ) && '' !== trim( (string) $voice_result['text'] ) ) {
			$transcript = trim( (string) $voice_result['text'] );
			$current    = trim( (string) ( $message['text'] ?? '' ) );
			$message['text']        = '' === $current
				? $transcript
				: $current . "\n\n<audio_transcript>\n" . $transcript . "\n</audio_transcript>";
			$message['remember_as'] = '[voice] ' . $message['text'];
			$message                = $this->mark_audio_ref_transcribed( $message, $voice_ref, $transcript );

			return array(
				'success' => true,
				'message' => $message,
			);
		}

		$error_detail = isset( $voice_result['error'] ) ? (string) $voice_result['error'] : 'Nepoznata greska';
		if ( '' !== trim( (string) ( $message['text'] ?? '' ) ) ) {
			return array(
				'success' => true,
				'message' => $this->mark_audio_ref( $message, $voice_ref, 'audio_transcription_error', $error_detail ),
			);
		}
		$reply        = 'Nisam uspela da transkribujem glasovnu poruku: ' . $error_detail
			. "\n\nPosalji poruku ponovo kao tekst ili pokusaj ponovo.";

		$this->send_reply( $message, $reply );
		if ( ! empty( $message['chat_id'] ) ) {
			$this->call( 'remember_exchange', array( $message['chat_id'], '[voice message - transcription failed]', $reply ) );
		}

		return array(
			'success' => true,
			'handled' => true,
			'reply'   => $reply,
		);
	}

	private function mark_audio_ref_transcribed( $message, $voice_ref, $transcript ) {
		return $this->mark_audio_ref( $message, $voice_ref, 'audio_transcript', $transcript );
	}

	private function mark_audio_ref( $message, $voice_ref, $field, $value ) {
		if ( empty( $message['media_refs'] ) || ! is_array( $message['media_refs'] ) ) {
			return $message;
		}

		foreach ( $message['media_refs'] as &$ref ) {
			if (
				! is_array( $ref )
				|| (string) ( $ref['file_id'] ?? '' ) !== (string) ( $voice_ref['file_id'] ?? '' )
				|| array_key_exists( 'audio_transcript', $ref )
				|| array_key_exists( 'audio_transcription_error', $ref )
			) {
				continue;
			}
			$ref[ $field ] = $value;
			break;
		}
		unset( $ref );

		return $message;
	}

	private function send_typing_indicator( $message ) {
		$chat_id = isset( $message['chat_id'] ) ? (string) $message['chat_id'] : '';
		if ( '' === trim( $chat_id ) ) {
			return;
		}

		if ( isset( $this->callbacks['send_typing_indicator'] ) && is_callable( $this->callbacks['send_typing_indicator'] ) ) {
			$this->call( 'send_typing_indicator', array( $chat_id ), false );
			return;
		}

		$channel = isset( $message['channel'] ) ? sanitize_key( (string) $message['channel'] ) : 'telegram';
		if ( 'whatsapp' !== $channel && $this->telegram && method_exists( $this->telegram, 'send_chat_action' ) ) {
			$this->telegram->send_chat_action( $chat_id, 'typing' );
		}
	}

	private function send_reply( $message, $reply ) {
		$chat_id = isset( $message['chat_id'] ) ? (string) $message['chat_id'] : '';
		if ( '' === trim( $chat_id ) ) {
			return;
		}

		$channel     = isset( $message['channel'] ) ? sanitize_key( (string) $message['channel'] ) : 'telegram';
		$message_id  = isset( $message['message_id'] ) ? intval( $message['message_id'] ) : 0;
		if ( 'telegram' !== $channel && isset( $this->callbacks['send_channel_message'] ) && is_callable( $this->callbacks['send_channel_message'] ) ) {
			$this->call( 'send_channel_message', array( $channel, $chat_id, $reply, $message_id, array(), $message ), array() );
			return;
		}

		if ( $this->telegram && method_exists( $this->telegram, 'send_message' ) ) {
			$this->telegram->send_message( $chat_id, $reply, $message_id );
		}
	}

	private function call( $name, $args = array(), $default = null ) {
		return Niwa_AI_Admin_Autonomy_Callbacks::call( $this->callbacks, $name, $args, $default );
	}
}
