<?php
defined( 'ABSPATH' ) || exit;

if ( !class_exists( 'Better_Messages_AI' ) ) {
    class Better_Messages_AI
    {
        public $api;
        public static function instance()
        {

            static $instance = null;

            if (null === $instance) {
                $instance = new Better_Messages_AI();
            }

            return $instance;
        }

        public function __construct()
        {
            add_action( 'init',      array( $this, 'register_post_type' ) );

            add_filter( 'better_messages_rest_thread_item', array( $this, 'rest_thread_item'), 20, 5 );

            add_filter('better_messages_get_user_roles', array($this, 'get_user_roles'), 10, 2 );

            if ( version_compare(phpversion(), '8.1', '>=') ) {
                // Requires PHP 8.1+
                require_once "dependencies/autoload.php";
                require_once "api/open-ai.php";

                $this->api = Better_Messages_OpenAI_API::instance();

                add_action( 'admin_init', array( $this, 'register_event' ) );
                add_action( 'rest_api_init',  array( $this, 'rest_api_init' ) );
                add_action( 'save_post', array( $this, 'save_post' ), 1, 2 );

                add_action( 'bp_better_chat_settings_updated', array($this, 'check_if_api_key_valid'));

                add_action( 'better_messages_message_sent', array( $this, 'on_message_sent'), 10, 1 );
                add_action( 'better_messages_before_message_delete', array( $this, 'before_delete_message' ), 10 , 3 );

                add_action( 'bp_better_messages_new_thread_created', array( $this, 'on_new_thread_created'), 10, 2 );
                add_filter( 'better_messages_can_send_message', array( $this, 'block_reply_if_needed' ), 20, 3 );
                add_action( 'better_messages_before_new_thread',  array( $this, 'restrict_new_thread_if_needed'), 10, 2 );

                add_action('better_messages_ai_bot_ensure_completion', array( $this, 'ai_bot_ensure_completion'), 10, 2 );
                add_action('better_messages_ai_ensure_completion_job', array( $this->api, 'ensureResponseCompletionJob' ) );
            }
        }

        public function register_event()
        {
            if ( ! wp_next_scheduled( 'better_messages_ai_ensure_completion_job' ) ) {
                wp_schedule_event( time(), 'better_messages_ai_ensure_completion_job', 'better_messages_ai_ensure_completion_job' );
            }
        }

        public function get_user_roles( $roles, $user_id )
        {
            if( $user_id < 0 ){
                $guest_id = absint($user_id);
                $guest = Better_Messages()->guests->get_guest_user( $guest_id );

                if( $guest && $guest->ip && str_starts_with($guest->ip, 'ai-chat-bot-') ){
                    $bot_id = str_replace('ai-chat-bot-', '', $guest->ip);

                    if( $this->bot_exists( $bot_id ) ){
                        $roles = ['bm-bot'];
                    }
                }
            }

            return $roles;
        }

        public function restrict_new_thread_if_needed( &$args, &$errors ){
            // Get array with recipients user ids, which user trying to start conversation with
            $recipients = $args['recipients'];

            if( $recipients && count( $recipients ) === 1 ){
                $recipient_id = reset( $recipients );

                if( $recipient_id < 0 ){
                    $guest_id = absint($recipient_id);
                    $guest = Better_Messages()->guests->get_guest_user( $guest_id );

                    if( $guest && $guest->ip && str_starts_with($guest->ip, 'ai-chat-bot-') ){
                        $bot_id = str_replace('ai-chat-bot-', '', $guest->ip);

                        if( $this->bot_exists( $bot_id ) ){
                            $bot_settings = $this->get_bot_settings( $bot_id );

                            if( $bot_settings['enabled'] !== '1' || empty( $bot_settings['model'] ) ){
                                $errors['bot_disabled'] = _x('The bot is currently disabled', 'AI Chat Bots', 'bp-better-messages');
                            }
                        }
                    }
                }
            }
        }

        public function on_new_thread_created( $thread_id, $message_id = null )
        {
            $thread_type = Better_Messages()->functions->get_thread_type( $thread_id );

            if( $thread_type !== 'thread'){
                return;
            }

            $recipients = Better_Messages()->functions->get_recipients( $thread_id );

            if( count( $recipients ) === 2 ) {
                foreach ($recipients as $user) {
                    $user_id = $user->user_id;
                    if ($user_id < 0) {
                        $guest_id = absint($user_id);
                        $guest = Better_Messages()->guests->get_guest_user($guest_id);

                        if ($guest && $guest->ip && str_starts_with($guest->ip, 'ai-chat-bot-')) {
                            $bot_id = str_replace('ai-chat-bot-', '', $guest->ip);

                            if( $this->bot_exists( $bot_id ) ){
                                Better_Messages()->functions->update_thread_meta( $thread_id, 'ai_bot_thread', $bot_id );
                            }
                        }
                    }
                }
            }
        }

        public function bot_exists( $bot_id )
        {
            $post = get_post( $bot_id );

            if( $post && $post->post_type === 'bm-ai-chat-bot' && $post->post_status !== 'trash' ){
                return true;
            }

            return false;
        }

        public function is_bot_conversation( $bot_id, $thread_id )
        {
            $bot_thread_id = Better_Messages()->functions->get_thread_meta( $thread_id, 'ai_bot_thread' );

            if( empty( $bot_thread_id) ) return false;

            return (int) $bot_thread_id === (int) $bot_id;
        }

        public function block_reply_if_needed( $allowed, $user_id, $thread_id )
        {
            $thread_type = Better_Messages()->functions->get_thread_type( $thread_id );

            if( $thread_type !== 'thread'){
                return $allowed;
            }

            $recipients = Better_Messages()->functions->get_recipients( $thread_id );

            if( count( $recipients ) === 2 ) {
                foreach ($recipients as $user) {
                    $user_id = $user->user_id;
                    if ($user_id < 0) {
                        $guest_id = absint($user_id);
                        $guest = Better_Messages()->guests->get_guest_user($guest_id);

                        if ($guest && $guest->ip && str_starts_with($guest->ip, 'ai-chat-bot-')) {
                            $bot_id = str_replace('ai-chat-bot-', '', $guest->ip);

                            if( $this->bot_exists( $bot_id ) && $this->is_bot_conversation( $bot_id, $thread_id ) ){
                                $bot_settings = $this->get_bot_settings($bot_id);

                                if ( $bot_settings['enabled'] !== '1'  || empty( $bot_settings['model'] ) ) {
                                    $allowed = false;
                                    global $bp_better_messages_restrict_send_message;
                                    $bp_better_messages_restrict_send_message['bot_is_disabled'] = _x('The bot is currently disabled', 'AI Chat Bots', 'bp-better-messages');
                                } else {
                                    $is_waiting_for_response = Better_Messages()->functions->get_thread_meta( $thread_id, 'ai_waiting_for_response' );

                                    if ($is_waiting_for_response) {
                                        $time_ago = time() - $is_waiting_for_response;
                                        $time_limit = 60 * 5; // 5 minutes

                                        if ($time_ago < $time_limit) {
                                            $allowed = false;
                                            global $bp_better_messages_restrict_send_message;
                                            $bp_better_messages_restrict_send_message['waiting_for_ai_response'] = _x('Please wait until response is completed', 'AI Chat Bots', 'bp-better-messages');
                                        } else {
                                            Better_Messages()->functions->delete_thread_meta( $thread_id, 'ai_waiting_for_response' );
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return $allowed;
        }

        public function check_if_api_key_valid()
        {
            $api_key_exists = ! empty(Better_Messages()->settings['openAiApiKey']);

            if( $api_key_exists ){
                $this->api->update_api_key();
                $this->api->check_api_key();
            } else {
                delete_option( 'better_messages_openai_error' );
            }
        }

        public function rest_api_init()
        {
            register_rest_route('better-messages/v1/ai', '/createResponse', array(
                'methods' => 'GET',
                'callback' => array( $this->api, 'reply_to_message'),
                'permission_callback' => '__return_true',
            ));

            register_rest_route('better-messages/v1/ai', '/cancelResponse/(?P<id>\d+)', array(
                'methods' => 'POST',
                'callback' => array( $this->api, 'cancel_response'),
                'permission_callback' => array( Better_Messages()->api, 'check_thread_access' ),
                'args' => array(
                    'id' => array(
                        'validate_callback' => function($param, $request, $key) {
                            return is_numeric( $param );
                        }
                    ),
                ),
            ));

            register_rest_route('better-messages/v1/admin/ai', '/getModels', array(
                'methods' => 'GET',
                'callback' => array( $this->api, 'get_models'),
                'permission_callback' => array($this, 'user_is_admin'),
            ));

        }

        public function user_is_admin(){
            return current_user_can('manage_options');
        }

        public function register_post_type(){
            $args = array(
                'public'               => false,
                'labels'               => [
                    'name'          => _x( 'AI Chat Bots', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'singular_name' => _x( 'AI Chat Bot', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'add_new'       => _x( 'Create new AI Chat Bot', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'add_new_item'  => _x( 'Create new AI Chat Bot', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'edit_item'     => _x( 'Edit AI Chat Bot', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'new_item'      => _x( 'New AI Chat Bot', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'featured_image'        => _x( 'AI Chat Bot Avatar', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'set_featured_image'    => _x( 'Set AI Chat Bot avatar', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'remove_featured_image' => _x( 'Remove AI Chat Bot avatar', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                    'use_featured_image'    => _x( 'Use as AI Chat Bot avatar', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                ],
                'publicly_queryable'   => false,
                'show_ui'              => true,
                'show_in_menu'         => 'bp-better-messages',
                'menu_position'        => 1,
                'query_var'            => false,
                'capability_type'      => 'page',
                'has_archive'          => false,
                'hierarchical'         => false,
                'show_in_admin_bar'    => false,
                'show_in_nav_menus'    => false,
                'supports'             => array( 'title', 'thumbnail' ),
                'register_meta_box_cb' => array( $this, 'register_meta_box' )

            );

            register_post_type( 'bm-ai-chat-bot', $args );
        }

        public function register_meta_box()
        {
            add_meta_box(
                'bm-ai-chat-bot-settings',
                _x( 'Settings', 'Chat rooms settings page', 'bp-better-messages' ),
                array( $this, 'bot_settings' ),
                null,
                'advanced'
            );
        }

        public function bot_settings( $post )
        {
            $roles = get_editable_roles();
            if(isset($roles['administrator'])) unset( $roles['administrator'] );

            $roles['bm-guest'] = [
                'name' => _x('Guests', 'Settings page', 'bp-better-messages' )
            ];

            $settings = $this->get_bot_settings( $post->ID );

            wp_nonce_field( 'bm-save-ai-chat-bot-settings-' . $post->ID, 'bm_save_ai_chat_bot_nonce' );

            $bot = $this->get_bot_user( $post->ID );
            $voices = $this->get_voices();
            $bot_user_id = $bot ? absint($bot->id) * -1 : 0;

            $openai_error = get_option( 'better_messages_openai_error', false );
            $api_key_exists = ! empty(Better_Messages()->settings['openAiApiKey']) && empty($openai_error);

            $voice_messages_banner = '';
            if( ! class_exists('BP_Better_Messages_Voice_Messages') ){
                $voice_messages_banner = '<div class="bp-better-messages-banner bm-error">';
                $voice_messages_banner .= sprintf(_x('<a href="%s" target="_blank">Voice Messages</a> add-on is required to use audio models.', 'Settings page', 'bp-better-messages'), admin_url('admin.php?page=bp-better-messages-addons') );
                $voice_messages_banner .= '</div>';
            }

            if (version_compare(phpversion(), '8.1', '<')) { ?>
            <div class="bm-admin-error" style="font-size: 150%;margin: 10px 0">
                <?php echo sprintf(esc_html_x('Website must to have PHP version %s or higher, currently PHP version %s is used.', 'Settings page', 'bp-better-messages'), '<strong>8.1</strong>', '<strong>' . phpversion() . '</strong>' ); ?>
            </div>
            <?php } else if ( ! $api_key_exists ){ ?>
                <div class="bm-admin-error" style="font-size: 150%;margin: 10px 0">
                    <?php echo sprintf(_x('Website must have valid Open AI Api Key, setup key at <a href="%s">settings page</a>.', 'Settings page', 'bp-better-messages'), add_query_arg( 'page', 'bp-better-messages', admin_url('admin.php') ) . '#integrations_openai' ); ?>
                </div>
            <?php } else  { ?>
            <div class="bm-ai-chat-bot-settings"
                 data-bot-id="<?php echo esc_attr($post->ID); ?>"
                 data-bot-user-id="<?php echo $bot_user_id; ?>"
                 data-settings="<?php echo esc_attr(json_encode($settings)); ?>"
                 data-roles="<?php echo esc_attr(json_encode($roles)); ?>"
                 data-voices="<?php echo esc_attr(json_encode($voices)); ?>"
                 data-voice-messages-banner="<?php echo esc_attr($voice_messages_banner); ?>">
                <p style="text-align: center"><?php _ex( 'Loading',  'WP Admin', 'bp-better-messages' ); ?></p>
            </div>
            <?php
            }
        }

        public function get_default_settings()
        {
            $voices = $this->get_voices();

            $defaults = array(
                "enabled" => "0",
                "images"  => "0",
                "imagesGeneration" => "0",
                "imagesGenerationModel" => "gpt-image-1-mini",
                "imagesGenerationQuality" => "auto",
                "imagesGenerationSize" => "auto",
                "files" => "0",
                "webSearch" => "0",
                "webSearchContextSize" => "medium",
                "fileSearch" => "0",
                "fileSearchVectorIds" => [],
                "serviceTier" => "auto",
                "model"   => "",
                "instruction" => _x( 'You are a helpful assistant', 'AI Chat Bots (WP Admin)', 'bp-better-messages' ),
                "voice" => $voices[0]
            );

            return $defaults;
        }

        public function get_voices()
        {
            return [
                'alloy',
                'ash',
                'ballad',
                'coral',
                'echo',
                'sage',
                'shimmer',
                'verse'
            ];
        }

        public function get_bot_settings( $bot_id )
        {
            $defaults = $this->get_default_settings();

            $args = get_post_meta( $bot_id, 'bm-ai-chat-bot-settings', true );

            if( empty( $args ) || ! is_array( $args ) ){
                $args = array();
            }

            if( ! isset( $args['images'] ) && ! empty($args['model'] )  ){
                $args['images'] = str_contains($args['model'], 'gpt-4-turbo') || str_contains($args['model'], 'gpt-4o') ? '1' : '0';
            }

            if( isset( $args['voice'] ) ){
                $voices = $this->get_voices();

                if( ! in_array( $args['voice'], $voices ) ){
                    $args['voice'] = $defaults['voice'];
                }
            }

            $result = wp_parse_args( $args, $defaults );

            return $result;
        }

        public function save_post( $post_id, $post ){
            if( ! isset($_POST['bm_save_ai_chat_bot_nonce']) ){
                return $post->ID;
            }

            //Verify it came from proper authorization.
            if ( ! wp_verify_nonce($_POST['bm_save_ai_chat_bot_nonce'], 'bm-save-ai-chat-bot-settings-' . $post->ID ) ) {
                return $post->ID;
            }

            //Check if the current user can edit the post
            if ( ! current_user_can( 'manage_options' ) ) {
                return $post->ID;
            }

            if( isset( $_POST['bm'] ) && is_array($_POST['bm']) ){
                $old_settings = $this->get_bot_settings( $post->ID );

                $settings = (array) $_POST['bm'];

                if( ! $settings['model'] ){
                    $settings['model'] = $old_settings['model'];
                }

                if( ! empty( $settings['fileSearchVectorIds'] ) ){
                    $lines = explode( "\n", $settings['fileSearchVectorIds']);

                    $vector_ids = [];

                    $added_lines = 0;
                    foreach( $lines as $line ){
                        $line = trim( $line );
                        if( ! empty( $line ) ){
                            $vector_ids[] = $line;
                            $added_lines++;
                        }

                        if( $added_lines == 2 ){
                            break;
                        }
                    }

                    $settings['fileSearchVectorIds'] = array_unique( $vector_ids );
                } else {
                    $settings['fileSearchVectorIds'] = [];
                }

                $defaults = $this->get_default_settings();

                $settings = wp_parse_args( $settings, $defaults );

                update_post_meta( $post->ID, 'bm-ai-chat-bot-settings', $settings );

                $this->create_or_update_bot_user( $post->ID, $post->post_title );
            }
        }

        public function get_bot_user( $bot_id )
        {
            $bot_user = wp_cache_get( 'bot_user_' . $bot_id, 'bm_messages' );

            if( $bot_user ){
                return $bot_user;
            }

            global $wpdb;

            $query = $wpdb->prepare( "SELECT * FROM `" . bm_get_table('guests') . "` WHERE `ip` = %s AND `deleted_at` IS NULL", "ai-chat-bot-" . $bot_id );

            $guest_user = $wpdb->get_row( $query );

            if( $guest_user ){
                wp_cache_set( 'bot_user_' . $bot_id, $guest_user, 'bm_messages' );

                return $guest_user;
            } else {
                return false;
            }
        }

        public function create_or_update_bot_user( $bot_id, $name )
        {
            $bot = $this->get_bot_user( $bot_id );

            if( $bot ){
                if( $bot->name != $name ){
                    global $wpdb;

                    $wpdb->update( bm_get_table('guests'), ['name' => $name], ['id' => $bot->id] );
                    do_action( 'better_messages_guest_updated', absint($bot->id) * -1 );
                    do_action( 'better_messages_user_updated', absint($bot->id) * -1 );
                }
            } else {
                global $wpdb;

                $result = $wpdb->insert( bm_get_table('guests'), [
                    'ip'     => "ai-chat-bot-" . $bot_id,
                    'name'   => $name,
                    'secret' => ''
                ] );

                if( $result ) {
                    $bot_id = $wpdb->insert_id;
                    do_action('better_messages_guest_updated', absint($bot_id) * -1);
                    do_action('better_messages_user_updated', absint($bot_id) * -1);
                }
            }
        }

        public function rest_thread_item( $thread_item, $thread_id, $thread_type, $include_personal, $user_id ){
            if( $thread_type !== 'thread'){
                return $thread_item;
            }

            $recipients = $thread_item['participants'];
            if( count( $recipients ) === 2 ){
                foreach( $recipients as $user_id ){
                    if( $user_id < 0 ) {
                        $guest_id = absint($user_id);
                        $guest = Better_Messages()->guests->get_guest_user($guest_id);

                        if ( $guest && $guest->ip && str_starts_with($guest->ip, 'ai-chat-bot-') ) {
                            $bot_id = str_replace('ai-chat-bot-', '', $guest->ip);
                            if ( $this->is_bot_conversation($bot_id, $thread_id) ) {
                                $settings = $this->get_bot_settings($bot_id);

                                $thread_item['botId'] = (int) $bot_id;
                                $thread_item['permissions']['canAudioCall'] = false;
                                $thread_item['permissions']['canVideoCall'] = false;
                                $thread_item['permissions']['canEditOwnMessages'] = false;
                                $thread_item['permissions']['canDeleteOwnMessages'] = false;
                                $thread_item['permissions']['canDeleteAllMessages'] = false;
                                $thread_item['permissions']['canInvite'] = false;
                                $thread_item['permissions']['preventReplies'] = true;

                                $thread_item['permissions']['preventVoiceMessages'] = ( ! str_contains($settings['model'], '-audio-') || ! class_exists('BP_Better_Messages_Voice_Messages') );

                                if (isset($thread_item['permissions']['canUpload'])) {
                                    $support_images = $settings['images'];
                                    $support_files = true;

                                    $thread_item['permissions']['canUpload'] = (bool) $support_images;

                                    $formats = [];

                                    if ( $support_images ) {
                                        $formats[] = '.png';
                                        $formats[] = '.jpg';
                                        $formats[] = '.jpeg';
                                        $formats[] = '.gif';
                                        $formats[] = '.webp';
                                    }

                                    if( $support_files ) {
                                        $formats[] = '.pdf';
                                    }

                                    if( count($formats) > 0 ){
                                        $thread_item['permissions']['canUploadExtensions'] = $formats;
                                        $thread_item['permissions']['canUploadMaxSize'] = 20;
                                        $thread_item['permissions']['totalMaxUploadSize'] = 50;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return $thread_item;
        }

        public function before_delete_message( $message_id, $thread_id, $deleteMethod )
        {
            try {
                $message = Better_Messages()->functions->get_message($message_id);

                if ( $message ) {
                    if (str_starts_with($message->message, '<!-- BM-AI -->')) {
                        $open_ai_conversation = Better_Messages_OpenAI_API::instance()->get_open_ai_conversation($message->thread_id);

                        if (is_wp_error($open_ai_conversation)) {
                            return;
                        }

                        if (!isset($open_ai_conversation['id'])) {
                            return;
                        }

                        $open_ai_conversation_id = $open_ai_conversation['id'];

                        $open_ai_message_id = Better_Messages()->functions->get_message_meta($message_id, 'openai_message_id');

                        if ( ! $open_ai_message_id) {
                            return;
                        }

                        $this->api->delete_conversation_message( $open_ai_conversation_id, $open_ai_message_id );

                        if( defined('BM_DEBUG') ) {
                            file_put_contents(ABSPATH . 'open-ai.log', time() . ' - deleted_message - ' . print_r( "$open_ai_conversation_id, $open_ai_message_id", true ) . "\n", FILE_APPEND | LOCK_EX);
                        }
                    }
                }
            } catch (Throwable $e) {
                // silent fail if happens
            }
        }

        public function on_message_sent( $message )
        {
            // Sender ID
            $sender_id = (int) $message->sender_id;

            $new_thread = $message->new_thread;

            // Recipients User IDs
            $recipients = Better_Messages()->functions->get_recipients( (int) $message->thread_id );

            if( count( $recipients ) === 2 ){
                foreach ($recipients as $recipient){
                    $user_id = (int) $recipient->user_id;

                    if( $sender_id !== $user_id && $user_id < 0 ){
                        $guest_id = absint($user_id);
                        $guest = Better_Messages()->guests->get_guest_user( $guest_id );

                        if( $guest && $guest->ip && str_starts_with($guest->ip, 'ai-chat-bot-') ){
                            $bot_id = (int) str_replace('ai-chat-bot-', '', $guest->ip);

                            if( $this->bot_exists( $bot_id ) && ( $this->is_bot_conversation( $bot_id, $message->thread_id ) || $new_thread ) ){
                                global $wpdb;

                                $bot_settings = $this->get_bot_settings( $bot_id );
                                Better_Messages()->functions->update_message_meta($message->id, 'ai_bot_id', $bot_id);
                                Better_Messages()->functions->update_message_meta($message->id, 'ai_waiting_for_response', time());
                                Better_Messages()->functions->update_thread_meta($message->thread_id, 'ai_waiting_for_response', time());

                                do_action('better_messages_thread_self_update', $message->thread_id, $sender_id);
                                do_action('better_messages_thread_updated', $message->thread_id, $sender_id);

                                $table = bm_get_table('messages');
                                $wpdb->query( $wpdb->prepare( "UPDATE `{$table}` SET `message` = CONCAT(%s, `message`) WHERE `id` = %d;", '<!-- BM-AI -->', $message->id ) );

                                if ( ! empty( Better_Messages()->settings['openAiApiKey'] ) && ! empty( $bot_settings['model'] ) ) {
                                    // Ensure create response trigger in case something goes wrong
                                    if( ! wp_get_scheduled_event( 'better_messages_ai_bot_ensure_completion', [ $bot_id, $message->id ] ) ){
                                        wp_schedule_single_event( time() + 15, 'better_messages_ai_bot_ensure_completion', [ $bot_id, $message->id ] );
                                    }

                                    $url = add_query_arg([
                                        'bot_id' => $bot_id,
                                        'message_id' => $message->id
                                    ], Better_Messages()->functions->get_rest_api_url() . 'ai/createResponse');

                                    wp_remote_get( $url, [
                                        'blocking' => false,
                                        'timeout' => 0
                                    ] );
                                }
                            }
                        }
                    }
                }
            }
        }

        public function ai_bot_ensure_completion( $bot_id, $message_id )
        {
            $this->api->process_reply( $bot_id, $message_id );
        }
    }

    function Better_Messages_AI(){
        return Better_Messages_AI::instance();
    }
}
