<?php
/**
 * AI Chatbot: storefront shortcode and frontend assets.
 *
 * The widget posts directly to the Askagento /chatbot API from the browser with the same
 * headers as text search (`X-Askagento-Site-Id`, `X-Askagento-Api-Key`);
 * no WordPress AJAX proxy is needed.
 * Discovery credentials are exposed to the storefront JS config - see readme.txt External services.
 */

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

/**
 * Default accent color for the floating chat bubble (matches askagento.com landing page).
 */
function askagento_ai_chatbot_default_bubble_color(): string {
    return '#0f172a';
}

/**
 * Welcome message shown when a shopper opens the chat panel (Setup → AI Chatbot).
 */
function askagento_ai_chatbot_welcome_message(): string {
    $default = __(
        'Hi! Ask me anything about our products. I\'m here to help.',
        'askagento'
    );
    $stored = get_option('askagento_ai_chatbot_welcome_message', $default);

    if (! is_string($stored)) {
        return $default;
    }

    return (string) apply_filters('askagento_ai_chatbot_welcome_message', $stored);
}

/**
 * Sanitize welcome message (AI Chatbot → Setup).
 */
function askagento_sanitize_ai_chatbot_welcome_message($value): string {
    return sanitize_textarea_field((string) $value);
}

/**
 * Whether the floating chat bubble is shown across the storefront.
 */
function askagento_ai_chatbot_bubble_enabled(): bool {
    $stored = get_option('askagento_ai_chatbot_bubble_enabled', true);
    $enabled = ! empty($stored) && ! in_array((string) $stored, ['0', 'false', 'off'], true);

    return (bool) apply_filters('askagento_ai_chatbot_bubble_enabled', $enabled);
}

/**
 * Sanitize storefront bubble toggle (AI Chatbot → Setup).
 */
function askagento_sanitize_ai_chatbot_bubble_enabled($value): bool {
    return ! empty($value) && ! in_array((string) $value, ['0', 'false', 'off'], true);
}

/**
 * Whether the "Powered by AskAgento" credit is shown in the chat panel.
 *
 * Opt-in: WordPress.org guideline 10 requires storefront credits to default to hidden.
 */
function askagento_ai_chatbot_powered_by_enabled(): bool {
    $stored = get_option('askagento_ai_chatbot_powered_by_enabled', false);
    $enabled = ! empty($stored) && ! in_array((string) $stored, ['0', 'false', 'off'], true);

    return (bool) apply_filters('askagento_ai_chatbot_powered_by_enabled', $enabled);
}

/**
 * Sanitize storefront credit toggle (AI Chatbot → Setup).
 */
function askagento_sanitize_ai_chatbot_powered_by_enabled($value): bool {
    return ! empty($value) && ! in_array((string) $value, ['0', 'false', 'off'], true);
}

/**
 * Accent color for the floating chat bubble and panel header.
 */
function askagento_ai_chatbot_bubble_color(): string {
    $stored = (string) get_option('askagento_ai_chatbot_bubble_color', askagento_ai_chatbot_default_bubble_color());

    if (! preg_match('/^#[0-9a-fA-F]{6}$/', $stored)) {
        $stored = askagento_ai_chatbot_default_bubble_color();
    }

    // Public demo shop uses the brand green bubble (matches the v1/v2 landing
    // pages), regardless of any stored/blue value.
    if (
        function_exists('askagento_recommend_cross_sell_is_demo_shop')
        && askagento_recommend_cross_sell_is_demo_shop()
    ) {
        $stored = '#14b873';
    }

    return (string) apply_filters('askagento_ai_chatbot_bubble_color', $stored);
}

/**
 * Sanitize bubble accent color (AI Chatbot → Setup).
 */
function askagento_sanitize_ai_chatbot_bubble_color($value): string {
    $color = sanitize_hex_color((string) $value);

    if (! is_string($color) || $color === '') {
        return askagento_ai_chatbot_default_bubble_color();
    }

    return $color;
}

/**
 * Panel header logo letter (bubble chat), e.g. "A".
 */
function askagento_ai_chatbot_panel_logo(): string {
    $stored = (string) get_option('askagento_ai_chatbot_panel_logo', 'A');
    $stored = trim($stored);

    if ($stored === '') {
        $stored = 'A';
    }

    if (function_exists('mb_substr')) {
        $stored = (string) mb_substr($stored, 0, 2);
    } else {
        $stored = substr($stored, 0, 2);
    }

    return (string) apply_filters('askagento_ai_chatbot_panel_logo', $stored);
}

/**
 * Sanitize panel logo letter (AI Chatbot → Setup).
 */
function askagento_sanitize_ai_chatbot_panel_logo($value): string {
    $logo = sanitize_text_field((string) $value);
    $logo = trim($logo);

    if ($logo === '') {
        return 'A';
    }

    if (function_exists('mb_substr')) {
        return (string) mb_substr($logo, 0, 2);
    }

    return substr($logo, 0, 2);
}

/**
 * Panel header title (bubble chat), e.g. "AskAgento".
 */
function askagento_ai_chatbot_panel_title(): string {
    $default = 'AskAgento';
    $stored  = get_option('askagento_ai_chatbot_panel_title', $default);

    if (! is_string($stored) || trim($stored) === '') {
        return $default;
    }

    return (string) apply_filters('askagento_ai_chatbot_panel_title', trim($stored));
}

/**
 * Sanitize panel title (AI Chatbot → Setup).
 */
function askagento_sanitize_ai_chatbot_panel_title($value): string {
    $title = sanitize_text_field((string) $value);

    return trim($title) !== '' ? trim($title) : 'AskAgento';
}

/**
 * Powered-by footer HTML for the bubble chat panel.
 *
 * Returns an empty string unless the shop owner opted in under AI Chatbot → Setup.
 *
 * @return string
 */
function askagento_ai_chatbot_powered_by_footer_html(): string {
    if (! askagento_ai_chatbot_powered_by_enabled()) {
        return '';
    }

    $url = (string) apply_filters('askagento_ai_chatbot_powered_by_url', 'https://askagento.com');

    return '<footer class="askagento-chatbot-panel__footer">'
        . esc_html__('Powered by', 'askagento')
        . ' <a href="' . esc_url($url) . '" target="_blank" rel="noopener noreferrer">AskAgento</a>'
        . '</footer>';
}

/**
 * True when the chatbot can be shown - delegates to text-search availability
 * (same credentials: registered site_id + api_key) so the check is consistent.
 */
function askagento_ai_chatbot_is_available() {
    if (!function_exists('askagento_ai_text_search_is_available') || !askagento_ai_text_search_is_available()) {
        return false;
    }

    return !function_exists('askagento_feature_is_enabled') || askagento_feature_is_enabled('ai_chatbot');
}

/**
 * Lightweight product index for matching assistant replies to catalogue cards.
 *
 * @return list<array{id: string, title: string, url: string, image: string, price: string}>
 */
function askagento_chatbot_frontend_catalog() {
    if (!function_exists('wc_get_products')) {
        return [];
    }

    $limit = (int) apply_filters('askagento_chatbot_catalog_index_limit', 250);

    if ($limit < 1) {
        $limit = 250;
    }

    if ($limit > 500) {
        $limit = 500;
    }

    $products = wc_get_products(
        [
            'status'  => 'publish',
            'limit'   => $limit,
            'orderby' => 'title',
            'order'   => 'ASC',
            'return'  => 'objects',
        ]
    );

    if (!is_array($products)) {
        return [];
    }

    $out = [];

    foreach ($products as $product) {
        if (!is_object($product) || !method_exists($product, 'get_id')) {
            continue;
        }

        $product_id = (int) $product->get_id();

        if ($product_id < 1) {
            continue;
        }

        $image_id  = $product->get_image_id();
        $image_url = $image_id ? wp_get_attachment_image_url((int) $image_id, 'woocommerce_thumbnail') : '';
        $price_raw = $product->get_price_html();
        $price     = is_string($price_raw) && $price_raw !== '' ? wp_strip_all_tags($price_raw) : '';

        $out[] = [
            'id'    => (string) $product_id,
            'title' => (string) $product->get_name(),
            'url'   => (string) get_permalink($product_id),
            'image' => is_string($image_url) && $image_url !== '' ? $image_url : '',
            'price' => $price,
        ];
    }

    return $out;
}

/**
 * AJAX: resolve chatbot product cards to image + permalink by exact title.
 *
 * The assistant reply is text only and names products by their exact catalogue
 * title. Rather than run data search per product (slow, and
 * demo-rate-limited), this does one direct DB lookup for all titles at once.
 *
 * POST params: nonce (askagento_ai_text_search), titles (JSON array of strings).
 */
function askagento_ajax_ai_chatbot_resolve_products() {
    check_ajax_referer('askagento_ai_text_search', 'nonce');

    $titles_raw = isset($_POST['titles']) ? sanitize_text_field(wp_unslash($_POST['titles'])) : '';
    $titles     = is_string($titles_raw) ? json_decode($titles_raw, true) : [];

    if (!is_array($titles)) {
        wp_send_json_success(['results' => []]);
    }

    $titles = array_values(array_unique(array_filter(array_map(
        static function ($t) {
            return is_string($t) ? sanitize_text_field($t) : '';
        },
        $titles
    ))));

    // Bound the work; a single reply only ever shows a handful of products.
    $titles = array_slice($titles, 0, 20);

    if (empty($titles) || !function_exists('askagento_ai_text_search_build_shop_result_entry')) {
        wp_send_json_success(['results' => []]);
    }

    global $wpdb;

    $placeholders = implode(',', array_fill(0, count($titles), '%s'));
    $sql          = "SELECT ID, post_title FROM {$wpdb->posts}
        WHERE post_status = 'publish'
          AND post_type IN ('product', 'product_variation')
          AND post_title IN ($placeholders)";

    $cache_key = 'askagento_chatbot_titles_' . md5((string) wp_json_encode($titles));
    $rows      = wp_cache_get($cache_key, 'askagento');

    if (false === $rows) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared -- Direct query required to resolve product titles to IDs in bulk for chatbot product-card lookup; placeholders built from fixed count.
        $rows = $wpdb->get_results($wpdb->prepare($sql, $titles));
        wp_cache_set($cache_key, $rows, 'askagento', 5 * MINUTE_IN_SECONDS);
    }

    $out = [];

    if (is_array($rows)) {
        foreach ($rows as $row) {
            $entry = askagento_ai_text_search_build_shop_result_entry((int) $row->ID, []);

            if ($entry === null) {
                continue;
            }

            $out[] = [
                'title'     => (string) $row->post_title,
                'image_url' => isset($entry['image_url']) ? (string) $entry['image_url'] : '',
                'permalink' => isset($entry['permalink']) ? (string) $entry['permalink'] : '',
            ];
        }
    }

    wp_send_json_success(['results' => $out]);
}

add_action('wp_ajax_askagento_ai_chatbot_resolve', 'askagento_ajax_ai_chatbot_resolve_products');
add_action('wp_ajax_nopriv_askagento_ai_chatbot_resolve', 'askagento_ajax_ai_chatbot_resolve_products');

/**
 * Enqueue chatbot frontend assets (idempotent).
 */
function askagento_enqueue_chatbot_frontend_assets() {
    static $done = false;

    if ($done) {
        return;
    }

    $done = true;

    // Register askagento-front style/script in case the product-filter widget is not on this page.
    if (!wp_style_is('askagento-front', 'registered')) {
        wp_register_style('askagento-front', ASKAGENTO_PLUGIN_URL . 'assets/css/front.css', [], askagento_asset_version('assets/css/front.css'));
    }

    wp_enqueue_style('askagento-front');

    wp_enqueue_script(
        'askagento-chatbot-reply-format',
        ASKAGENTO_PLUGIN_URL . 'assets/js/chatbot-reply-format.js',
        [],
        askagento_asset_version('assets/js/chatbot-reply-format.js'),
        true
    );

    wp_enqueue_script(
        'askagento-chatbot-front',
        ASKAGENTO_PLUGIN_URL . 'assets/js/front-chatbot.js',
        ['askagento-chatbot-reply-format'],
        askagento_asset_version('assets/js/front-chatbot.js'),
        true
    );

    $install = function_exists('askagento_get_install_settings') ? askagento_get_install_settings() : [];
    $api_url = isset($install['api_url']) ? rtrim((string) $install['api_url'], '/') : '';
    $site_id = (string) get_option('askagento_install_site_id', '');
    $api_key = isset($install['api_key']) ? trim((string) $install['api_key']) : '';

    $chatbot_url = ($api_url !== '' && $site_id !== '' && $api_key !== '')
        ? $api_url . '/chatbot'
        : '';

    $cfg = [
        'chatbotUrl'      => $chatbot_url,
        'siteId'          => $site_id,
        'apiKey'          => $api_key,
        // Used to fill product-card thumbnails the LLM reply references but the
        // local catalog index does not cover (see enrichProductImages in JS).
        'ajaxUrl'         => admin_url('admin-ajax.php'),
        'textSearchNonce' => wp_create_nonce('askagento_ai_text_search'),
        'catalog'         => askagento_chatbot_frontend_catalog(),
        'welcomeMessage'  => askagento_ai_chatbot_welcome_message(),
        'bubbleColor'     => askagento_ai_chatbot_bubble_color(),
        'panelTitle'      => askagento_ai_chatbot_panel_title(),
        'i18n'            => [
            'placeholder'           => __('Ask about our products...', 'askagento'),
            'send'                  => __('Send', 'askagento'),
            'error'                 => __('Something went wrong. Try again.', 'askagento'),
            'unavailable'           => __('Chatbot is not configured.', 'askagento'),
            'aiTokenQuotaExceeded'  => __('AI token quota exceeded.', 'askagento'),
            'aiSearchQuotaExceeded' => __('AI search quota exceeded.', 'askagento'),
            'openChat'              => __('Open chat', 'askagento'),
            'closeChat'             => __('Close chat', 'askagento'),
            'chatMessages'          => __('Chat messages', 'askagento'),
            'chatInput'             => __('Chat message input', 'askagento'),
            'sendMessage'           => __('Send message', 'askagento'),
            'thinking'              => __('Thinking', 'askagento'),
        ],
    ];

    /** @var false|string $json */
    $json = wp_json_encode($cfg);

    if (is_string($json)) {
        wp_add_inline_script(
            'askagento-chatbot-front',
            'window.askagentoAiChatbotFront=' . $json . ';',
            'before'
        );
    }
}

/**
 * Inline SVG icon for the floating chat bubble button.
 *
 * @return string
 */
function askagento_chatbot_fab_icon_svg() {
    return '<svg class="askagento-chatbot-fab__icon" width="26" height="26" viewBox="0 0 24 24" fill="none" aria-hidden="true">'
        . '<path fill="currentColor" d="M12 2.5C6.75 2.5 2.5 6.28 2.5 11c0 2.35 1.2 4.44 3.08 5.78L4 21.5l4.62-2.26c1.02.35 2.1.54 3.23.54 5.25 0 9.5-3.78 9.5-8.5S17.25 2.5 12 2.5z"/>'
        . '<circle cx="8.25" cy="11" r="1.1" fill="currentColor" opacity="0.45"/>'
        . '<circle cx="12" cy="11" r="1.1" fill="currentColor" opacity="0.45"/>'
        . '<circle cx="15.75" cy="11" r="1.1" fill="currentColor" opacity="0.45"/>'
        . '</svg>';
}

/**
 * Shared inner panel markup (messages + input).
 *
 * @param string $panel_id DOM id for the dialog panel.
 * @param bool   $hidden   Whether the panel starts hidden (bubble mode).
 * @return string
 */
function askagento_get_chatbot_panel_inner_html($panel_id, $hidden = false) {
    $panel_id = sanitize_key((string) $panel_id);

    if ($panel_id === '') {
        $panel_id = 'askagento-chatbot-panel';
    }

    $panel_title = askagento_ai_chatbot_panel_title();
    $panel_logo  = askagento_ai_chatbot_panel_logo();

    ob_start();
    ?>
    <div
        id="<?php echo esc_attr($panel_id); ?>"
        class="askagento-chatbot-panel"
        <?php echo $hidden ? 'hidden' : ''; ?>
        role="dialog"
        aria-label="<?php echo esc_attr($panel_title); ?>"
    >
        <header class="askagento-chatbot-panel__head">
            <div class="askagento-chatbot-panel__brand">
                <span class="askagento-chatbot-panel__logo" aria-hidden="true"><?php echo esc_html($panel_logo); ?></span>
                <span class="askagento-chatbot-panel__title"><?php echo esc_html($panel_title); ?></span>
            </div>
            <button type="button" class="askagento-chatbot-panel__close" aria-label="<?php esc_attr_e('Close chat', 'askagento'); ?>">×</button>
        </header>
        <div
            class="askagento-chatbot-messages"
            role="log"
            aria-live="polite"
            aria-label="<?php esc_attr_e('Chat messages', 'askagento'); ?>"
        ></div>
        <div class="askagento-chatbot-form">
            <textarea
                class="askagento-chatbot-input"
                rows="1"
                placeholder="<?php esc_attr_e('Ask about our products...', 'askagento'); ?>"
                aria-label="<?php esc_attr_e('Chat message input', 'askagento'); ?>"
            ></textarea>
            <button
                type="button"
                class="askagento-chatbot-send askagento-btn"
                aria-label="<?php esc_attr_e('Send message', 'askagento'); ?>"
            >&#8593;</button>
        </div>
        <div class="askagento-chatbot-status" aria-live="assertive"></div>
        <?php
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        echo askagento_ai_chatbot_powered_by_footer_html();
        ?>
    </div>
    <?php
    return (string) ob_get_clean();
}

/**
 * Inline chatbot widget (shortcode).
 *
 * @param string $suffix Safe DOM-id suffix.
 * @return string
 */
function askagento_get_chatbot_markup($suffix = '1') {
    $suffix = sanitize_key((string) $suffix);

    if ($suffix === '') {
        $suffix = '1';
    }

    $color = askagento_ai_chatbot_bubble_color();

    ob_start();
    ?>
    <div
        class="askagento-chatbot-root askagento-chatbot-root--inline"
        data-askagento-chatbot-root
        data-askagento-chatbot-mode="inline"
        style="--askagento-chatbot-accent: <?php echo esc_attr($color); ?>"
    >
        <div class="askagento-chatbot">
            <div
                class="askagento-chatbot-messages"
                role="log"
                aria-live="polite"
                aria-label="<?php esc_attr_e('Chat messages', 'askagento'); ?>"
            ></div>
            <div class="askagento-chatbot-form">
                <textarea
                    class="askagento-chatbot-input"
                    rows="1"
                    placeholder="<?php esc_attr_e('Ask about our products...', 'askagento'); ?>"
                    aria-label="<?php esc_attr_e('Chat message input', 'askagento'); ?>"
                ></textarea>
                <button
                    type="button"
                    class="askagento-chatbot-send askagento-btn"
                    aria-label="<?php esc_attr_e('Send message', 'askagento'); ?>"
                >&#8593;</button>
            </div>
            <div class="askagento-chatbot-status" aria-live="assertive"></div>
        </div>
    </div>
    <?php
    return (string) ob_get_clean();
}

/**
 * Floating chat bubble for shop / optional embed (landing-page style).
 *
 * @param string $suffix Safe DOM-id suffix.
 * @return string
 */
function askagento_get_chatbot_bubble_markup($suffix = 'shop') {
    $suffix   = sanitize_key((string) $suffix);
    $panel_id = 'askagento-chatbot-panel-' . ($suffix !== '' ? $suffix : 'shop');
    $color    = askagento_ai_chatbot_bubble_color();

    ob_start();
    ?>
    <div
        class="askagento-chatbot-root askagento-chatbot-root--bubble"
        data-askagento-chatbot-root
        data-askagento-chatbot-mode="bubble"
        style="--askagento-chatbot-accent: <?php echo esc_attr($color); ?>"
    >
        <button
            type="button"
            class="askagento-chatbot-fab"
            aria-expanded="false"
            aria-controls="<?php echo esc_attr($panel_id); ?>"
            aria-label="<?php esc_attr_e('Open chat', 'askagento'); ?>"
        >
            <?php
            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            echo askagento_chatbot_fab_icon_svg();
            ?>
        </button>
        <?php
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        echo askagento_get_chatbot_panel_inner_html($panel_id, true);
        ?>
    </div>
    <?php
    return (string) ob_get_clean();
}

/**
 * Shortcode: [askagento_chatbot] or [askagento_chatbot id="my-id"]
 *
 * @param array|string $atts
 * @return string
 */
function askagento_shortcode_ai_chatbot($atts) {
    if (!askagento_ai_chatbot_is_available()) {
        if (current_user_can('manage_options')) {
            return '<p style="padding:10px 14px;border:1px solid #c3c4c7;background:#fcf9e8;border-radius:6px;max-width:560px;">'
                . esc_html__(
                    'Askagento chatbot is hidden until this shop is registered and the Discovery API is configured. Finish installation under Askagento > Settings.',
                    'askagento'
                )
                . '</p>';
        }

        return '';
    }

    $atts = shortcode_atts(
        ['id' => '1'],
        is_array($atts) ? $atts : [],
        'askagento_chatbot'
    );

    askagento_enqueue_chatbot_frontend_assets();

    return askagento_get_chatbot_markup($atts['id']);
}

add_shortcode('askagento_chatbot', 'askagento_shortcode_ai_chatbot');

/**
 * Auto-inject floating bubble on public storefront pages.
 *
 * ON by default when AI Chatbot → Setup has the bubble enabled.
 * Disable with: add_filter('askagento_chatbot_bubble_on_storefront', '__return_false').
 */
function askagento_chatbot_show_bubble_on_storefront() {
    if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
        return false;
    }

    if (! askagento_ai_chatbot_bubble_enabled()) {
        return false;
    }

    if (! askagento_ai_chatbot_is_available()) {
        return false;
    }

    if (! (bool) apply_filters('askagento_chatbot_bubble_on_storefront', true)) {
        return false;
    }

    if (function_exists('is_feed') && is_feed()) {
        return false;
    }

    if (function_exists('is_embed') && is_embed()) {
        return false;
    }

    return true;
}

add_action('wp_enqueue_scripts', function () {
    if (askagento_chatbot_show_bubble_on_storefront()) {
        askagento_enqueue_chatbot_frontend_assets();
    }
}, 22);

add_action('wp_footer', function () {
    static $rendered = false;

    if ($rendered || ! askagento_chatbot_show_bubble_on_storefront()) {
        return;
    }

    $rendered = true;

    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    echo askagento_get_chatbot_bubble_markup('site');
}, 50);
