<?php
/**
 * Channel incoming message orchestration.
 *
 * @package Niwa_AI
 */

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

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

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

	public function handle( $message, $wake_runner = true ) {
		$message = is_array( $message ) ? $message : array();
		if ( empty( $message['success'] ) ) {
			return array(
				'success' => true,
				'ignored' => true,
			);
		}

		$reaction_result = $this->call( 'handle_reaction_message', array( $message ) );
		if ( null !== $reaction_result ) {
			return $reaction_result;
		}

		$authorization = (array) $this->call(
			'authorize_channel_message',
			array( $message ),
			array(
				'handled'   => false,
				'user_role' => 'admin',
			)
		);
		if ( ! empty( $authorization['handled'] ) ) {
			return isset( $authorization['result'] ) && is_array( $authorization['result'] )
				? $authorization['result']
				: array(
					'success' => true,
					'ignored' => true,
				);
		}

		$user_role            = isset( $authorization['user_role'] ) ? (string) $authorization['user_role'] : 'admin';
		$message['user_role'] = $user_role;
		$this->call( 'remember_turn_progress_locale', array( $message ) );
		if ( 'admin' === $user_role ) {
			$this->call( 'remember_admin_delivery_origin', array( $message ) );
		}

		$preprocessor = $this->call( 'get_message_preprocessor' );
		$media_kinds  = $preprocessor && method_exists( $preprocessor, 'media_kinds' ) ? $preprocessor->media_kinds( $message ) : array();
		$this->debug(
			'incoming_message',
			array(
				'chat_id'          => isset( $message['chat_id'] ) ? (string) $message['chat_id'] : '',
				'message_id'       => isset( $message['message_id'] ) ? intval( $message['message_id'] ) : 0,
				'update_id'        => isset( $message['update_id'] ) ? intval( $message['update_id'] ) : 0,
				'channel'          => isset( $message['channel'] ) ? sanitize_key( (string) $message['channel'] ) : '',
				'user_role'        => $user_role,
				'language_code'    => isset( $message['language_code'] ) ? (string) $message['language_code'] : '',
				'callback'         => ! empty( $message['callback_query_id'] ),
				'kind'             => isset( $message['kind'] ) ? (string) $message['kind'] : '',
				'media_kinds'      => $media_kinds,
				'is_album'         => ! empty( $message['is_album'] ),
				'album_size'       => intval( $message['album_size'] ?? 0 ),
				'is_text_fragment' => ! empty( $message['is_text_fragment'] ),
				'is_edited'        => ! empty( $message['is_edited'] ),
				'is_forwarded'     => ! empty( $message['forward']['is_forwarded'] ),
				'has_caption'      => '' !== trim( (string) ( $message['caption'] ?? '' ) ),
				'text_preview'     => isset( $message['text'] ) ? (string) $message['text'] : '',
			)
		);

		if ( $preprocessor && method_exists( $preprocessor, 'apply_stock_manager_media_policy' ) ) {
			$message = $preprocessor->apply_stock_manager_media_policy( $message );
		}

		$gates       = $this->call( 'get_message_gates' );
		$gate_result = $gates && method_exists( $gates, 'before_actor_intake' )
			? $gates->before_actor_intake( $message )
			: array( 'handled' => false );
		if ( ! empty( $gate_result['handled'] ) ) {
			return isset( $gate_result['result'] ) && is_array( $gate_result['result'] )
				? $gate_result['result']
				: array(
					'success' => true,
					'ignored' => true,
				);
		}

		$actor_intake = $this->call( 'get_actor_intake' );
		return $actor_intake && method_exists( $actor_intake, 'enqueue' )
			? $actor_intake->enqueue( $message, $wake_runner, ! empty( $gate_result['callback_acknowledged'] ) )
			: array(
				'success' => false,
				'error'   => 'actor_intake_unavailable',
				'reply'   => '',
			);
	}

	private function debug( $event, $context = array() ) {
		$this->call( 'debug_logger', array( $event, $context ) );
	}

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