<?php
/**
 * Builds actor execution context from a Telegram message payload.
 */

defined( 'ABSPATH' ) || exit;

class Niwa_AI_Admin_Autonomy_Telegram_Message_Context_Builder {

    private $telegram;
    private $chat_agent;
    private $conversation_store;
    private $session_state;
    private $callbacks;

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

    public function build( $message ) {
        $message    = is_array( $message ) ? $message : array();
        $chat_id    = isset( $message['chat_id'] ) ? (string) $message['chat_id'] : '';
        $channel    = isset( $message['channel'] ) ? sanitize_key( (string) $message['channel'] ) : 'telegram';
        if ( '' === $channel ) {
            $channel = 'telegram';
        }
        $user_role  = isset( $message['user_role'] ) ? (string) $message['user_role'] : 'admin';
        $session_id = 'admin_ui' === $channel && ! empty( $message['session_id'] )
            ? trim( (string) $message['session_id'] )
            : (string) $this->call( 'get_founder_session_id', array( $chat_id ), $chat_id );
        $history    = $this->conversation_store && method_exists( $this->conversation_store, 'get' ) ? $this->conversation_store->get( $session_id ) : array();
		if ( 'admin_ui' === $channel ) {
			$history = $this->exclude_current_admin_ui_turn( $history, $message );
		}
        $has_runtime_state = $this->chat_agent && method_exists( $this->chat_agent, 'session_has_runtime_state' )
            ? ! empty( $this->chat_agent->session_has_runtime_state( $session_id ) )
            : false;

        $context = array(
            'channel'             => $channel,
            'chat_id'             => $chat_id,
            'message_id'          => isset( $message['message_id'] ) ? intval( $message['message_id'] ) : 0,
            'session_id'          => $session_id,
            'history'             => $history,
            'is_new_session'      => empty( $history ) && ! $has_runtime_state,
            'callback_data'       => isset( $message['callback_data'] ) ? (string) $message['callback_data'] : '',
            'user_role'           => $user_role,
            'stock_manager_label' => $this->resolve_stock_manager_label( $chat_id, $user_role ),
        );

        if ( $this->chat_agent && method_exists( $this->chat_agent, 'prepare_context' ) ) {
            if ( 'stock_manager' === $user_role ) {
                $context['memory_summary']     = '';
                $context['seed_notes']         = '';
                $context['site_context_blob']  = method_exists( $this->chat_agent, 'build_site_context_blob_public' ) ? $this->chat_agent->build_site_context_blob_public() : '';
                $context['recent_work_notes']  = '';
            } else {
                $context = array_merge( $context, (array) $this->chat_agent->prepare_context( $session_id, $history ) );
            }
        }

        $context = array_merge( $context, (array) $this->call( 'build_media_attachments_context', array( $message ), array() ) );
        $context = $this->apply_message_annotations( $context, $message );
        $this->remember_current_media_context( $session_id, $context );

		if ( ! empty( $message['skill_import_content'] ) ) {
			$context['skill_import_content']  = (string) $message['skill_import_content'];
			$context['skill_import_filename'] = isset( $message['skill_import_filename'] ) ? (string) $message['skill_import_filename'] : '';
		}
		if ( ! empty( $message['skill_import_archive_base64'] ) ) {
			$context['skill_import_archive_base64'] = (string) $message['skill_import_archive_base64'];
			$context['skill_import_filename']       = isset( $message['skill_import_filename'] ) ? (string) $message['skill_import_filename'] : '';
		}

		if ( ! empty( $message['spreadsheet_file_id'] ) ) {
            $context['spreadsheet_file_id']  = (string) $message['spreadsheet_file_id'];
            $context['spreadsheet_filename'] = isset( $message['spreadsheet_filename'] ) ? (string) $message['spreadsheet_filename'] : '';
        }

        return $context;
    }

    private function resolve_stock_manager_label( $chat_id, $user_role ) {
        if ( 'stock_manager' !== $user_role || ! $this->telegram || ! method_exists( $this->telegram, 'find_stock_manager' ) ) {
            return '';
        }

        $stock_manager = $this->telegram->find_stock_manager( $chat_id );
        return $stock_manager && ! empty( $stock_manager['label'] ) ? (string) $stock_manager['label'] : '';
    }

    private function apply_message_annotations( $context, $message ) {
        $forward = isset( $message['forward'] ) && is_array( $message['forward'] ) ? $message['forward'] : array();
        if ( ! empty( $forward['is_forwarded'] ) ) {
            $origin_label = isset( $forward['origin_label'] ) ? (string) $forward['origin_label'] : '';
            $origin_type  = isset( $forward['origin_type'] ) ? (string) $forward['origin_type'] : '';
            $context['forward_marker'] = '' !== $origin_label
                ? sprintf( '[Forwarded from %s%s]', $origin_label, '' !== $origin_type ? ' (' . $origin_type . ')' : '' )
                : '[Forwarded message]';
        }

        if ( ! empty( $message['location'] ) && is_array( $message['location'] ) ) {
            $location = $message['location'];
            $lat      = isset( $location['lat'] ) ? (float) $location['lat'] : 0.0;
            $lng      = isset( $location['lng'] ) ? (float) $location['lng'] : 0.0;
            $accuracy = isset( $location['horizontal_accuracy'] ) ? (float) $location['horizontal_accuracy'] : 0.0;
            $context['location_text'] = sprintf( 'Location: %.6f, %.6f%s', $lat, $lng, $accuracy > 0 ? sprintf( ' (±%.0fm)', $accuracy ) : '' );
        }

        if ( ! empty( $message['contact'] ) && is_array( $message['contact'] ) ) {
            $contact = $message['contact'];
            $name    = trim( ( $contact['first_name'] ?? '' ) . ' ' . ( $contact['last_name'] ?? '' ) );
            $phone   = isset( $contact['phone'] ) ? (string) $contact['phone'] : '';
            $context['contact_text'] = trim( 'Contact: ' . ( '' !== $name ? $name : '(no name)' ) . ( '' !== $phone ? ' — ' . $phone : '' ) );
        }

        if ( ! empty( $message['is_album'] ) ) {
            $context['is_album']   = true;
            $context['album_size'] = isset( $message['album_size'] ) ? intval( $message['album_size'] ) : 0;
        }
        if ( ! empty( $message['is_text_fragment'] ) ) {
            $context['is_text_fragment'] = true;
            $context['fragment_count']   = isset( $message['fragment_count'] ) ? intval( $message['fragment_count'] ) : 0;
        }
        if ( ! empty( $message['is_edited'] ) ) {
            $context['is_edited']     = true;
            $context['edited_marker'] = '[Edited message] The founder edited a previous message; treat the current text/media as the corrected version of that earlier turn.';
        }

        $caption = isset( $message['caption'] ) ? (string) $message['caption'] : '';
        if ( '' !== $caption ) {
            $context['caption'] = $caption;
        }

        return $context;
    }

    private function remember_current_media_context( $session_id, $context ) {
        $session_id = trim( (string) $session_id );
        if ( '' === $session_id || ! $this->session_state || ! method_exists( $this->session_state, 'remember_media_context' ) ) {
            return;
        }

        $attachment_id = isset( $context['attachment_image_attachment_id'] ) ? intval( $context['attachment_image_attachment_id'] ) : 0;
        $attachment_ids = isset( $context['attachment_image_attachment_ids'] ) && is_array( $context['attachment_image_attachment_ids'] )
            ? array_values( array_filter( array_map( 'intval', $context['attachment_image_attachment_ids'] ) ) )
            : array();
        $image_url  = isset( $context['attachment_image_url'] ) ? esc_url_raw( (string) $context['attachment_image_url'] ) : '';
        $image_urls = isset( $context['attachment_image_urls'] ) && is_array( $context['attachment_image_urls'] )
            ? array_values( array_filter( array_map( 'esc_url_raw', array_map( 'strval', $context['attachment_image_urls'] ) ) ) )
            : array();

        if ( $attachment_id <= 0 && empty( $attachment_ids ) && '' === $image_url && empty( $image_urls ) ) {
            return;
        }

        if ( $attachment_id <= 0 && ! empty( $attachment_ids ) ) {
            $attachment_id = intval( $attachment_ids[0] );
        }

        $this->session_state->remember_media_context(
            $session_id,
            array(
                'attachment_image_attachment_id'  => $attachment_id,
                'attachment_image_attachment_ids' => $attachment_ids,
                'attachment_image_url'            => $image_url,
                'attachment_image_urls'           => $image_urls,
                'message_id'                      => isset( $context['message_id'] ) ? intval( $context['message_id'] ) : 0,
            )
        );
    }

	private function exclude_current_admin_ui_turn( $history, $message ) {
		$history    = is_array( $history ) ? $history : array();
		$message    = is_array( $message ) ? $message : array();
		$request_id = trim( (string) ( $message['request_id'] ?? '' ) );
		$job_id     = trim( (string) ( $message['admin_ui_job_id'] ?? '' ) );
		$current_sequence = intval( $message['admin_ui_sequence'] ?? 0 );
		if ( '' === $request_id && '' === $job_id ) {
			return $history;
		}
		$committed_sequences = array();
		if ( $current_sequence > 0 ) {
			foreach ( $history as $item ) {
				$meta = is_array( $item ) && isset( $item['meta'] ) && is_array( $item['meta'] ) ? $item['meta'] : array();
				$sequence = intval( $item['admin_ui_sequence'] ?? ( $meta['admin_ui_sequence'] ?? 0 ) );
				if ( is_array( $item ) && 'bot' === sanitize_key( (string) ( $item['role'] ?? '' ) ) && $sequence > 0 && $sequence < $current_sequence && ( ! empty( $item['delivery_committed'] ) || ! empty( $meta['delivery_committed'] ) ) ) {
					$committed_sequences[ $sequence ] = true;
				}
			}
		}

		return array_values(
			array_filter(
				$history,
				static function ( $item ) use ( $request_id, $job_id, $current_sequence, $committed_sequences ) {
					if ( ! is_array( $item ) ) {
						return true;
					}
					$role = sanitize_key( (string) ( $item['role'] ?? '' ) );
					$meta = isset( $item['meta'] ) && is_array( $item['meta'] ) ? $item['meta'] : array();
					$sequence = intval( $item['admin_ui_sequence'] ?? ( $meta['admin_ui_sequence'] ?? 0 ) );
					if ( $current_sequence > 0 && $sequence > 0 ) {
						if ( $sequence >= $current_sequence ) {
							return false;
						}
						if ( 'user' === $role && empty( $committed_sequences[ $sequence ] ) ) {
							return false;
						}
					}
					if ( 'user' !== $role ) {
						return true;
					}
					$item_request = trim( (string) ( $item['request_id'] ?? ( $meta['request_id'] ?? '' ) ) );
					$item_id      = trim( (string) ( $item['id'] ?? '' ) );
					$item_job     = trim( (string) ( $item['job_id'] ?? ( $item['admin_ui_job_id'] ?? ( $meta['admin_ui_job_id'] ?? '' ) ) ) );
					$request_match = '' !== $request_id && ( ( '' !== $item_request && hash_equals( $request_id, $item_request ) ) || ( '' !== $item_id && hash_equals( $request_id, $item_id ) ) );
					$job_match     = '' !== $job_id && '' !== $item_job && hash_equals( $job_id, $item_job );
					return ! $request_match && ! $job_match;
				}
			)
		);
	}

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