<?php
/**
 * Builds Telegram media context for admin autonomy turns.
 *
 * @package Niwa_AI
 */

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

class Niwa_AI_Admin_Autonomy_Media_Context_Builder {

    private $telegram;
    private $chat_agent;
    private $callbacks;

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

    public function build( $message ) {
        $out  = array();
        $refs = isset( $message['media_refs'] ) && is_array( $message['media_refs'] ) ? $message['media_refs'] : array();

        if ( empty( $refs ) ) {
            return $out;
        }

        $image_urls           = array();
        $documents            = array();
        $placeholders         = array();
        $sticker_descriptions = array();
        $incoming_media       = array();
        $first_attachment     = 0;
        $attachment_ids       = array();

        foreach ( $refs as $ref ) {
            if ( ! is_array( $ref ) || empty( $ref['file_id'] ) ) {
                continue;
            }

            $kind         = isset( $ref['kind'] ) ? (string) $ref['kind'] : '';
            $mime_hint    = isset( $ref['mime_hint'] ) ? (string) $ref['mime_hint'] : '';
            $is_image_doc = 'document' === $kind && 0 === strpos( $mime_hint, 'image/' );
            $transcript   = trim( (string) ( $ref['audio_transcript'] ?? '' ) );

            if ( '' !== $transcript && ! in_array( $kind, array( 'video', 'animation', 'video_note' ), true ) ) {
                continue;
            }

            if ( 'image' === $kind || $is_image_doc ) {
                $this->append_image_ref( $ref, $image_urls, $attachment_ids, $first_attachment, $placeholders );
                continue;
            }

            if ( 'document' === $kind ) {
                $this->append_document_ref( $ref, $mime_hint, $documents, $image_urls, $attachment_ids, $first_attachment, $placeholders );
                continue;
            }

            if ( in_array( $kind, array( 'voice', 'audio' ), true ) ) {
                $placeholders[] = '<media:audio>';
                continue;
            }

            if ( in_array( $kind, array( 'video', 'animation', 'video_note' ), true ) ) {
                $incoming_media[] = $this->build_incoming_media_entry_with_preview( $ref, $kind );
                continue;
            }

            if ( 'sticker' === $kind ) {
                $incoming_media[] = $this->build_sticker_entry( $ref, $sticker_descriptions );
                continue;
            }
        }

        $reply_image_urls = $this->collect_reply_image_urls( $message );

        if ( ! empty( $image_urls ) ) {
            $out['attachment_image_urls'] = $image_urls;
            $out['attachment_image_url']  = $image_urls[0];
            $attachment_ids = array_values( array_unique( array_filter( array_map( 'intval', $attachment_ids ) ) ) );
            if ( ! empty( $attachment_ids ) ) {
                $out['attachment_image_attachment_ids'] = $attachment_ids;
            }
            if ( $first_attachment > 0 ) {
                $out['attachment_image_attachment_id'] = $first_attachment;
            }
        }

        if ( ! empty( $documents ) ) {
            $out['attachment_documents'] = $documents;
            $excerpts = $this->parse_document_excerpts( $documents );
            if ( ! empty( $excerpts ) ) {
                $out['document_excerpts'] = $excerpts;
            }
        }

        if ( ! empty( $placeholders ) ) {
            $out['attachment_placeholders'] = $placeholders;
        }
        if ( ! empty( $sticker_descriptions ) ) {
            $out['sticker_descriptions'] = $sticker_descriptions;
        }
        if ( ! empty( $incoming_media ) ) {
            $out['incoming_media'] = $incoming_media;
        }
        if ( ! empty( $reply_image_urls ) ) {
            $out['reply_image_urls'] = $reply_image_urls;
        }

        return $out;
    }

    public function describe_sticker_via_vision( $ref, $image_url = null ) {
        try {
            if ( ! $this->chat_agent ) {
                return '';
            }

            $openai_client = $this->chat_agent->get_openai_client_instance();
            if ( ! $openai_client ) {
                return '';
            }

            $url = is_string( $image_url ) ? trim( $image_url ) : '';
            if ( '' === $url ) {
                if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_Image_Utils' ) ) {
                    return '';
                }

                $dl = $this->download_media_ref( $ref );
                if ( empty( $dl['success'] ) || empty( $dl['path'] ) ) {
                    return '';
                }

                $sideloaded = Niwa_AI_Admin_Autonomy_Image_Utils::ingest_local_image(
                    (string) $dl['path'],
                    'niwa-sticker-' . time(),
                    0,
                    ! array_key_exists( 'cleanup', $dl ) || ! empty( $dl['cleanup'] )
                );
                if ( empty( $sideloaded['url'] ) ) {
                    return '';
                }
                $url = (string) $sideloaded['url'];
            }

            return $this->call_vision_describe_sticker( $url );
        } catch ( \Throwable $e ) {
            return '';
        }
    }

    public function call_vision_describe_sticker( $image_url ) {
        try {
            $image_url = trim( (string) $image_url );
            if ( '' === $image_url || ! $this->chat_agent ) {
                return '';
            }

            $openai_client = $this->chat_agent->get_openai_client_instance();
            if ( ! $openai_client ) {
                return '';
            }

            $auth_mode = method_exists( $this->chat_agent, 'get_auth_mode' )
                ? (string) $this->chat_agent->get_auth_mode()
                : 'api_key';
            $creds = array();
            if ( method_exists( $this->chat_agent, 'get_auth_credentials' ) ) {
                $creds = (array) $this->chat_agent->get_auth_credentials();
            } elseif ( method_exists( $this->chat_agent, 'get_api_key_direct' ) ) {
                $api_key = (string) $this->chat_agent->get_api_key_direct();
                if ( '' !== $api_key ) {
                    $creds = array( 'api_key' => $api_key );
                }
            }

            $model = 'gpt-5.4-mini';
            if ( method_exists( $this->chat_agent, 'get_founder_model' ) ) {
                $maybe_model = (string) $this->chat_agent->get_founder_model();
                if ( '' !== $maybe_model ) {
                    $model = $maybe_model;
                }
            }

            $result = $openai_client->generate(
                $model,
                array(
                    array(
                        'type' => 'text',
                        'text' => 'Describe this sticker.',
                    ),
                    array(
                        'type'      => 'image_url',
                        'image_url' => array(
                            'url'    => $image_url,
                            'detail' => 'low',
                        ),
                    ),
                ),
                'Describe this Telegram sticker in one short sentence -- emoji-equivalent meaning, mood, or key visual elements. Max 100 chars.',
                $auth_mode,
                $creds,
                15
            );

            if ( empty( $result['success'] ) ) {
                return '';
            }

            $answer = isset( $result['answer'] ) ? trim( (string) $result['answer'] ) : '';
            if ( '' === $answer ) {
                return '';
            }
            if ( function_exists( 'mb_substr' ) ) {
                if ( mb_strlen( $answer ) > 120 ) {
                    $answer = trim( mb_substr( $answer, 0, 120 ) );
                }
            } elseif ( strlen( $answer ) > 120 ) {
                $answer = trim( substr( $answer, 0, 120 ) );
            }

            return $answer;
        } catch ( \Throwable $e ) {
            return '';
        }
    }

    private function append_image_ref( $ref, &$image_urls, &$attachment_ids, &$first_attachment, &$placeholders ) {
        $dl = $this->download_media_ref( $ref );
        if ( empty( $dl['success'] ) || empty( $dl['path'] ) || ! class_exists( 'Niwa_AI_Admin_Autonomy_Image_Utils' ) ) {
            $placeholders[] = '<media:image>';
            return;
        }

        $prefix  = 'whatsapp' === ( isset( $dl['source_channel'] ) ? (string) $dl['source_channel'] : '' ) ? 'whatsapp-image-' : 'telegram-image-';
        $cleanup = ! array_key_exists( 'cleanup', $dl ) || ! empty( $dl['cleanup'] );
        $this->append_sideloaded_image( (string) $dl['path'], $prefix, $image_urls, $attachment_ids, $first_attachment, $placeholders, $cleanup );
    }

    private function append_document_ref( $ref, $mime_hint, &$documents, &$image_urls, &$attachment_ids, &$first_attachment, &$placeholders ) {
        $dl = $this->download_media_ref( $ref );
        if ( empty( $dl['success'] ) || empty( $dl['path'] ) ) {
            $placeholders[] = '<media:document>';
            return;
        }

        $effective_kind = isset( $dl['kind'] ) ? (string) $dl['kind'] : 'document';
        if ( 'image' === $effective_kind ) {
            $prefix  = 'whatsapp' === ( isset( $dl['source_channel'] ) ? (string) $dl['source_channel'] : '' ) ? 'whatsapp-image-' : 'telegram-image-';
            $cleanup = ! array_key_exists( 'cleanup', $dl ) || ! empty( $dl['cleanup'] );
            $this->append_sideloaded_image( (string) $dl['path'], $prefix, $image_urls, $attachment_ids, $first_attachment, $placeholders, $cleanup );
            return;
        }

        if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_Image_Utils' ) ) {
            $placeholders[] = '<media:document>';
            return;
        }

        $saved = Niwa_AI_Admin_Autonomy_Image_Utils::save_inbound_document(
            (string) $dl['path'],
            isset( $ref['file_name'] ) ? (string) $ref['file_name'] : '',
            true
        );
        if ( ! empty( $saved['error'] ) ) {
            $placeholders[] = '<media:document>';
            return;
        }

        $documents[] = array(
            'path'         => isset( $saved['path'] ) ? (string) $saved['path'] : '',
            'filename'     => isset( $saved['filename'] ) ? (string) $saved['filename'] : '',
            'content_type' => isset( $dl['content_type'] ) ? (string) $dl['content_type'] : $mime_hint,
            'mime_hint'    => $mime_hint,
            'kind'         => $effective_kind,
        );
    }

    private function append_sideloaded_image( $path, $prefix, &$image_urls, &$attachment_ids, &$first_attachment, &$placeholders, $cleanup = true ) {
        if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_Image_Utils' ) ) {
            $placeholders[] = '<media:image>';
            return;
        }

        $sideloaded = Niwa_AI_Admin_Autonomy_Image_Utils::ingest_local_image(
            $path,
            $prefix . time(),
            0,
            ! empty( $cleanup )
        );
        if ( empty( $sideloaded['url'] ) ) {
            $placeholders[] = '<media:image>';
            return;
        }

        $image_urls[] = (string) $sideloaded['url'];
        if ( ! empty( $sideloaded['attachment_id'] ) ) {
            $attachment_id     = intval( $sideloaded['attachment_id'] );
            $attachment_ids[]  = $attachment_id;
            $first_attachment  = 0 === $first_attachment ? $attachment_id : $first_attachment;
        }
    }

    private function build_sticker_entry( $ref, &$sticker_descriptions ) {
        $is_animated = ! empty( $ref['is_animated_sticker'] );
        $is_video    = ! empty( $ref['is_video_sticker'] );
        $entry       = $this->build_incoming_media_entry_with_preview( $ref, 'sticker' );

        if ( $is_animated || $is_video ) {
            $this->append_sticker_visual_description( $ref, $entry, $sticker_descriptions );
            return $entry;
        }

        $unique_id = isset( $ref['file_unique_id'] ) ? (string) $ref['file_unique_id'] : '';
        $emoji     = isset( $ref['sticker_emoji'] ) ? (string) $ref['sticker_emoji'] : '';
        $set_name  = isset( $ref['sticker_set'] ) ? (string) $ref['sticker_set'] : '';
        $cached    = '' !== $unique_id && class_exists( 'Niwa_AI_Admin_Autonomy_Telegram_Sticker_Cache' )
            ? Niwa_AI_Admin_Autonomy_Telegram_Sticker_Cache::get( $unique_id )
            : null;

        if ( is_array( $cached ) && ! empty( $cached['description'] ) ) {
            $sticker_descriptions[] = (string) $cached['description'];
        } elseif ( class_exists( 'Niwa_AI_Admin_Autonomy_Telegram_Sticker_Cache' ) ) {
            $derived = Niwa_AI_Admin_Autonomy_Telegram_Sticker_Cache::describe_from_metadata( $emoji, $set_name );
            if ( '' !== $derived ) {
                if ( '' !== $unique_id ) {
                    Niwa_AI_Admin_Autonomy_Telegram_Sticker_Cache::set( $unique_id, $derived, $emoji, $set_name );
                }
                $sticker_descriptions[] = $derived;
            }
        }

        $this->append_sticker_visual_description( $ref, $entry, $sticker_descriptions );
        return $entry;
    }

    private function append_sticker_visual_description( $ref, &$entry, &$sticker_descriptions ) {
        $visual_description = $this->describe_sticker_preview_for_context( $ref, $entry );
        if ( '' === $visual_description ) {
            return;
        }

        $entry['visual_description'] = $visual_description;
        $sticker_descriptions[]      = $visual_description;
    }

    private function build_incoming_media_entry( $ref, $kind ) {
        $ref   = is_array( $ref ) ? $ref : array();
        $entry = array(
            'kind'             => (string) $kind,
            'file_id'          => isset( $ref['file_id'] ) ? (string) $ref['file_id'] : '',
            'file_unique_id'   => isset( $ref['file_unique_id'] ) ? (string) $ref['file_unique_id'] : '',
            'mime_type'        => isset( $ref['mime_hint'] ) ? (string) $ref['mime_hint'] : '',
            'duration_seconds' => isset( $ref['duration'] ) ? intval( $ref['duration'] ) : 0,
            'width'            => isset( $ref['width'] ) ? intval( $ref['width'] ) : 0,
            'height'           => isset( $ref['height'] ) ? intval( $ref['height'] ) : 0,
            'file_size_bytes'  => isset( $ref['size'] ) ? intval( $ref['size'] ) : 0,
            'file_name'        => isset( $ref['file_name'] ) ? (string) $ref['file_name'] : '',
        );

        if ( 'sticker' === $kind ) {
            $entry['sticker_emoji']       = isset( $ref['sticker_emoji'] ) ? (string) $ref['sticker_emoji'] : '';
            $entry['sticker_set']         = isset( $ref['sticker_set'] ) ? (string) $ref['sticker_set'] : '';
            $entry['is_animated_sticker'] = ! empty( $ref['is_animated_sticker'] );
            $entry['is_video_sticker']    = ! empty( $ref['is_video_sticker'] );
        }

        return $entry;
    }

    private function describe_sticker_preview_for_context( $ref, $entry ) {
        $preview_url = isset( $entry['preview_image_url'] ) ? trim( (string) $entry['preview_image_url'] ) : '';
        if ( '' === $preview_url ) {
            return '';
        }

        $description = $this->call_vision_describe_sticker( $preview_url );
        if ( '' === $description ) {
            return '';
        }

        $unique_id = isset( $ref['file_unique_id'] ) ? trim( (string) $ref['file_unique_id'] ) : '';
        if ( '' !== $unique_id && class_exists( 'Niwa_AI_Admin_Autonomy_Telegram_Sticker_Cache' ) ) {
            Niwa_AI_Admin_Autonomy_Telegram_Sticker_Cache::set(
                $unique_id,
                $description,
                isset( $ref['sticker_emoji'] ) ? (string) $ref['sticker_emoji'] : '',
                isset( $ref['sticker_set'] ) ? (string) $ref['sticker_set'] : ''
            );
        }

        return $description;
    }

    private function build_incoming_media_entry_with_preview( $ref, $kind ) {
        $entry = $this->build_incoming_media_entry( $ref, $kind );
        $ref   = is_array( $ref ) ? $ref : array();

        $transcript_result = '' !== trim( (string) ( $ref['audio_transcript'] ?? '' ) )
            ? array( 'transcript' => trim( (string) $ref['audio_transcript'] ), 'error' => '' )
            : $this->maybe_transcribe_video_audio( $kind, $ref );
        if ( '' !== $transcript_result['transcript'] ) {
            $entry['audio_transcript'] = $transcript_result['transcript'];
        }

        if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_Image_Utils' ) ) {
            return $entry;
        }

        $attempts = $this->preview_download_attempts( $ref, $kind );
        $last_error = '';
        foreach ( $attempts as $attempt ) {
            $dl = $this->download_media_ref( $attempt['ref'] );
            if ( empty( $dl['success'] ) || empty( $dl['path'] ) ) {
                $last_error = isset( $dl['error'] ) ? (string) $dl['error'] : 'download_failed';
                continue;
            }

            $ingest_path = (string) $dl['path'];
            $cleanup     = ! array_key_exists( 'cleanup', $dl ) || ! empty( $dl['cleanup'] );
            if ( 'ffmpeg_extract' === $attempt['mode'] ) {
                $frame = Niwa_AI_Admin_Autonomy_Image_Utils::extract_video_frame( $ingest_path );
                if ( $cleanup && is_file( $ingest_path ) ) {
                    @unlink( $ingest_path );
                }
                if ( empty( $frame['success'] ) || empty( $frame['path'] ) ) {
                    $last_error = isset( $frame['error'] ) ? (string) $frame['error'] : 'ffmpeg_extract_failed';
                    continue;
                }
                $ingest_path = (string) $frame['path'];
            }

            if ( '' === $ingest_path || ! is_file( $ingest_path ) ) {
                continue;
            }

            $sideloaded = Niwa_AI_Admin_Autonomy_Image_Utils::ingest_local_image(
                $ingest_path,
                ( 'whatsapp' === ( isset( $dl['source_channel'] ) ? (string) $dl['source_channel'] : '' ) ? 'whatsapp-' : 'telegram-' ) . sanitize_key( $kind ) . '-preview-' . time(),
                0,
                $cleanup
            );
            if ( empty( $sideloaded['url'] ) ) {
                $last_error = isset( $sideloaded['error'] ) ? (string) $sideloaded['error'] : 'sideload_failed';
                continue;
            }

            $entry['preview_image_url'] = (string) $sideloaded['url'];
            $entry['preview_source']    = (string) $attempt['mode'];
            if ( ! empty( $sideloaded['attachment_id'] ) ) {
                $entry['preview_attachment_id'] = intval( $sideloaded['attachment_id'] );
            }

            $extra_urls = $this->maybe_extract_extra_video_frames( $kind, $ref );
            if ( ! empty( $extra_urls ) ) {
                $entry['extra_frame_urls'] = $extra_urls;
            }

            return $entry;
        }

        $entry['preview_status'] = 'extract_failed';
        if ( '' !== $last_error ) {
            $entry['preview_error'] = $last_error;
        }

        $extra_urls = $this->maybe_extract_extra_video_frames( $kind, $ref );
        if ( ! empty( $extra_urls ) ) {
            $entry['extra_frame_urls'] = $extra_urls;
            unset( $entry['preview_status'], $entry['preview_error'] );
        }

        return $entry;
    }

    private function preview_download_attempts( $ref, $kind ) {
        $is_static_sticker = 'sticker' === $kind
            && empty( $ref['is_animated_sticker'] )
            && empty( $ref['is_video_sticker'] );

        if ( $is_static_sticker ) {
            return array( array( 'mode' => 'main_image', 'ref' => $ref ) );
        }

        $attempts = array();
        if ( ! empty( $ref['thumb_file_id'] ) ) {
            $attempts[] = array(
                'mode' => 'thumbnail',
                'ref'  => array(
                    'kind'      => 'image',
                    'file_id'   => (string) $ref['thumb_file_id'],
                    'mime_hint' => 'image/jpeg',
                ),
            );
        }
        $attempts[] = array( 'mode' => 'ffmpeg_extract', 'ref' => $ref );

        return $attempts;
    }

    private function maybe_extract_extra_video_frames( $kind, $ref ) {
        if ( ! in_array( (string) $kind, array( 'video', 'video_note' ), true ) || empty( $ref['file_id'] ) ) {
            return array();
        }
        if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_Image_Utils' ) ) {
            return array();
        }

        $duration = isset( $ref['duration'] ) ? intval( $ref['duration'] ) : 0;
        if ( $duration <= 5 ) {
            return array();
        }

        $probe_path = Niwa_AI_Admin_Autonomy_Temp_Files::create( 'niwa-ffmpeg-probe-' );
        if ( '' === $probe_path ) {
            return array();
        }
        $probe_result = Niwa_AI_Admin_Autonomy_Image_Utils::extract_video_frame( $probe_path );
        if ( is_file( $probe_path ) ) {
            @unlink( $probe_path );
        }
        if ( ! empty( $probe_result['error'] ) && in_array( (string) $probe_result['error'], array( 'ffmpeg_not_found', 'shell_exec_disabled' ), true ) ) {
            return array();
        }

        $dl = $this->download_media_ref( $ref );
        if ( empty( $dl['success'] ) || empty( $dl['path'] ) ) {
            return array();
        }

        $main_path = (string) $dl['path'];
        $frames    = Niwa_AI_Admin_Autonomy_Image_Utils::extract_video_frames( $main_path, 3 );
        if ( ( ! array_key_exists( 'cleanup', $dl ) || ! empty( $dl['cleanup'] ) ) && is_file( $main_path ) ) {
            @unlink( $main_path );
        }
        if ( empty( $frames['success'] ) || empty( $frames['paths'] ) ) {
            return array();
        }

        $urls = array();
        foreach ( (array) $frames['paths'] as $frame_path ) {
            $frame_path = (string) $frame_path;
            if ( '' === $frame_path || ! is_file( $frame_path ) ) {
                continue;
            }
            $sideloaded = Niwa_AI_Admin_Autonomy_Image_Utils::ingest_local_image(
                $frame_path,
                ( 'whatsapp' === ( isset( $dl['source_channel'] ) ? (string) $dl['source_channel'] : '' ) ? 'whatsapp-' : 'telegram-' ) . sanitize_key( $kind ) . '-frame-' . time(),
                0,
                true
            );
            if ( ! empty( $sideloaded['url'] ) ) {
                $urls[] = (string) $sideloaded['url'];
            }
        }

        return $urls;
    }

    private function maybe_transcribe_video_audio( $kind, $ref ) {
        $blank = array( 'transcript' => '', 'error' => '' );

        if ( ! in_array( (string) $kind, array( 'video', 'video_note' ), true ) || empty( $ref['file_id'] ) ) {
            return $blank;
        }
        $duration = isset( $ref['duration'] ) ? intval( $ref['duration'] ) : 0;
        if ( $duration <= 0 ) {
            return $blank;
        }
        $size = isset( $ref['size'] ) ? intval( $ref['size'] ) : 0;
        if ( $size > 0 && $size > 25 * 1024 * 1024 ) {
            return array( 'transcript' => '', 'error' => 'too_large_for_whisper' );
        }

        try {
            $result = $this->call( 'transcribe_voice_message', array( $ref ), array( 'success' => false ) );
        } catch ( \Throwable $e ) {
            return array( 'transcript' => '', 'error' => 'transcribe_exception' );
        }

        if ( empty( $result['success'] ) ) {
            return array(
                'transcript' => '',
                'error'      => isset( $result['error'] ) ? (string) $result['error'] : 'transcribe_failed',
            );
        }

        $text = isset( $result['text'] ) ? trim( (string) $result['text'] ) : '';
        if ( '' === $text ) {
            return $blank;
        }
        if ( strlen( $text ) > 4000 ) {
            $text = substr( $text, 0, 4000 ) . '...';
        }

        return array( 'transcript' => $text, 'error' => '' );
    }

    private function collect_reply_image_urls( $message ) {
        $reply_refs = isset( $message['reply_media_refs'] ) && is_array( $message['reply_media_refs'] ) ? $message['reply_media_refs'] : array();
        $urls       = array();

        foreach ( $reply_refs as $ref ) {
            if ( ! is_array( $ref ) || empty( $ref['file_id'] ) ) {
                continue;
            }
            $kind = isset( $ref['kind'] ) ? (string) $ref['kind'] : '';
            $mime = isset( $ref['mime_hint'] ) ? (string) $ref['mime_hint'] : '';
            if ( 'image' !== $kind && ! ( 'document' === $kind && 0 === strpos( $mime, 'image/' ) ) ) {
                continue;
            }
            if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_Image_Utils' ) ) {
                continue;
            }

            $dl = $this->download_media_ref( $ref );
            if ( empty( $dl['success'] ) || empty( $dl['path'] ) ) {
                continue;
            }

            $sideloaded = Niwa_AI_Admin_Autonomy_Image_Utils::ingest_local_image(
                (string) $dl['path'],
                ( 'whatsapp' === ( isset( $dl['source_channel'] ) ? (string) $dl['source_channel'] : '' ) ? 'whatsapp-reply-image-' : 'telegram-reply-image-' ) . time(),
                0,
                ! array_key_exists( 'cleanup', $dl ) || ! empty( $dl['cleanup'] )
            );
            if ( ! empty( $sideloaded['url'] ) ) {
                $urls[] = (string) $sideloaded['url'];
            }
        }

        return $urls;
    }

    private function download_media_ref( $ref ) {
        $ref = is_array( $ref ) ? $ref : array();
        if ( 'whatsapp' === ( isset( $ref['channel'] ) ? (string) $ref['channel'] : '' ) ) {
            $path = isset( $ref['local_path'] ) ? (string) $ref['local_path'] : '';
			$path = (string) $this->call( 'resolve_whatsapp_local_media_path', array( $path ), '' );
			if ( '' === $path || ! is_readable( $path ) ) {
                return array(
                    'success' => false,
                    'error'   => 'whatsapp_local_media_unreadable',
                );
            }

            return array(
                'success'        => true,
                'path'           => $path,
                'content_type'   => isset( $ref['mime_hint'] ) ? (string) $ref['mime_hint'] : '',
                'kind'           => isset( $ref['kind'] ) ? (string) $ref['kind'] : 'document',
                'source_channel' => 'whatsapp',
                'cleanup'        => false,
            );
        }

        if ( ! $this->telegram || ! method_exists( $this->telegram, 'download_inbound_media' ) ) {
            return array(
                'success' => false,
                'error'   => 'telegram_media_downloader_unavailable',
            );
        }

        $dl = $this->telegram->download_inbound_media( $ref );
        if ( is_array( $dl ) ) {
            $dl['source_channel'] = 'telegram';
            if ( ! array_key_exists( 'cleanup', $dl ) ) {
                $dl['cleanup'] = true;
            }
        }
        return is_array( $dl ) ? $dl : array( 'success' => false, 'error' => 'download_failed' );
    }

    private function parse_document_excerpts( $documents ) {
        if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_Document_Parser' ) ) {
            return array();
        }

        $excerpts = array();
        foreach ( $documents as $doc ) {
            $parsed = Niwa_AI_Admin_Autonomy_Document_Parser::parse_document(
                isset( $doc['path'] ) ? (string) $doc['path'] : '',
                isset( $doc['content_type'] ) ? (string) $doc['content_type'] : '',
                isset( $doc['filename'] ) ? (string) $doc['filename'] : ''
            );
            $excerpts[] = array(
                'filename'     => isset( $doc['filename'] ) ? (string) $doc['filename'] : '',
                'content_type' => isset( $doc['content_type'] ) ? (string) $doc['content_type'] : '',
                'format'       => isset( $parsed['format'] ) ? (string) $parsed['format'] : 'unknown',
                'success'      => ! empty( $parsed['success'] ),
                'text'         => isset( $parsed['text'] ) ? (string) $parsed['text'] : '',
                'metadata'     => isset( $parsed['metadata'] ) && is_array( $parsed['metadata'] ) ? $parsed['metadata'] : array(),
                'truncated'    => ! empty( $parsed['truncated'] ),
                'error'        => isset( $parsed['error'] ) ? (string) $parsed['error'] : '',
            );
        }

        return $excerpts;
    }

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