<?php
/**
 * Uninstall BoostBot
 *
 * This file runs when the plugin is uninstalled (deleted).
 * It removes all data created by the plugin.
 *
 * @package BoostBot
 * @since   1.0.0
 */

// phpcs:ignoreFile WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-scope variables set by the includer, not true globals.

// Exit if not called by WordPress
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit;
}

global $wpdb;

/**
 * Check if we should delete data on uninstall.
 * By default, we DO delete data. Users can change this in settings.
 */
$delete_data = get_option( 'boostbot_delete_data_on_uninstall', true );

if ( $delete_data ) {

    // =========================================================
    // 1. STOP BACKGROUND PROCESSES FIRST
    //    Prevent table locks and race conditions by pausing the
    //    indexer before dropping tables.
    // =========================================================
    update_option( 'boostbot_index_paused', true );

    /**
     * 2. DELETE ALL CUSTOM DATABASE TABLES
     *
     * This list MUST match BoostBot_DB_Manager::define_tables().
     * When adding new tables to the DB manager, add them here too.
     *
     * Uses a single DROP TABLE statement for atomicity.
     * Falls back to individual drops if the batch fails.
     */
    $tables_to_delete = array(
        // Core data tables
        'boostbot_leads',
        'boostbot_conversations',
        'boostbot_knowledge_index',
        'boostbot_knowledge_chunks',
        'boostbot_knowledge_raptor_nodes',
        'boostbot_index_queue',
        'boostbot_site_profile',
        'boostbot_widgets',
        'boostbot_form_fields',
        'boostbot_chatbot_widgets',
        'boostbot_analytics',
        'boostbot_cache',
        // Bot / personality tables
        'boostbot_bots',
        'boostbot_personalities',
        'boostbot_personality_traits',
        'boostbot_tones',
        // Contact / gallery tables
        'boostbot_contact_lists',
        'boostbot_contacts',
        'boostbot_galleries',
        'boostbot_gallery_images',
        // Preset tables
        'boostbot_appearance_presets',
        'boostbot_opening_screen_presets',
        // Feature tables
        'boostbot_meetings',
        'boostbot_widget_usage',
        'boostbot_bundles',
    );

    // Build fully-qualified table names
    $full_table_names = array();
    foreach ( $tables_to_delete as $table ) {
        $full_table_names[] = $wpdb->prefix . $table;
    }

    // Try batch DROP first (faster, atomic)
    $table_list = implode( ', ', $full_table_names );
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.NotPrepared
    $batch_result = $wpdb->query( "DROP TABLE IF EXISTS {$table_list}" );

    // If batch failed, fall back to individual drops
    if ( false === $batch_result ) {
        foreach ( $full_table_names as $table_name ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.NotPrepared
            $wpdb->query( "DROP TABLE IF EXISTS `{$table_name}`" );
        }
    }

    /**
     * 3. DELETE ALL PLUGIN OPTIONS
     *
     * Instead of maintaining a fragile hardcoded list, delete ALL
     * options with the boostbot_ prefix. This catches every option
     * including migration flags, settings, license data, etc.
     */
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query(
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        $wpdb->prepare(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
            $wpdb->esc_like( 'boostbot_' ) . '%'
        )
    );

    /**
     * 4. DELETE ALL TRANSIENTS
     */
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query(
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        $wpdb->prepare(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
            $wpdb->esc_like( '_transient_boostbot_' ) . '%',
            $wpdb->esc_like( '_transient_timeout_boostbot_' ) . '%'
        )
    );

    /**
     * 5. DELETE USER META
     */
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query(
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        $wpdb->prepare(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE %s",
            $wpdb->esc_like( 'boostbot_' ) . '%'
        )
    );

    /**
     * 6. REMOVE CAPABILITIES FROM ALL ROLES
     */
    $capabilities = array(
        'manage_boostbot',
        'view_boostbot_leads',
        'edit_boostbot_leads',
        'delete_boostbot_leads',
        'export_boostbot_leads',
        'view_boostbot_conversations',
        'manage_boostbot_settings',
        'manage_boostbot_knowledge',
    );

    // Remove from all roles, not just administrator
    global $wp_roles;
    if ( isset( $wp_roles ) && is_object( $wp_roles ) ) {
        foreach ( $wp_roles->roles as $role_name => $role_info ) {
            $role = get_role( $role_name );
            if ( $role ) {
                foreach ( $capabilities as $cap ) {
                    $role->remove_cap( $cap );
                }
            }
        }
    }

    /**
     * 7. CLEAR ALL SCHEDULED CRON EVENTS
     *
     * Uses wp_clear_scheduled_hook() which removes ALL events for
     * each hook, not just the next scheduled one.
     */
    $cron_hooks = array(
        'boostbot_daily_analytics',
        'boostbot_cleanup_old_conversations',
        'boostbot_cache_cleanup',
        'boostbot_check_content_updates',
        'boostbot_generate_reports',
        'boostbot_optimize_database',
        'boostbot_usage_report',
        'boostbot_reset_monthly_counters',
        'boostbot_incremental_index',
        'boostbot_webhook_retry',
        'boostbot_monthly_reset',
        // Indexing (new + legacy)
        'boostbot_process_index_batch',
        'boostbot_index_recover_stuck',
        'boostbot_process_index_queue',
        // Monitoring
        'boostbot_low_credits_check',
        // Activation self-test
        'boostbot_loopback_self_test',
    );

    foreach ( $cron_hooks as $hook ) {
        wp_clear_scheduled_hook( $hook );
    }

    /**
     * 8. DELETE LOG FILES
     */
    $log_dir = WP_CONTENT_DIR . '/boostbot-logs/';
    if ( is_dir( $log_dir ) ) {
        $files = glob( $log_dir . '*' );
        if ( is_array( $files ) ) {
            foreach ( $files as $file ) {
                if ( is_file( $file ) ) {
                    wp_delete_file( $file );
                }
            }
        }
        global $wp_filesystem;
        if ( empty( $wp_filesystem ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            WP_Filesystem();
        }
        if ( ! empty( $wp_filesystem ) ) {
            $wp_filesystem->rmdir( $log_dir, true );
        } else {
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- WP_Filesystem unavailable fallback
            @rmdir( $log_dir );
        }
    }

    // Alternative log location (inside plugin)
    $plugin_log_dir = dirname( __FILE__ ) . '/logs/';
    if ( is_dir( $plugin_log_dir ) ) {
        $files = glob( $plugin_log_dir . '*' );
        if ( is_array( $files ) ) {
            foreach ( $files as $file ) {
                if ( is_file( $file ) && basename( $file ) !== '.gitkeep' ) {
                    wp_delete_file( $file );
                }
            }
        }
    }
}

/**
 * 9. CLEAR REWRITE RULES (always, regardless of delete_data setting)
 */
flush_rewrite_rules();
