<?php
/**
 * Plugin Name: AskAgento
 * Plugin URI: https://www.askagento.com
 * Description: AI catalogue search by natural language and by image. Chatbot, recommendations and agents. Auto filter and auto labelling.
 * Version: 1.0.7
 * Author: VisualSearch GmbH
 * Author URI: https://www.visualsearch.at
 * License: GPLv2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: askagento
 * Requires at least: 7.0
 * Requires PHP: 8.1
 * Requires Plugins: woocommerce
 */

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

add_action('before_woocommerce_init', static function () {
    if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
    }
});

define('ASKAGENTO_VERSION', '1.0.7');
// Public API base, including the version segment (api.askagento.com/v1).
define('ASKAGENTO_API_BASE', 'https://api.askagento.com/v1');
define('ASKAGENTO_PLUGIN_FILE', __FILE__);
define('ASKAGENTO_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('ASKAGENTO_PLUGIN_URL', plugin_dir_url(__FILE__));

/**
 * Bust browser/CDN caches when plugin assets change (file mtime beats a static ASKAGENTO_VERSION).
 *
 * @param string $relative_path Path under the plugin dir, e.g. assets/js/front.js
 */
function askagento_asset_version($relative_path) {
    $full = ASKAGENTO_PLUGIN_DIR . ltrim(str_replace('\\', '/', (string) $relative_path), '/');

    if (is_readable($full)) {
        $m = filemtime($full);

        if ($m) {
            return (string) $m;
        }
    }

    return ASKAGENTO_VERSION;
}

// Prefixes
define('ASKAGENTO_TAX_PREFIX', '_askagento_t_');
define('ASKAGENTO_META_PREFIX', '_askagento_m_');
define('ASKAGENTO_NUM_PREFIX', '_askagento_n_');
define('ASKAGENTO_AI_PREFIX', '_askagento_a_');

/**
 * Public query-var names derived from published Auto Filter configs.
 *
 * Built only after `init` so WooCommerce and other plugins finish registering
 * CPTs/taxonomies and loading translations (WP 6.7+ JIT textdomain notices).
 *
 * @return array<int, string>
 */
function askagento_collect_product_filter_query_var_names() {
    static $done = false;
    static $names = [];

    if ($done) {
        return $names;
    }

    if (!did_action('init')) {
        return [];
    }

    $done = true;

    $filters = get_posts([
        'post_type'   => ASKAGENTO_POST_TYPE,
        'post_status' => 'publish',
        'numberposts' => -1,
        'fields'      => 'ids',
    ]);
    foreach ($filters as $fid) {
        $fields = askagento_get_fields($fid);
        if (empty($fields)) {
            continue;
        }
        foreach ($fields as $field) {
            $parts = explode(':', $field['source'], 2);
            if (count($parts) !== 2) {
                continue;
            }
            $field_name = askagento_get_field_name($parts[0], $parts[1]);
            $names[] = $field_name;
            if ($field['type'] === 'range') {
                $names[] = $field_name . '_min';
                $names[] = $field_name . '_max';
            }
        }
    }

    return $names;
}


add_action('init', static function () {
    askagento_collect_product_filter_query_var_names();
}, 20);


add_filter('query_vars', 'askagento_register_query_vars');
function askagento_register_query_vars($vars) {
    foreach (askagento_collect_product_filter_query_var_names() as $name) {
        $vars[] = $name;
    }

    return $vars;
}

// Load files
require_once ASKAGENTO_PLUGIN_DIR . 'includes/post-types.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/data-sources.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/frontend.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/query.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/cache.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/counts.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/filter-products-ajax.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/widget.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/install.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/billing.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/catalogue_sync.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/recommend_upsell.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/recommend_cross_sell.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/llm_api_keys.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/search_text.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/search_image.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/chatbot.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/filtering.php';
require_once ASKAGENTO_PLUGIN_DIR . 'includes/labelling.php';

if (is_admin()) {
    require_once ASKAGENTO_PLUGIN_DIR . 'admin/admin.php';
    require_once ASKAGENTO_PLUGIN_DIR . 'admin/settings.php';
    require_once ASKAGENTO_PLUGIN_DIR . 'admin/settings_agents.php';
}

/**
 * Welcome + consent notices only on the Plugins screen (after WP "Activate"), not site-wide.
 */
function askagento_is_plugins_admin_screen() {
    global $pagenow;

    return is_admin()
        && isset($pagenow)
        && $pagenow === 'plugins.php'
        && current_user_can('activate_plugins');
}

/**
 * Current admin request targets plugins.php (works before $pagenow is always set).
 */
function askagento_is_plugins_php_request() {
    if (!is_admin()) {
        return false;
    }

    global $pagenow;

    if (!empty($pagenow) && $pagenow === 'plugins.php') {
        return true;
    }

    $self = isset($_SERVER['PHP_SELF']) ? wp_basename(sanitize_file_name(wp_unslash($_SERVER['PHP_SELF']))) : '';

    return ($self === 'plugins.php');
}

/**
 * URL flags WordPress adds right after activating plugin(s).
 */
function askagento_request_has_wp_plugin_activate_query() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only WordPress core activation flag; not user-submitted form data.
    if (isset($_GET['activate']) && sanitize_text_field(wp_unslash($_GET['activate'])) === 'true') {
        return true;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only WordPress core activation flag; not user-submitted form data.
    if (isset($_GET['activate-multi']) && sanitize_text_field(wp_unslash($_GET['activate-multi'])) === 'true') {
        return true;
    }

    return false;
}

function askagento_clear_consent_dialog_meta_for_current_user() {
    $uid = get_current_user_id();

    if (!$uid) {
        return;
    }

    delete_user_meta($uid, 'askagento_show_consent_dialog');
    delete_user_meta($uid, 'askagento_onboarding_welcome');
}

/**
 * Open consent dialog from Plugins row (“Complete setup” link).
 */
function askagento_handle_plugins_open_consent_request() {
    if (!is_admin()) {
        return;
    }

    if (!askagento_is_plugins_php_request() || empty($_GET['askagento_open_consent'])) {
        return;
    }

    if (!current_user_can('activate_plugins')) {
        return;
    }

    if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), 'askagento_open_consent')) {
        wp_safe_redirect(admin_url('plugins.php'));
        exit;
    }

    if (!get_option('askagento_consent_required')) {
        wp_safe_redirect(admin_url('plugins.php'));
        exit;
    }

    $uid = get_current_user_id();

    if (!$uid) {
        return;
    }

    update_user_meta($uid, 'askagento_show_consent_dialog', true);
    update_user_meta($uid, 'askagento_onboarding_welcome', true);
    wp_safe_redirect(admin_url('plugins.php'));
    exit;
}
add_action('admin_init', 'askagento_handle_plugins_open_consent_request', 6);

/**
 * Consume WP's ?activate=true: store one-shot banner for this user and land on clean Plugins URL.
 */
function askagento_redirect_after_wp_plugin_activation_banner() {
    if (!is_admin()) {
        return;
    }

    if (!askagento_is_plugins_php_request()) {
        return;
    }

    if (!get_option('askagento_consent_required')) {
        return;
    }

    if (!current_user_can('activate_plugins')) {
        return;
    }

    if (!askagento_request_has_wp_plugin_activate_query()) {
        return;
    }

    $uid = get_current_user_id();

    if (!$uid) {
        return;
    }

    update_user_meta($uid, 'askagento_show_consent_dialog', true);
    update_user_meta($uid, 'askagento_onboarding_welcome', true);
    wp_safe_redirect(admin_url('plugins.php'));
    exit;
}
add_action('admin_init', 'askagento_redirect_after_wp_plugin_activation_banner', 7);

/**
 * WP-CLI activation (e.g. wp plugin activate) has no ?activate=true browser redirect - unlock onboarding for the first admin who opens Plugins.
 */
function askagento_unlock_onboarding_after_cli_plugin_activation() {
    if (!is_admin() || !askagento_is_plugins_php_request()) {
        return;
    }

    if (!get_option('askagento_unlock_onboarding_next_admin')) {
        return;
    }

    if (!get_option('askagento_consent_required')) {
        delete_option('askagento_unlock_onboarding_next_admin');
        return;
    }

    if (!is_user_logged_in() || !current_user_can('activate_plugins')) {
        return;
    }

    $uid = get_current_user_id();

    if (!$uid) {
        return;
    }

    update_user_meta($uid, 'askagento_show_consent_dialog', true);
    update_user_meta($uid, 'askagento_onboarding_welcome', true);
    delete_option('askagento_unlock_onboarding_next_admin');
}
add_action('admin_init', 'askagento_unlock_onboarding_after_cli_plugin_activation', 9);

/**
 * Show consent panel again same request as install retries (URLs with ?askagento_install=…).
 */
function askagento_maybe_reopen_consent_after_install_error() {
    if (!is_admin()) {
        return;
    }

    if (!askagento_is_plugins_php_request()) {
        return;
    }

    if (!get_option('askagento_consent_required')) {
        return;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only plugin install-status flag; sanitized and allowlist-validated below.
    if (empty($_GET['askagento_install'])) {
        return;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only plugin install-status flag; sanitized and allowlist-validated below.
    $slug = sanitize_key(wp_unslash($_GET['askagento_install']));

    if (!in_array($slug, ['no_products', 'failed', 'api_failed'], true)) {
        return;
    }

    if (!current_user_can('activate_plugins')) {
        return;
    }

    $uid = get_current_user_id();

    if (!$uid) {
        return;
    }

    update_user_meta($uid, 'askagento_show_consent_dialog', true);
    delete_user_meta($uid, 'askagento_onboarding_welcome');
}
add_action('admin_init', 'askagento_maybe_reopen_consent_after_install_error', 15);

/**
 * Handle post-activation consent actions.
 */
function askagento_handle_consent_actions() {
    if (!is_admin()) {
        return;
    }

    if (empty($_GET['askagento_consent_action']) || empty($_GET['_wpnonce'])) {
        return;
    }

    if (!current_user_can('activate_plugins')) {
        return;
    }

    if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'askagento_consent_action')) {
        return;
    }

    $action = sanitize_key(wp_unslash($_GET['askagento_consent_action']));

    if ($action === 'accept') {
        update_option('askagento_data_transfer_consent', 'accepted', false);

        if (!askagento_install_api_is_enabled()) {
            delete_option('askagento_consent_required');
            askagento_clear_consent_dialog_meta_for_current_user();
            wp_safe_redirect(admin_url('plugins.php?askagento_consent=accepted'));
            exit;
        }

        $result = askagento_send_install_data(true);
        if (is_wp_error($result)) {
            $code = $result->get_error_code();
            $slug = ($code === 'no_products') ? 'no_products' : 'failed';
            wp_safe_redirect(admin_url('plugins.php?askagento_install=' . $slug));
            exit;
        }

        $last_status = get_option('askagento_install_last_status', '');
        if ($last_status === 'error') {
            wp_safe_redirect(admin_url('plugins.php?askagento_install=api_failed'));
            exit;
        }

        delete_option('askagento_consent_required');
        askagento_clear_consent_dialog_meta_for_current_user();
        wp_safe_redirect(admin_url('plugins.php?askagento_install=started'));
        exit;
    }

    if ($action === 'decline') {
        askagento_clear_consent_dialog_meta_for_current_user();
        update_option('askagento_data_transfer_consent', 'declined', false);
        deactivate_plugins(plugin_basename(__FILE__));
        wp_safe_redirect(admin_url('plugins.php?deactivate=true&askagento_consent=declined'));
        exit;
    }
}
add_action('admin_init', 'askagento_handle_consent_actions');

/**
 * Remove legacy options from older releases (prevent duplicate / site-wide notices).
 */
function askagento_activation_admin_cleanup_legacy_options() {
    if (!is_admin()) {
        return;
    }
    delete_option('askagento_welcome_notice');
    delete_option('askagento_install_activation_pending');
    delete_option('askagento_show_welcome_on_plugins');
}
add_action('admin_init', 'askagento_activation_admin_cleanup_legacy_options', 5);

// Hooks
register_activation_hook(__FILE__, 'askagento_activate');
register_deactivation_hook(__FILE__, 'askagento_deactivate');
register_uninstall_hook(__FILE__, 'askagento_uninstall');
add_action('init', 'askagento_register_post_type');

/**
 * Add quick Settings link on Plugins page.
 */
add_filter('plugin_action_links_' . plugin_basename(__FILE__), function($links) {
    if (get_option('askagento_consent_required') && current_user_can('activate_plugins')) {
        $open_url = wp_nonce_url(
            admin_url('plugins.php?askagento_open_consent=1'),
            'askagento_open_consent'
        );
        $open_link = '<a href="' . esc_url($open_url) . '">' . esc_html__('Complete setup', 'askagento') . '</a>';
        array_unshift($links, $open_link);
    }

    $settings_url = admin_url('edit.php?post_type=' . ASKAGENTO_POST_TYPE . '&page=askagento-settings');
    $settings_link = '<a href="' . esc_url($settings_url) . '">' . esc_html__('Settings', 'askagento') . '</a>';
    array_unshift($links, $settings_link);
    return $links;
});

/**
 * Activate plugin
 */
function askagento_activate() {
    askagento_register_post_type();
    askagento_create_tables();
    flush_rewrite_rules();
    update_option('askagento_consent_required', 1, false);
    add_option('askagento_activated_at', gmdate('Y-m-d'), '', false);

    if (function_exists('askagento_schedule_filter_cache_rebuild_all_published')) {
        askagento_schedule_filter_cache_rebuild_all_published();
    }

    if (function_exists('askagento_recommend_upsell_reset_activity_options')) {
        askagento_recommend_upsell_reset_activity_options();
    }

    if (function_exists('askagento_recommend_upsell_maybe_schedule_cron')) {
        askagento_recommend_upsell_maybe_schedule_cron();
    }

    if (function_exists('askagento_recommend_cross_sell_maybe_schedule_cron')) {
        askagento_recommend_cross_sell_maybe_schedule_cron();
    }

    if (function_exists('askagento_catalogue_sync_maybe_schedule_cron')) {
        askagento_catalogue_sync_maybe_schedule_cron();
    }

    // Browser: ?activate=true → askagento_redirect_after_wp_plugin_activation_banner. CLI: no redirect → flag for first Plugins visit.
    if ((defined('WP_CLI') && WP_CLI) || PHP_SAPI === 'cli') {
        update_option('askagento_unlock_onboarding_next_admin', 1, false);
    }
}

/**
 * Deactivate plugin
 */
function askagento_deactivate() {
    delete_option('askagento_unlock_onboarding_next_admin');

    // Best effort request: deactivation should notify backend to remove indexed data.
    if (function_exists('askagento_send_uninstall_data')) {
        $uninstall_result = askagento_send_uninstall_data();
    }

    if (function_exists('askagento_recommend_upsell_unschedule_cron')) {
        askagento_recommend_upsell_unschedule_cron();
    }

    if (function_exists('askagento_recommend_cross_sell_unschedule_cron')) {
        askagento_recommend_cross_sell_unschedule_cron();
    }

    if (function_exists('askagento_catalogue_sync_unschedule_cron')) {
        askagento_catalogue_sync_unschedule_cron();
    }

    flush_rewrite_rules();
}

/**
 * Uninstall plugin and notify remote API to remove indexed data
 */
function askagento_uninstall() {
    if (!function_exists('askagento_send_uninstall_data')) {
        require_once ASKAGENTO_PLUGIN_DIR . 'includes/install.php';
    }

    require_once ASKAGENTO_PLUGIN_DIR . 'includes/uninstall-cleanup.php';

    // Best effort request - uninstall must continue even if API is unreachable
    askagento_send_uninstall_data();

    askagento_plugin_uninstall_cleanup();
}

/**
 * Consent onboarding: persists on the Plugins screen until the user accepts or declines
 * (askagento_clear_consent_dialog_meta_for_current_user() clears the flags in askagento_handle_consent_actions()).
 */
add_action('admin_notices', function() {
    if (!askagento_is_plugins_admin_screen()) {
        return;
    }

    if (!get_option('askagento_consent_required')) {
        return;
    }

    $uid = get_current_user_id();

    if (!$uid || !get_user_meta($uid, 'askagento_show_consent_dialog', true)) {
        return;
    }

    $show_welcome = (bool) get_user_meta($uid, 'askagento_onboarding_welcome', true);

    $nonce = wp_create_nonce('askagento_consent_action');
    $accept_url = add_query_arg([
        'askagento_consent_action' => 'accept',
        '_wpnonce'          => $nonce,
    ], admin_url('plugins.php'));
    $decline_url = add_query_arg([
        'askagento_consent_action' => 'decline',
        '_wpnonce'          => $nonce,
    ], admin_url('plugins.php'));
    ?>
    <div class="notice notice-warning askagento-askagento-onboarding">
        <?php if ($show_welcome) : ?>
            <h2 style="margin:0 0 8px;font-size:1.15em;"><?php esc_html_e('Welcome to AskAgento', 'askagento'); ?></h2>
            <p><?php esc_html_e('Thanks for activating the plugin. Complete the step below once; your catalog is sent only after you click I Agree.', 'askagento'); ?></p>
            <ul style="list-style:disc;margin:0 0 12px 1.25em;">
                <li><?php esc_html_e('No personal customer data is required for this activation.', 'askagento'); ?></li>
            </ul>
            <p style="margin:0 0 12px;">
                <a href="https://askagento.com/v1/privacy.html" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Privacy Policy', 'askagento'); ?></a>
            </p>
        <?php endif; ?>
        <p><strong><?php esc_html_e('Consent required', 'askagento'); ?></strong></p>
        <p><?php esc_html_e('To use AskAgento, agree to transferring product catalogue data from this shop to our servers.', 'askagento'); ?></p>
        <p>
            <a href="<?php echo esc_url($accept_url); ?>" class="button button-primary"><?php esc_html_e('I Agree', 'askagento'); ?></a>
            <a href="<?php echo esc_url($decline_url); ?>" class="button"><?php esc_html_e('Decline and Deactivate', 'askagento'); ?></a>
        </p>
    </div>
    <?php
});

/**
 * Welcome after consent recorded (install API off or similar).
 */
add_action('admin_notices', function() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only plugin consent flag; sanitized and compared against a fixed string.
    if (!askagento_is_plugins_admin_screen() || empty($_GET['askagento_consent'])) {
        return;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only plugin consent flag; sanitized and compared against a fixed string.
    if (sanitize_key(wp_unslash($_GET['askagento_consent'])) !== 'accepted') {
        return;
    }

    $settings_url = add_query_arg(
        'tab',
        'status',
        admin_url('edit.php?post_type=' . ASKAGENTO_POST_TYPE . '&page=askagento-settings')
    );
    ?>
    <div class="notice notice-success is-dismissible askagento-askagento-welcome-done">
        <h2 style="margin:0 0 8px;font-size:1.15em;"><?php esc_html_e('Welcome to AskAgento', 'askagento'); ?></h2>
        <p><?php esc_html_e('Consent is saved. Configure filters and search from AskAgento settings when you are ready.', 'askagento'); ?></p>
        <p><a href="<?php echo esc_url($settings_url); ?>" class="button button-primary"><?php esc_html_e('Open AskAgento settings', 'askagento'); ?></a></p>
    </div>
    <?php
});

/**
 * One-shot notice while remote install is still processing (non-polling admin screens).
 */
add_action('admin_notices', function() {
    if (!function_exists('askagento_should_show_install_processing_notice') || !askagento_should_show_install_processing_notice()) {
        return;
    }

    $settings_url = add_query_arg(
        'tab',
        'status',
        admin_url('edit.php?post_type=' . ASKAGENTO_POST_TYPE . '&page=askagento-settings')
    );
    ?>
    <div class="notice notice-info is-dismissible askagento-install-processing-notice">
        <p>
            <strong><?php esc_html_e('AskAgento', 'askagento'); ?></strong>
            <?php esc_html_e('Your product catalogue is being synced for AI search.', 'askagento'); ?>
            <a href="<?php echo esc_url($settings_url); ?>"><?php esc_html_e('View status', 'askagento'); ?></a>
        </p>
    </div>
    <?php
});

/**
 * One-shot notice after background install polling detects completion.
 */
add_action('admin_notices', function() {
    if (!current_user_can('manage_options')) {
        return;
    }

    if (!get_option('askagento_install_completion_notice_pending')) {
        return;
    }

    delete_option('askagento_install_completion_notice_pending');
    ?>
    <div class="notice notice-success is-dismissible askagento-install-completion-notice">
        <p>
            <strong><?php esc_html_e('AskAgento installation complete.', 'askagento'); ?></strong>
            <?php esc_html_e('Your product catalogue is ready for AI search.', 'askagento'); ?>
        </p>
    </div>
    <?php
});

/**
 * Persistent blocking notice while the catalogue exceeds the plan's product cap.
 *
 * AI features are disabled server-side and in the plugin until the merchant upgrades
 * or reduces the catalogue, so this notice is not dismissible.
 *
 * States the block only; the upgrade call to action lives on Settings → Plan so no
 * upgrade prompt appears on unrelated admin screens.
 */
add_action('admin_notices', function() {
    if (!current_user_can('manage_options')) {
        return;
    }
    if (!function_exists('askagento_is_over_product_limit') || !askagento_is_over_product_limit()) {
        return;
    }

    $site_id = trim((string) get_option('askagento_install_site_id', ''));
    $state = function_exists('askagento_get_product_limit_state')
        ? askagento_get_product_limit_state($site_id)
        : ['product_count' => null, 'max_products' => null, 'plan_label' => ''];

    $count = isset($state['product_count']) ? (int) $state['product_count'] : null;
    $max   = isset($state['max_products']) ? (int) $state['max_products'] : null;
    $plan  = !empty($state['plan_label']) ? (string) $state['plan_label'] : '';

    if ($count !== null && $max !== null && $plan !== '') {
        $text = sprintf(
            /* translators: 1: product count, 2: plan name, 3: plan product limit */
            esc_html__('Your catalogue has %1$d products, which exceeds the %2$s plan limit of %3$d. AskAgento is blocked until you upgrade your plan or reduce your catalogue.', 'askagento'),
            $count,
            $plan,
            $max
        );
    } else {
        $text = esc_html__('Your catalogue exceeds your plan\'s product limit. AskAgento is blocked until you upgrade your plan or reduce your catalogue.', 'askagento');
    }
    ?>
    <div class="notice notice-error askagento-product-limit-notice">
        <p>
            <strong><?php esc_html_e('AskAgento', 'askagento'); ?></strong>
            <?php echo esc_html($text); ?>
        </p>
    </div>
    <?php
});

/**
 * One-shot notices after consent + remote install attempt.
 */
add_action('admin_notices', function() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only plugin install-status flag; sanitized and allowlist-validated below.
    if (!askagento_is_plugins_admin_screen() || empty($_GET['askagento_install'])) {
        return;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only plugin install-status flag; sanitized and allowlist-validated below.
    $slug = sanitize_key(wp_unslash($_GET['askagento_install']));

    if ($slug === 'started') {
        $settings_url = add_query_arg(
            'tab',
            'status',
            admin_url('edit.php?post_type=' . ASKAGENTO_POST_TYPE . '&page=askagento-settings')
        );
        $product_count = function_exists('askagento_get_install_product_count')
            ? askagento_get_install_product_count()
            : 0;
        $eta_seconds = function_exists('askagento_estimate_install_seconds')
            ? askagento_estimate_install_seconds($product_count)
            : 0;
        $eta_display = function_exists('askagento_format_install_eta_display')
            ? askagento_format_install_eta_display($eta_seconds)
            : (string) $eta_seconds;
        $rate_display = function_exists('askagento_format_install_rate_display')
            ? askagento_format_install_rate_display()
            : '';
        ?>
        <div class="notice notice-success is-dismissible askagento-askagento-welcome-done">
            <h2 style="margin:0 0 8px;font-size:1.15em;"><?php esc_html_e('Welcome to AskAgento', 'askagento'); ?></h2>
            <p><?php esc_html_e('Thank you. Your consent is saved and your product catalogue is being synced.', 'askagento'); ?></p>
            <?php if ($product_count > 0 && $eta_seconds > 0) : ?>
                <p>
                    <strong><?php echo esc_html(sprintf(
                        /* translators: 1: product count, 2: human-readable duration, 3: products per second (one decimal) */
                        __('Syncing %1$d products. This installation usually takes about %2$s (~%3$s products/s).', 'askagento'),
                        $product_count,
                        $eta_display,
                        $rate_display
                    )); ?></strong><br>
                    <?php esc_html_e('You can stay on this page or continue working elsewhere; we will notify you when it is done.', 'askagento'); ?>
                </p>
            <?php endif; ?>
            <div id="askagento-install-poll-status" class="askagento-install-poll-status" style="margin:10px 0;"></div>
            <p><a href="<?php echo esc_url($settings_url); ?>" class="button button-primary"><?php esc_html_e('Open AskAgento settings', 'askagento'); ?></a></p>
        </div>
        <?php
        return;
    }

    $messages = [
        'no_products'  => [
            'class' => 'notice-warning',
            'text'  => __('No products were found to sync. Add products to your store, then click I Agree again to send your catalog.', 'askagento'),
        ],
        'failed'       => [
            'class' => 'notice-error',
            'text'  => __('Could not reach the AskAgento server. Check your internet connection and click I Agree again to retry.', 'askagento'),
        ],
        'api_failed' => [
            'class' => 'notice-error',
            'text'  => __('AskAgento returned an error. Click I Agree again to retry or contact support.', 'askagento'),
        ],
    ];

    if (!isset($messages[$slug])) {
        return;
    }

    $m = $messages[$slug];
    $detail = '';
    if ($slug === 'failed') {
        $stored = get_option('askagento_install_admin_notice');
        if (is_array($stored) && !empty($stored['text']) && is_string($stored['text'])) {
            $detail = $stored['text'];
        }
    }
    ?>
    <div class="notice <?php echo esc_attr($m['class']); ?> is-dismissible">
        <p><?php echo esc_html($m['text']); ?></p>
        <?php if ($detail !== '') : ?>
            <p><strong><?php esc_html_e('Details:', 'askagento'); ?></strong> <?php echo esc_html($detail); ?></p>
        <?php endif; ?>
    </div>
    <?php
});

/**
 * Create database tables
 */
function askagento_create_tables() {
    global $wpdb;

    $charset_collate = $wpdb->get_charset_collate();

    // Cache table
    $table_cache = $wpdb->prefix . 'askagento_cache';
    $sql_cache = "CREATE TABLE $table_cache (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        filter_id int(11) NOT NULL,
        post_id bigint(20) NOT NULL,
        post_parent_id bigint(20) NOT NULL DEFAULT 0,
        field_name varchar(255) NOT NULL,
        field_value varchar(255) NOT NULL DEFAULT '',
        field_value_num bigint(20) NULL,
        term_parent_id bigint(20) NULL DEFAULT 0,
        PRIMARY KEY (id),
        KEY askagento_filter_idx (filter_id),
        KEY askagento_filter_field_idx (filter_id, field_name(32)),
        KEY askagento_filter_field_value_idx (filter_id, field_name(32), field_value(32)),
        KEY askagento_filter_field_num_idx (filter_id, field_name(32), field_value_num),
        KEY askagento_post_id_idx (post_id)
    ) $charset_collate;";

    // Term results table
    $table_terms = $wpdb->prefix . 'askagento_term_results';
    $sql_terms = "CREATE TABLE $table_terms (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        filter_id int(11) NOT NULL,
        field_name varchar(255) NOT NULL,
        field_value varchar(255) NOT NULL,
        result_ids mediumtext NOT NULL,
        PRIMARY KEY (id),
        KEY askagento_tr_filter_idx (filter_id),
        KEY askagento_tr_filter_field_idx (filter_id, field_name(32)),
        KEY askagento_tr_filter_field_value_idx (filter_id, field_name(32), field_value(32))
    ) $charset_collate;";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql_cache);
    dbDelta($sql_terms);
}
