<?php

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

class Niwa_AI_Admin_Autonomy_Telegram_Ingress {

    /** @var Niwa_AI_Admin_Autonomy_Telegram|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 handle_webhook_request( WP_REST_Request $request ) {
        if ( ! $this->telegram || ! $this->telegram->is_enabled() ) {
            return new WP_REST_Response(
                array(
                    'success' => false,
                    'error'   => 'telegram_disabled',
                ),
                403
            );
        }

        $runner_state = $this->telegram->get_runner_state();
        $secret       = isset( $runner_state['secret'] ) ? (string) $runner_state['secret'] : '';
        $header       = trim( (string) $request->get_header( 'x-telegram-bot-api-secret-token' ) );
        if ( '' === $secret || '' === $header || ! hash_equals( $secret, $header ) ) {
            return new WP_REST_Response(
                array(
                    'success' => false,
                    'error'   => 'forbidden',
                ),
                403
            );
        }

        if ( method_exists( $this->telegram, 'mark_webhook_delivery' ) ) {
            $this->telegram->mark_webhook_delivery();
        }

        $update = $request->get_json_params();
        if ( ! is_array( $update ) ) {
            $update = array();
        }

        try {
            $result = $this->process_webhook_update( $update );
        } catch ( Throwable $e ) {
            $this->log(
                'telegram_webhook_exception',
                array(
                    'error' => $this->format_exception( $e ),
                )
            );
            $result = array(
                'success' => false,
                'webhook' => true,
                'error'   => 'webhook_processing_exception',
            );
        }

        return new WP_REST_Response( $result, 200 );
    }

    public function process_webhook_update( $update ) {
        $message = $this->telegram ? $this->telegram->extract_message_payload( $update ) : array();
        $result  = (array) $this->call( 'process_extracted_message', array(), array( $message, true ) );

        $dispatch_result = isset( $result['runner_dispatch'] ) && is_array( $result['runner_dispatch'] )
            ? $result['runner_dispatch']
            : array();

        if ( ! empty( $result['duplicate'] ) || ! empty( $result['buffered'] ) ) {
            $dispatch_result = (array) $this->call(
                'dispatch_runner',
                array(),
                array(
                    ! empty( $result['buffered'] ) ? 'webhook-buffer' : 'message',
                    ! empty( $result['buffered'] ) ? 30 : $this->runner_liveness_ttl(),
                )
            );
        }

        $actor_result = array();
        if ( ! $this->should_use_local_cli_runner() && ( ! empty( $result['queued'] ) || ! empty( $result['duplicate'] ) ) ) {
            $actor_result = (array) $this->call( 'process_actor_runtime', array(), array( 1 ) );
            if ( ! empty( $actor_result['pending'] ) && ! $this->dispatch_result_covers_pending_work( $dispatch_result ) ) {
                $dispatch_result = (array) $this->call(
                    'dispatch_runner',
                    array(),
                    array( 'message', $this->runner_liveness_ttl() )
                );
            }
        }

        $response = array(
            'success' => true,
            'webhook' => true,
            'result'  => $result,
        );
        if ( ! empty( $actor_result ) ) {
            $response['actor_runtime'] = $this->summarize_actor_result( $actor_result );
        }
        if ( ! empty( $dispatch_result ) ) {
            $response['runner_dispatch'] = $dispatch_result;
        }

        return $response;
    }

    private function summarize_actor_result( $actor_result ) {
        $actor_result = is_array( $actor_result ) ? $actor_result : array();

        return array(
            'processed_sessions' => intval( isset( $actor_result['processed_sessions'] ) ? $actor_result['processed_sessions'] : 0 ),
            'processed_messages' => intval( isset( $actor_result['processed_messages'] ) ? $actor_result['processed_messages'] : 0 ),
            'pending'            => ! empty( $actor_result['pending'] ),
            'errors'             => isset( $actor_result['errors'] ) && is_array( $actor_result['errors'] )
                ? array_values( array_filter( $actor_result['errors'] ) )
                : array(),
        );
    }

    private function runner_liveness_ttl() {
        return intval( $this->call( 'runner_liveness_ttl', 30 ) );
    }

    private function should_use_local_cli_runner() {
        return ! empty( $this->call( 'should_use_local_cli_runner', false ) );
    }

    private function dispatch_result_covers_pending_work( $dispatch_result ) {
        $dispatch_result = is_array( $dispatch_result ) ? $dispatch_result : array();
        if ( empty( $dispatch_result ) ) {
            return false;
        }

        return ! empty( $dispatch_result['success'] ) || ! empty( $dispatch_result['wake_pending'] );
    }

    private function format_exception( Throwable $e ) {
        return (string) $this->call( 'format_exception', $e->getMessage(), array( $e ) );
    }

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

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