<?php
/**
 * Fired during plugin activation.
 *
 * @package BoostBot
 * @since   1.0.0
 */

// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Class BoostBot_Activator
 *
 * This class handles all logic executed during plugin activation.
 *
 * @since 1.0.0
 */
class BoostBot_Activator {

    /**
     * Activate the plugin.
     *
     * @return void
     */
    public static function activate() {
        // Create database tables
        self::create_tables();

        // Set default options
        self::set_default_options();

        // Set user capabilities
        self::add_capabilities();

        // Create default widgets (form templates)
        self::create_default_widgets();

        // Store plugin version
        update_option( 'boostbot_version', BOOSTBOT_VERSION );
        update_option( 'boostbot_db_version', BOOSTBOT_DB_VERSION );

        // First install detection (before we write installed_at)
        $is_first_install = ! get_option( 'boostbot_installed_at' );

        // Store installation date if first install
        if ( ! get_option( 'boostbot_installed_at' ) ) {
            update_option( 'boostbot_installed_at', current_time( 'mysql' ) );
        }

        // Flush rewrite rules
        flush_rewrite_rules();

        // Log activation
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG && class_exists( 'BoostBot_Logger' ) ) {
            BoostBot_Logger::info( 'BoostBot activated', array(
                'version'    => BOOSTBOT_VERSION,
                'db_version' => BOOSTBOT_DB_VERSION,
            ) );
        }

        // Run loopback self-test to determine if HTTP loopback is available on this host.
        // Result is stored in wp_options and used by the background indexer to decide
        // whether to attempt loopback or skip directly to WP-Cron.
        if ( class_exists( 'BoostBot_Background_Indexer' ) ) {
            // Schedule the self-test after a short delay (REST API may not be available during activation).
            wp_schedule_single_event( time() + 10, 'boostbot_loopback_self_test' );
        }

        // Proactive backend registration: schedule a deferred registration attempt.
        // For WP.org builds, only auto-register if the user has opted in to the cloud service.
        if ( class_exists( 'BoostBot_Registration_Monitor' ) && self::is_cloud_service_allowed() ) {
            BoostBot_Registration_Monitor::schedule_activation_registration();
        }

        // Set transient for welcome screen redirect (first install only)
        if ( $is_first_install ) {
            set_transient( 'boostbot_activation_redirect', true, 30 );
        }
    }

    /**
     * Check whether external cloud service calls are permitted.
     *
     * Self-hosted builds always allow cloud calls. WP.org builds require
     * explicit user opt-in via the boostbot_cloud_consent option.
     *
     * @return bool
     */
    public static function is_cloud_service_allowed(): bool {
        if ( defined( 'BOOSTBOT_SELF_HOSTED' ) && BOOSTBOT_SELF_HOSTED ) {
            return true;
        }
        return (bool) get_option( 'boostbot_cloud_consent', false );
    }

    /**
     * Week 27.x+: Safe DB upgrade hook for existing installs (no activation side effects).
     *
     * Runs dbDelta table updates + migrations, then updates boostbot_db_version.
     *
     * @return void
     */
    public static function upgrade_db() {
        self::create_tables();

        // Seed defaults for any enabled non-Hebrew languages
        try {
            $enabled = get_option( 'boostbot_enabled_languages', array() );
            if ( is_string( $enabled ) ) {
                $enabled = json_decode( $enabled, true ) ?: array();
            }
            if ( ! empty( $enabled ) && is_array( $enabled ) ) {
                $db_manager = new BoostBot_DB_Manager();
                foreach ( $enabled as $lang ) {
                    if ( 'he' !== $lang ) {
                        $db_manager->seed_language_defaults( $lang );
                    }
                }
            }
        } catch ( \Throwable $e ) {
            if ( class_exists( 'BoostBot_Logger' ) ) {
                BoostBot_Logger::error( 'Language seeding failed during upgrade', array( 'error' => $e->getMessage() ) );
            }
        }

        // Store DB version (do not touch boostbot_version here).
        update_option( 'boostbot_db_version', BOOSTBOT_DB_VERSION );

        if ( defined( 'WP_DEBUG' ) && WP_DEBUG && class_exists( 'BoostBot_Logger' ) ) {
            BoostBot_Logger::info( 'BoostBot DB upgraded', array(
                'db_version' => BOOSTBOT_DB_VERSION,
            ) );
        }
    }

    /**
     * Create the plugin database tables.
     *
     * @return void
     */
    private static function create_tables() {
        $db_manager = new BoostBot_DB_Manager();
        $db_manager->create_tables();

        // Run migrations
        self::run_migrations();
    }

    /**
     * Run database migrations.
     *
     * @return void
     */
    private static function run_migrations() {
        $migrations_dir = BOOSTBOT_PLUGIN_DIR . 'includes/database/migrations/';

        $migrations = array(
            'class-migration-add-visual-editor-fields.php'            => array( 'BoostBot_Migration_Add_Visual_Editor_Fields', 'run' ),
            'class-migration-add-bot-appearance-overrides.php'        => array( 'BoostBot_Migration_Add_Bot_Appearance_Overrides', 'up' ),
            'class-migration-add-bot-opening-screen-overrides.php'    => array( 'BoostBot_Migration_Add_Bot_Opening_Screen_Overrides', 'up' ),
            'class-migration-add-opening-buttons.php'                 => array( 'BoostBot_Migration_Add_Opening_Buttons', 'up' ),
            'class-migration-add-rag-columns.php'                     => array( 'BoostBot_Migration_Add_RAG_Columns', 'run' ),
            'class-migration-add-deep-indexing-incremental-columns.php' => array( 'BoostBot_Migration_Add_Deep_Indexing_Incremental_Columns', 'run' ),
            'class-migration-create-knowledge-chunks-table.php'       => array( 'BoostBot_Migration_Create_Knowledge_Chunks_Table', 'run' ),
            'class-migration-create-index-queue-table.php'            => array( 'BoostBot_Migration_Create_Index_Queue_Table', 'run' ),
            'class-migration-add-fulltext-index.php'                  => array( 'BoostBot_Migration_Add_Fulltext_Index', 'run' ),
            'class-migration-add-proactive-delay-seconds.php'         => array( 'BoostBot_Migration_Add_Proactive_Delay_Seconds', 'run' ),
            'class-migration-add-personality-custom-instructions.php'  => array( 'BoostBot_Migration_Add_Personality_Custom_Instructions', 'run' ),
            'class-migration-add-conversation-summary.php'            => array( 'BoostBot_Migration_Add_Conversation_Summary', 'run' ),
            'class-migration-add-bot-personality-columns.php'         => array( 'BoostBot_Migration_Add_Bot_Personality_Columns', 'run' ),
            'class-migration-remove-custom-prompt-mode.php'           => array( 'BoostBot_Migration_Remove_Custom_Prompt_Mode', 'run' ),
            'class-migration-add-language-column.php'                 => array( 'BoostBot_Migration_Add_Language_Column', 'run' ),
            'class-migration-add-language-to-meetings.php'            => array( 'BoostBot_Migration_Add_Language_To_Meetings', 'up' ),
            'class-migration-add-language-to-widget-usage.php'        => array( 'BoostBot_Migration_Add_Language_To_Widget_Usage', 'up' ),
            'class-migration-add-language-to-appearance-presets.php'  => array( 'BoostBot_Migration_Add_Language_To_Appearance_Presets', 'up' ),
            'class-migration-multilingual-backfill.php'               => array( 'BoostBot_Migration_Multilingual_Backfill', 'run' ),
            'class-migration-per-language-global-rules.php'            => array( 'BoostBot_Migration_Per_Language_Global_Rules', 'run' ),
            'class-migration-appearance-default-ref.php'               => array( 'BoostBot_Migration_Appearance_Default_Ref', 'run' ),
            'class-migration-global-values-per-language.php'            => array( 'BoostBot_Migration_Global_Values_Per_Language', 'run' ),
            'class-migration-create-woocommerce-tables.php'           => array( 'BoostBot_Migration_Create_WooCommerce_Tables', 'run' ),
            'class-migration-add-show-cart-button-to-woocommerce-presets.php' => array( 'BoostBot_Migration_Add_Show_Cart_Button_To_WooCommerce_Presets', 'run' ),
            'class-migration-create-commerce-events-table.php'        => array( 'BoostBot_Migration_Create_Commerce_Events_Table', 'run' ),
            'class-migration-add-coupon-purpose-columns.php'          => array( 'BoostBot_Migration_Add_Coupon_Purpose_Columns', 'run' ),
            'class-migration-add-language-to-bundles.php'             => array( 'BoostBot_Migration_Add_Language_To_Bundles', 'run' ),
            'class-migration-add-woocommerce-preset-to-bots.php'     => array( 'BoostBot_Migration_Add_WooCommerce_Preset_To_Bots', 'run' ),
            'class-migration-add-bundle-discount-method.php'         => array( 'BoostBot_Migration_Add_Bundle_Discount_Method', 'run' ),
            'class-migration-add-fulltext-index-knowledge-index.php' => array( 'BoostBot_Migration_Add_Fulltext_Index_Knowledge_Index', 'run' ),
            'class-migration-backfill-element-settings.php'          => array( 'BoostBot_Migration_Backfill_Element_Settings', 'run' ),
        );

        foreach ( $migrations as $file => $callable ) {
            $migration_file = $migrations_dir . $file;
            if ( ! file_exists( $migration_file ) ) {
                continue;
            }

            require_once $migration_file;
            [ $class, $method ] = $callable;

            if ( ! class_exists( $class ) ) {
                continue;
            }

            try {
                $class::$method();
            } catch ( \Throwable $e ) {
                BoostBot_Logger::error(
                    "[Migration] {$class}::{$method}() failed",
                    array( 'error' => $e->getMessage() )
                );
            }
        }
    }

    /**
     * Set default plugin options.
     *
     * @return void
     */
    private static function set_default_options() {
        $defaults = array(
            'boostbot_api_key'                  => '',
            'boostbot_plan_level'               => 'basic',
            // Monthly usage limits are deprecated (credits is the only limiter).
            'boostbot_monthly_limit'            => -1,
            'boostbot_current_usage'            => 0,
            'boostbot_bot_name'                 => __( 'BoostBot', 'boostbot' ),
            'boostbot_welcome_message'          => __( 'שלום! 👋 איך אוכל לעזור לך היום?', 'boostbot' ),
            'boostbot_primary_color'            => '#3BC2D0',
            'boostbot_accent_color'             => '#E32774',
            'boostbot_position'                 => 'bottom-right',
            'boostbot_is_active'                => true, // Active by default
            'boostbot_debug_mode'               => false,
            'boostbot_delete_data_on_uninstall' => true,
            'boostbot_license_status'           => 'free',
            'boostbot_settings_frozen'          => false,
            // Performance: Direct SSE streaming enabled by default for faster chatbot responses
            'boostbot_direct_streaming_enabled' => true,
        );

        foreach ( $defaults as $option_name => $default_value ) {
            // Only add if option doesn't exist (preserve existing settings)
            if ( false === get_option( $option_name ) ) {
                add_option( $option_name, $default_value );
            }
        }
    }

    /**
     * Add plugin-specific capabilities to administrator role.
     *
     * @return void
     */
    private static function add_capabilities() {
        $admin_role = get_role( 'administrator' );

        if ( $admin_role ) {
            $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',
            );

            foreach ( $capabilities as $cap ) {
                $admin_role->add_cap( $cap );
            }
        }
    }

    /**
     * Check if this is a fresh installation.
     *
     * @return bool
     */
    public static function is_fresh_install() {
        return ! get_option( 'boostbot_version' );
    }

    /**
     * Check if database needs upgrade.
     *
     * @return bool
     */
    public static function needs_db_upgrade() {
        $installed_db_version = get_option( 'boostbot_db_version', '0' );
        return version_compare( $installed_db_version, BOOSTBOT_DB_VERSION, '<' );
    }

    /**
     * Create default widgets - one per type.
     * 
     * Forms are active by default (ready to use).
     * Other widget types are inactive by default (require setup).
     *
     * @return void
     */
    private static function create_default_widgets() {
        // Check if defaults were already created (use an option flag)
        if ( get_option( 'boostbot_default_widgets_created' ) ) {
            return;
        }

        $widget_model = new BoostBot_Widget_Model();
        $field_model  = new BoostBot_Form_Field_Model();
        $created_widget_ids = array();

        // Resolve default bot once so all freshly created widgets are auto-linked to it.
        $default_bot_id = 0;
        if ( class_exists( 'BoostBot_Bot_Model' ) ) {
            $bot_model = new BoostBot_Bot_Model();
            $default_bot = $bot_model->get_default();
            $default_bot_id = ! empty( $default_bot->id ) ? (int) $default_bot->id : 0;
        }

        // Define all default widgets - one per type
        $default_widgets = array(
            // ============================================
            // FORMS - Active by default (ready to use)
            // ============================================
            
            // Form 1: Quick Contact (Name + Phone)
            array(
                'name'        => __( 'טופס מהיר', 'boostbot' ),
                'type'        => 'form',
                'description' => __( 'כשהלקוח רוצה להשאיר פרטים או שנחזור אליו - הצג טופס זה', 'boostbot' ),
                'is_active'   => 1, // Active - ready to use
                'config'      => array(
                    'submit_text'     => __( 'שלחו', 'boostbot' ),
                    'success_message' => __( 'תודה! נחזור אליך בהקדם', 'boostbot' ),
                    'show_labels'     => true,
                ),
                'fields'      => array(
                    array(
                        'field_type'  => 'text',
                        'label'       => __( 'שם', 'boostbot' ),
                        'name'        => 'name',
                        'is_required' => 1,
                        'placeholder' => __( 'השם שלך', 'boostbot' ),
                    ),
                    array(
                        'field_type'  => 'phone',
                        'label'       => __( 'טלפון', 'boostbot' ),
                        'name'        => 'phone',
                        'is_required' => 1,
                        'placeholder' => '050-1234567',
                    ),
                ),
            ),

            // Form 2: Full Contact (Name + Phone + Email + Message)
            array(
                'name'        => __( 'טופס יצירת קשר מלא', 'boostbot' ),
                'type'        => 'form',
                'description' => __( 'כשהלקוח רוצה לשלוח הודעה מפורטת - הצג טופס זה', 'boostbot' ),
                'is_active'   => 1, // Active - ready to use
                'config'      => array(
                    'submit_text'     => __( 'שלחו הודעה', 'boostbot' ),
                    'success_message' => __( 'תודה על פנייתך! נחזור אליך בהקדם', 'boostbot' ),
                    'show_labels'     => true,
                ),
                'fields'      => array(
                    array(
                        'field_type'  => 'text',
                        'label'       => __( 'שם מלא', 'boostbot' ),
                        'name'        => 'name',
                        'is_required' => 1,
                        'placeholder' => __( 'השם שלך', 'boostbot' ),
                    ),
                    array(
                        'field_type'  => 'phone',
                        'label'       => __( 'טלפון', 'boostbot' ),
                        'name'        => 'phone',
                        'is_required' => 1,
                        'placeholder' => '050-1234567',
                    ),
                    array(
                        'field_type'  => 'email',
                        'label'       => __( 'אימייל', 'boostbot' ),
                        'name'        => 'email',
                        'is_required' => 0,
                        'placeholder' => 'your@email.com',
                    ),
                    array(
                        'field_type'  => 'textarea',
                        'label'       => __( 'הודעה', 'boostbot' ),
                        'name'        => 'message',
                        'is_required' => 0,
                        'placeholder' => __( 'במה נוכל לעזור?', 'boostbot' ),
                    ),
                ),
            ),

            // ============================================
            // OTHER WIDGETS - Inactive by default (require setup)
            // ============================================

            // WhatsApp
            array(
                'name'        => __( 'וואטסאפ', 'boostbot' ),
                'type'        => 'whatsapp',
                'description' => __( 'כשהלקוח רוצה ליצור קשר בוואטסאפ - הצג כפתור זה', 'boostbot' ),
                'is_active'   => 0, // Inactive - requires phone number setup
                'config'      => array(
                    'contacts'         => array(),
                    'message_template' => __( 'היי, פניתי דרך הבוט באתר', 'boostbot' ),
                    'show_all_contacts' => false,
                ),
                'fields'      => array(),
            ),

            // Calendar
            array(
                'name'        => __( 'תאריכון', 'boostbot' ),
                'type'        => 'calendar_meeting',
                'description' => __( 'כשהלקוח רוצה לקבוע פגישה או לתאם שיחה - הצג תאריכון זה', 'boostbot' ),
                'is_active'   => 0, // Inactive - requires calendar setup
                'config'      => array(
                    'title'            => __( 'קבע פגישה', 'boostbot' ),
                    'require_name'     => true,
                    'require_phone'    => true,
                    'show_meeting_type_selection' => true,
                    'meeting_types'    => array(
                        array( 'id' => 'frontal', 'label' => __( 'פגישה פרונטלית', 'boostbot' ), 'icon' => 'user', 'require_name' => true, 'require_phone' => true, 'require_email' => false ),
                        array( 'id' => 'phone', 'label' => __( 'שיחה טלפונית', 'boostbot' ), 'icon' => 'phone', 'require_name' => true, 'require_phone' => true, 'require_email' => false ),
                        array( 'id' => 'video', 'label' => __( 'פגישה וירטואלית', 'boostbot' ), 'icon' => 'video', 'require_name' => true, 'require_phone' => true, 'require_email' => true ),
                    ),
                ),
                'fields'      => array(),
            ),

            // Gallery
            array(
                'name'        => __( 'גלריה', 'boostbot' ),
                'type'        => 'gallery',
                'description' => __( 'כשהלקוח רוצה לראות עבודות או דוגמאות - הצג גלריה זו', 'boostbot' ),
                'is_active'   => 0, // Inactive - requires images
                'config'      => array(
                    'name'        => __( 'גלריית עבודות', 'boostbot' ),
                    'description' => '',
                    'images'      => array(),
                ),
                'fields'      => array(),
            ),

            // YouTube
            array(
                'name'        => __( 'סרטון יוטיוב', 'boostbot' ),
                'type'        => 'youtube',
                'description' => __( 'כשהלקוח רוצה לצפות בסרטון או וידאו - הצג סרטון זה', 'boostbot' ),
                'is_active'   => 0, // Inactive - requires video URL
                'config'      => array(
                    'video_url'   => '',
                    'title'       => '',
                    'description' => '',
                    'autoplay'    => false,
                ),
                'fields'      => array(),
            ),

            // Contact Card
            array(
                'name'        => __( 'כרטיס איש קשר', 'boostbot' ),
                'type'        => 'contact_card',
                'description' => __( 'כשהלקוח רוצה לדעת עם מי לדבר או פרטי קשר - הצג כרטיס זה', 'boostbot' ),
                'is_active'   => 0, // Inactive - requires contact list
                'config'      => array(
                    'contact_list_ids' => array(),
                ),
                'fields'      => array(),
            ),
        );

        // Create each widget
        foreach ( $default_widgets as $widget_data ) {
            $fields = $widget_data['fields'] ?? array();
            unset( $widget_data['fields'] );

            $widget_data['config'] = wp_json_encode( $widget_data['config'] );
            $widget_id             = $widget_model->create( $widget_data );
            if ( $widget_id ) {
                $created_widget_ids[] = (int) $widget_id;
            }

            // Create form fields if any
            if ( $widget_id && ! empty( $fields ) ) {
                foreach ( $fields as $index => $field ) {
                    $field['widget_id']  = $widget_id;
                    $field['sort_order'] = $index;
                    $field_model->create( $field );
                }
            }
        }

        // Auto-assign all default widgets to the default bot.
        if ( $default_bot_id > 0 && ! empty( $created_widget_ids ) ) {
            foreach ( $created_widget_ids as $widget_id ) {
                $widget_model->assign_to_chatbot( $widget_id, $default_bot_id );
            }
        }

        // Mark as done so we don't create duplicates
        update_option( 'boostbot_default_widgets_created', true );

        if ( class_exists( 'BoostBot_Logger' ) ) {
            BoostBot_Logger::info( 'Default widgets created (one per type)', array(
                'count'          => count( $created_widget_ids ),
                'default_bot_id' => $default_bot_id,
                'auto_assigned'  => ( $default_bot_id > 0 && ! empty( $created_widget_ids ) ),
            ) );
        }
    }

    /**
     * Sync the JWT signing secret from the backend into wp-config.php.
     *
     * Fetches the current BOOSTBOT_JWT_SECRET from the backend and writes it
     * as a PHP constant in wp-config.php. If the write fails, the per-site
     * derived fallback secret still works — this is purely an optimization.
     *
     * Safe to call multiple times: skips if the secret is already current.
     *
     * @return bool True if synced/already current, false on failure.
     */
    public static function sync_jwt_secret(): bool {
        if ( ! class_exists( 'BoostBot_Credits_Backend_Client' ) ) {
            BoostBot_Logger::warning( '[JWT Sync] Skipped: credits backend client not available.' );
            return false;
        }

        try {
            $client  = new BoostBot_Credits_Backend_Client();
            $site_id = $client->ensure_site_id();

            if ( is_wp_error( $site_id ) || empty( $site_id ) ) {
                $reason = is_wp_error( $site_id ) ? $site_id->get_error_message() : 'empty site_id';
                BoostBot_Logger::warning( '[JWT Sync] Skipped: ' . $reason );
                return false;
            }

            $result = $client->fetch_jwt_secret( (string) $site_id );
            if ( is_wp_error( $result ) ) {
                BoostBot_Logger::error(
                    '[JWT Sync] Backend request failed',
                    array( 'error' => $result->get_error_message() )
                );
                return false;
            }

            $new_secret = $result['jwt_secret'] ?? '';
            if ( strlen( $new_secret ) < 32 ) {
                BoostBot_Logger::error( '[JWT Sync] Backend returned invalid secret (too short).' );
                return false;
            }

            // Check if already in sync.
            if ( defined( 'BOOSTBOT_JWT_SECRET' ) && BOOSTBOT_JWT_SECRET === $new_secret ) {
                BoostBot_Logger::info( '[JWT Sync] Already in sync — no update needed.' );
                return true;
            }

            // Write to wp-config.php.
            $written = self::write_jwt_secret_to_wp_config( $new_secret );
            if ( $written ) {
                BoostBot_Logger::info( '[JWT Sync] Successfully wrote BOOSTBOT_JWT_SECRET to wp-config.php.' );
            } else {
                BoostBot_Logger::warning( '[JWT Sync] Failed to write wp-config.php — using derived fallback.' );
            }

            return $written;
        } catch ( \Throwable $e ) {
            BoostBot_Logger::error( '[JWT Sync] Exception', array( 'error' => $e->getMessage() ) );
            return false;
        }
    }

    /**
     * Write or update BOOSTBOT_JWT_SECRET in wp-config.php.
     *
     * @param string $secret The new JWT secret value.
     * @return bool True on success.
     */
    private static function write_jwt_secret_to_wp_config( string $secret ): bool {
        $config_path = ABSPATH . 'wp-config.php';

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable -- Checking wp-config.php writability during activation
        if ( ! file_exists( $config_path ) || ! is_writable( $config_path ) ) {
            // wp-config.php might be one level up.
            $alt_path = dirname( ABSPATH ) . '/wp-config.php';
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable -- Checking wp-config.php writability during activation
            if ( file_exists( $alt_path ) && is_writable( $alt_path ) ) {
                $config_path = $alt_path;
            } else {
                BoostBot_Logger::warning( '[JWT Sync] wp-config.php not writable.' );
                return false;
            }
        }

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- reading wp-config.php for JWT secret injection
        $contents = file_get_contents( $config_path );
        if ( false === $contents ) {
            return false;
        }

        $define_line = "define( 'BOOSTBOT_JWT_SECRET', '" . addslashes( $secret ) . "' );";

        // Pattern: existing define for BOOSTBOT_JWT_SECRET (single or double quotes).
        $pattern = '/^\s*define\s*\(\s*[\'"]BOOSTBOT_JWT_SECRET[\'"]\s*,\s*[\'"][^\'"]*[\'"]\s*\)\s*;/m';

        if ( preg_match( $pattern, $contents ) ) {
            $new_contents = preg_replace( $pattern, $define_line, $contents, 1 );
        } else {
            // Insert before "/* That's all, stop editing! */" or at the end of the PHP block.
            $marker = "/* That's all, stop editing!";
            $pos    = strpos( $contents, $marker );
            if ( false !== $pos ) {
                $insert = "// BoostBot JWT signing secret (auto-synced from backend)\n" . $define_line . "\n\n";
                $new_contents = substr_replace( $contents, $insert, $pos, 0 );
            } else {
                $new_contents = $contents . "\n// BoostBot JWT signing secret (auto-synced from backend)\n" . $define_line . "\n";
            }
        }

        if ( $new_contents === $contents ) {
            return true;
        }

        // Verify the new contents are valid PHP before writing.
        // Use token_get_all() instead of exec('php -l') because exec() is
        // disabled on many shared hosting environments. The leading @ on
        // token_get_all() suppresses tokenizer notices at the call site,
        // which is the only suppression needed here.
        try {
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Tokenizer notices on malformed wp-config.php must not be surfaced to admins; we abort cleanly on empty result.
            $tokens = @token_get_all( $new_contents );
            if ( ! is_array( $tokens ) || empty( $tokens ) ) {
                BoostBot_Logger::error( '[JWT Sync] PHP syntax check failed (tokenizer) — aborting write.' );
                return false;
            }
        } catch ( \Throwable $e ) {
            BoostBot_Logger::error(
                '[JWT Sync] PHP syntax check exception',
                array( 'error' => $e->getMessage() )
            );
            return false;
        }

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents -- writing JWT secret to wp-config.php
        return false !== file_put_contents( $config_path, $new_contents );
    }
}



