<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

/**
 * React Development Environment Handler
 * 
 * This class handles loading React components in both development and production modes.
 * Instead of duplicating logic, it leverages the existing MAGICCL_Public::should_load_assets()
 * logic to determine when to enqueue React scripts, ensuring consistency with the 
 * existing permission and loading systems.
 * 
 * @since 2.0.0
 */
class MAGICCL_React_Dev {
    
    private $vite_dev_server = 'http://localhost:3000';
    public $is_dev_mode = false;
    
    /**
     * Allows developers to explicitly turn dev-mode on or off by defining the
     * `MAGICCL_DEV_MODE` constant in wp-config.php. If the constant is defined
     * the plugin will never perform the localhost availability check – this
     * avoids unnecessary requests on production while still giving full
     * control in local environments.
     */
    private function is_dev_mode_forced() {
        return defined( 'MAGICCL_DEV_MODE' );
    }
    
    public function __construct() {
        if ( $this->is_dev_mode_forced() ) {
            $this->is_dev_mode = (bool) MAGICCL_DEV_MODE;
        } else {
            $this->is_dev_mode = false;
        }
        
        // If in dev mode, inject React Refresh preamble into head for HMR support
        if ( $this->is_dev_mode ) {
            add_action( 'admin_head', array( $this, 'vite_refresh_preamble' ) );
            add_action( 'wp_head', array( $this, 'vite_refresh_preamble' ) );
        }
        
        // Hook into the existing MAGICCL_Public enqueue logic
        add_action( 'admin_enqueue_scripts', array( $this, 'maybe_enqueue_react_scripts' ), 9 ); // After MAGICCL_Public (priority 5)
        add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_react_scripts' ), 9 );
        
        // Add React root elements to both frontend and admin
        add_action( 'wp_footer', array( $this, 'add_react_root_elements' ) );
        add_action( 'admin_footer', array( $this, 'add_react_root_elements' ) );
        
        add_action( 'admin_head', array( $this, 'add_admin_styles' ) );
    }
    
    /**
     * Check if Vite dev server is running by making a test request
     */
    public function is_vite_dev_server_running() {
        // If the developer forced dev-mode explicitly, never probe the server.
        if ( $this->is_dev_mode_forced() ) {
            return (bool) MAGICCL_DEV_MODE;
        }

        // Only check in development/staging environments
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            /*
             * Use WordPress HTTP API for the availability check instead of
             * file_get_contents(). The HTTP API will return a WP_Error on
             * failure instead of triggering the PHP warning:
             *   "file_get_contents(...): Failed to open stream: Connection refused".
             * This keeps the admin UI clean while still accurately detecting
             * whether the Vite dev-server is running.
             */

            $response = wp_remote_get( $this->vite_dev_server, [
                'timeout' => 1,
                'redirection' => 0,
                'blocking' => true,
                'sslverify' => false, // Local dev server is usually http
                'headers' => [],
            ] );

            // If we didn't get a WP_Error back, the dev-server accepted the
            // connection – even when it responds with 404 for the root path.
            // That is enough to know that the server is running.

            return ! is_wp_error( $response );
        }
        
        return false;
    }
    
    /**
     * Hook into existing MAGICCL_Public enqueue logic to provide React scripts
     */
    public function maybe_enqueue_react_scripts( $hook ) {
        // Prevent multiple enqueue attempts
        static $enqueue_attempted = false;
        if ( $enqueue_attempted ) {
            return;
        }
        $enqueue_attempted = true;
        
        // Get the global MAGICCL_Public instance
        global $magiccl_public_instance;
        if ( ! $magiccl_public_instance ) {
            return; // MAGICCL_Public not loaded yet
        }
        
        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Public/admin page routing parameters from bookmarkable URLs; all sanitized with absint().
        $is_tour_mode = isset($_GET['magiccl_tour_mode']) && absint($_GET['magiccl_tour_mode']) === 1;
        $continue_tour_id = isset($_GET['magiccl_continue_tour']) ? absint($_GET['magiccl_continue_tour']) : 0;
        $has_tour_id = isset($_GET['tour_id']) ? absint($_GET['tour_id']) : 0;
        // phpcs:enable WordPress.Security.NonceVerification.Recommended

        // Check for active tours via Tour CPT
        $has_active_tours = false;
        if (class_exists('MAGICCL_Tour_CPT')) {
            $active_tours = MAGICCL_Tour_CPT::get_active_tours_for_context();
            $has_active_tours = !empty($active_tours);
        }

        // Force React loading for tour mode, regardless of checklist conditions
        $force_load_for_tours = $is_tour_mode || $continue_tour_id || $has_tour_id || $has_active_tours;

        // Check tour mode cookie as fallback
        if (!$force_load_for_tours && isset($_COOKIE['magiccl_tour_mode']) && sanitize_text_field(wp_unslash($_COOKIE['magiccl_tour_mode'])) === '1') {
            $force_load_for_tours = true;
        }
        
        // Determine which React app to load based on context
        if ( is_admin() ) {
            // Check if this is a plugin admin page
            $screen = get_current_screen();
            if ( $screen ) {
                $plugin_pages = array(
                    'toplevel_page_magic_plugins',        // Main MagicPlugins landing page
                    'magicplugins_page_magiccl_checklists',    // MagicChecklists main page
                    'magicplugins_page_magiccl_manage_license' // License management page
                );
                
                if ( in_array( $screen->id, $plugin_pages ) ) {
                    // Always load admin React app on plugin admin pages, regardless of checklist conditions
                    $this->enqueue_admin_scripts( $hook );
                                         // Only load public React app if there are actual checklists that need drawer/floating buttons
                     // This prevents React instance conflicts on fresh installs
                     if ( $force_load_for_tours || $magiccl_public_instance->should_load_assets() ) {
                         $this->enqueue_public_scripts( $hook );
                     }
                } else {
                    // For non-plugin admin pages, check if we should load public assets
                    if ( $force_load_for_tours || $magiccl_public_instance->should_load_assets() ) {
                        // Load public React app for drawer/floating buttons on admin pages
                        $this->enqueue_public_scripts( $hook );
                    }
                }
            }
        } else {
            // For frontend pages, check if we should load public assets
            if ( $force_load_for_tours || $magiccl_public_instance->should_load_assets() ) {
                // Load public React app on frontend
                $this->enqueue_public_scripts( $hook );
            }
        }
    }

    /**
     * Enqueue admin React scripts
     */
    private function enqueue_admin_scripts( $hook ) {
        if ( $this->is_dev_mode ) {
            $this->enqueue_admin_dev_scripts( $hook );
        } else {
            $this->enqueue_admin_prod_scripts( $hook );
        }
        $this->localize_admin_data();
    }

    /**
     * Enqueue public React scripts  
     */
    private function enqueue_public_scripts( $hook ) {
        
        if ( $this->is_dev_mode ) {
            $this->enqueue_public_dev_scripts( $hook );
        } else {
            $this->enqueue_public_prod_scripts( $hook );
        }
    }
    
    /**
     * Enqueue admin development scripts from Vite dev server
     */
    private function enqueue_admin_dev_scripts( $hook ) {
        
        // Check if tour assets are needed and enqueue them first
        if ($this->should_load_tour_assets()) {
            $this->enqueue_tour_assets();
        }

        // Vite client for HMR
        wp_enqueue_script(
            'vite-client',
            $this->vite_dev_server . '/@vite/client',
            array(),
            null,
            false
        );
        
        // Add type="module" to Vite client
        add_filter( 'script_loader_tag', function( $tag, $handle ) {
            if ( $handle === 'vite-client' ) {
                return str_replace( ' src=', ' type="module" src=', $tag );
            }
            return $tag;
        }, 10, 2 );
        
        // Admin React app from Vite dev server
        wp_enqueue_script(
            'magiccl-react-admin-dev',
            $this->vite_dev_server . '/src/admin.jsx',
            array( 'vite-client' ),
            null,
            true
        );
        
        add_filter( 'script_loader_tag', function( $tag, $handle ) {
            if ( $handle === 'magiccl-react-admin-dev' ) {
                return str_replace( ' src=', ' type="module" src=', $tag );
            }
            return $tag;
        }, 10, 2 );
        
        // Localize script data for React
        $this->localize_admin_data();
    }
    
    /**
     * Enqueue public development scripts from Vite dev server
     */
    private function enqueue_public_dev_scripts( $hook ) {
        // Check if tour assets are needed and enqueue them first
        if ($this->should_load_tour_assets()) {
            $this->enqueue_tour_assets();
        }

        // Check if we're loading both admin and public on the same page
        $is_plugin_page = is_admin() && $this->is_plugin_admin_page();
        $public_handle_suffix = $is_plugin_page ? '-drawer' : '';
        
        // Apply dual-loading protection when admin React OR tour assets might clash with public React
        $needs_dual_protection = $is_plugin_page || $this->should_load_tour_assets();
        
        // Vite client for HMR - only enqueue if not already enqueued
        if ( ! wp_script_is( 'vite-client', 'enqueued' ) ) {
            wp_enqueue_script(
                'vite-client',
                $this->vite_dev_server . '/@vite/client',
                array(),
                null,
                false
            );
            
            // Add type="module" to Vite client
            add_filter( 'script_loader_tag', function( $tag, $handle ) {
                if ( $handle === 'vite-client' ) {
                    return str_replace( ' src=', ' type="module" src=', $tag );
                }
                return $tag;
            }, 10, 2 );
        }
        
        // Public React app from Vite dev server
        wp_enqueue_script(
            'magiccl-react-public-dev' . $public_handle_suffix,
            $this->vite_dev_server . '/src/main.jsx',
            array( 'vite-client' ),
            null,
            true
        );
        
        add_filter( 'script_loader_tag', function( $tag, $handle ) use ( $public_handle_suffix ) {
            if ( $handle === 'magiccl-react-public-dev' . $public_handle_suffix ) {
                return str_replace( ' src=', ' type="module" src=', $tag );
            }
            return $tag;
        }, 10, 2 );
        
        // Localize script data for React
        $this->localize_public_data( $public_handle_suffix );
        
        // Add script isolation when dual React loading is detected
        if ( $needs_dual_protection ) {
            $this->add_script_isolation_for_dual_loading( $public_handle_suffix );
        }
        
        // React isolation will be handled globally via enqueue_public_* methods
    }
    
    /**
     * Enqueue admin production built scripts
     */
    private function enqueue_admin_prod_scripts( $hook ) {
        
        // Check if tour assets are needed and enqueue them first
        if ($this->should_load_tour_assets()) {
            $this->enqueue_tour_assets();
        }

        $dist_path = MAGIC_CHECKLISTS_PLUGIN_PATH . 'dist/';
        $dist_url = MAGIC_CHECKLISTS_PLUGIN_URL . 'dist/';
        
        // Load vendor chunks first
        $vendor_handles = $this->enqueue_vendor_chunks( $dist_path, $dist_url );
        
        // Load the main CSS file (Vite generates index-[hash].css for all styles)
        $this->enqueue_main_css( $dist_path, $dist_url );
        
        // Admin React app
        $admin_js_path = $dist_path . 'admin.js';
        
        if ( file_exists( $admin_js_path ) ) {
            // If no vendor handles were loaded, try loading without dependencies as fallback
            $dependencies = !empty($vendor_handles) ? $vendor_handles : array();
            
            wp_enqueue_script(
                'magiccl-react-admin',
                $dist_url . 'admin.js',
                $dependencies,
                MAGIC_CHECKLISTS_VERSION,
                true
            );
            
            // Add type="module" to admin script
            add_filter( 'script_loader_tag', function( $tag, $handle ) {
                if ( $handle === 'magiccl-react-admin' ) {
                    return str_replace( ' src=', ' type="module" src=', $tag );
                }
                return $tag;
            }, 10, 2 );
            
            // Check what files exist in the dist directory
            if (file_exists($dist_path)) {
                $files = scandir($dist_path);
                
                // Try to find admin script with different naming patterns
                $admin_js_files = array_filter($files, function($file) {
                    return strpos($file, 'admin') !== false && substr($file, -3) === '.js';
                });
                
                                if (!empty($admin_js_files)) {
                    $admin_file = reset($admin_js_files);
                    
                    // If no vendor handles were loaded, try loading without dependencies as fallback
                    $dependencies = !empty($vendor_handles) ? $vendor_handles : array();
                    
                    wp_enqueue_script(
                        'magiccl-react-admin',
                        $dist_url . $admin_file,
                        $dependencies,
                        MAGIC_CHECKLISTS_VERSION,
                        true
                    );
                    
                    // Add type="module" to admin script
                    add_filter( 'script_loader_tag', function( $tag, $handle ) {
                        if ( $handle === 'magiccl-react-admin' ) {
                            return str_replace( ' src=', ' type="module" src=', $tag );
                        }
                        return $tag;
                    }, 10, 2 );
                } else {
                    // As a last resort, try loading any JS file that might work
                    $any_js_files = array_filter($files, function($file) {
                        return substr($file, -3) === '.js' && $file !== '.' && $file !== '..';
                    });
                    if (!empty($any_js_files)) {
                    }
                }
            }
        }
        
        // Localize script data for React
        $this->localize_admin_data();
    }
    
    /**
     * Enqueue public production built scripts
     */
    private function enqueue_public_prod_scripts( $hook ) {
        // Check if tour assets are needed and enqueue them first
        if ($this->should_load_tour_assets()) {
            $this->enqueue_tour_assets();
        }

        $dist_path = MAGIC_CHECKLISTS_PLUGIN_PATH . 'dist/';
        $dist_url = MAGIC_CHECKLISTS_PLUGIN_URL . 'dist/';
        
        // Check if we're loading both admin and public on the same page
        $is_plugin_page = $this->is_plugin_admin_page();
        $public_handle_suffix = $is_plugin_page ? '-drawer' : '';
        
        // Apply dual-loading protection when admin React OR tour assets might clash with public React
        $needs_dual_protection = $is_plugin_page || $this->should_load_tour_assets();
        
        // Load vendor chunks first
        $vendor_handles = $this->enqueue_vendor_chunks( $dist_path, $dist_url );
        
        // Load the main CSS file (Vite generates index-[hash].css for all styles)
        $this->enqueue_main_css( $dist_path, $dist_url );
        
        // Public React app
        if ( file_exists( $dist_path . 'main.js' ) ) {
            wp_enqueue_script(
                'magiccl-react-public' . $public_handle_suffix,
                $dist_url . 'main.js',
                $vendor_handles,
                MAGIC_CHECKLISTS_VERSION,
                true
            );
            
            // Add type="module" to public script
            add_filter( 'script_loader_tag', function( $tag, $handle ) use ( $public_handle_suffix ) {
                if ( $handle === 'magiccl-react-public' . $public_handle_suffix ) {
                    return str_replace( ' src=', ' type="module" src=', $tag );
                }
                return $tag;
            }, 10, 2 );
        }
        
        // Localize script data for React
        $this->localize_public_data( $public_handle_suffix );
        
        // Add script isolation when dual React loading is detected
        if ( $needs_dual_protection ) {
            $this->add_script_isolation_for_dual_loading( $public_handle_suffix );
        }
        
        // React isolation will be handled globally via enqueue_public_* methods
    }
    
    /**
     * Enqueue the main CSS file generated by Vite
     */
    private function enqueue_main_css( $dist_path, $dist_url ) {
        // Only enqueue CSS once if not already enqueued
        if ( wp_style_is( 'magiccl-react-styles', 'enqueued' ) ) {
            return;
        }
        
        // Vite generates CSS files as styles-[hash].css in the assets folder
        $css_files = glob( $dist_path . 'assets/styles-*.css' );
        
        if ( ! empty( $css_files ) ) {
            $css_file = str_replace( $dist_path, '', $css_files[0] );
            wp_enqueue_style(
                'magiccl-react-styles',
                $dist_url . $css_file,
                array(),
                MAGIC_CHECKLISTS_VERSION
            );
        } else {
            // Fallback: check for index-[hash].css pattern (from previous builds)
            $css_files = glob( $dist_path . 'assets/index-*.css' );
            
            if ( ! empty( $css_files ) ) {
                $css_file = str_replace( $dist_path, '', $css_files[0] );
                wp_enqueue_style(
                    'magiccl-react-styles',
                    $dist_url . $css_file,
                    array(),
                    MAGIC_CHECKLISTS_VERSION
                );
            } else {
                // Final fallback: check for CSS in root directory
                if ( file_exists( $dist_path . 'index.css' ) ) {
                    wp_enqueue_style(
                        'magiccl-react-styles',
                        $dist_url . 'index.css',
                        array(),
                        MAGIC_CHECKLISTS_VERSION
                    );
                } else {
                    // Check what CSS files exist in the assets directory
                    $assets_path = $dist_path . 'assets/';
                    if (file_exists($assets_path)) {
                        $all_css_files = glob( $assets_path . '*.css' );
                    }
                }
            }
        }
    }
    
    /**
     * Enqueue vendor chunks for optimized loading
     * @return array Array of vendor handle names
     */
    private function enqueue_vendor_chunks( $dist_path, $dist_url ) {
        $vendor_handles = array();
        
        // Load vendor chunk (React, ReactDOM) - only enqueue if not already enqueued
        $vendor_files = glob( $dist_path . 'vendor-*.js' );
        
        if ( ! empty( $vendor_files ) && ! wp_script_is( 'magiccl-vendor-chunk', 'enqueued' ) ) {
            $vendor_file = str_replace( $dist_path, '', $vendor_files[0] );
            wp_enqueue_script(
                'magiccl-vendor-chunk',
                $dist_url . $vendor_file,
                array(),
                MAGIC_CHECKLISTS_VERSION,
                true
            );
            
            add_filter( 'script_loader_tag', function( $tag, $handle ) {
                if ( $handle === 'magiccl-vendor-chunk' ) {
                    return str_replace( ' src=', ' type="module" src=', $tag );
                }
                return $tag;
            }, 10, 2 );
        } else {
            if (empty($vendor_files)) {
                // Try to find any JS files that might be vendor chunks
                $all_js_files = glob( $dist_path . '*.js' );
                $possible_vendor_files = array_filter($all_js_files, function($file) {
                    $basename = basename($file);
                    return strpos($basename, 'vendor') !== false || 
                           strpos($basename, 'chunk') !== false ||
                           strpos($basename, 'react') !== false;
                });
                
                if (!empty($possible_vendor_files)) {
                    $vendor_file = str_replace( $dist_path, '', $possible_vendor_files[0] );
                    wp_enqueue_script(
                        'magiccl-vendor-chunk',
                        $dist_url . $vendor_file,
                        array(),
                        MAGIC_CHECKLISTS_VERSION,
                        true
                    );
                    
                    add_filter( 'script_loader_tag', function( $tag, $handle ) {
                        if ( $handle === 'magiccl-vendor-chunk' ) {
                            return str_replace( ' src=', ' type="module" src=', $tag );
                        }
                        return $tag;
                    }, 10, 2 );
                    $vendor_handles[] = 'magiccl-vendor-chunk';
                }
            } else {
            }
        }
        
        if ( wp_script_is( 'magiccl-vendor-chunk', 'enqueued' ) || wp_script_is( 'magiccl-vendor-chunk', 'done' ) ) {
            $vendor_handles[] = 'magiccl-vendor-chunk';
        }
        
        // Load Flowbite chunk - only enqueue if not already enqueued
        $flowbite_files = glob( $dist_path . 'flowbite-*.js' );
        
        if ( ! empty( $flowbite_files ) && ! wp_script_is( 'magiccl-flowbite-chunk', 'enqueued' ) ) {
            $flowbite_file = str_replace( $dist_path, '', $flowbite_files[0] );
            wp_enqueue_script(
                'magiccl-flowbite-chunk',
                $dist_url . $flowbite_file,
                array( 'magiccl-vendor-chunk' ),
                MAGIC_CHECKLISTS_VERSION,
                true
            );
            
            add_filter( 'script_loader_tag', function( $tag, $handle ) {
                if ( $handle === 'magiccl-flowbite-chunk' ) {
                    return str_replace( ' src=', ' type="module" src=', $tag );
                }
                return $tag;
            }, 10, 2 );
        }
        
        if ( wp_script_is( 'magiccl-flowbite-chunk', 'enqueued' ) || wp_script_is( 'magiccl-flowbite-chunk', 'done' ) ) {
            $vendor_handles[] = 'magiccl-flowbite-chunk';
        }
        
        // Load utils chunk - only enqueue if not already enqueued
        $utils_files = glob( $dist_path . 'utils-*.js' );
        
        if ( ! empty( $utils_files ) && ! wp_script_is( 'magiccl-utils-chunk', 'enqueued' ) ) {
            $utils_file = str_replace( $dist_path, '', $utils_files[0] );
            wp_enqueue_script(
                'magiccl-utils-chunk',
                $dist_url . $utils_file,
                array( 'magiccl-vendor-chunk' ),
                MAGIC_CHECKLISTS_VERSION,
                true
            );
            
            add_filter( 'script_loader_tag', function( $tag, $handle ) {
                if ( $handle === 'magiccl-utils-chunk' ) {
                    return str_replace( ' src=', ' type="module" src=', $tag );
                }
                return $tag;
            }, 10, 2 );
        }
        
        if ( wp_script_is( 'magiccl-utils-chunk', 'enqueued' ) || wp_script_is( 'magiccl-utils-chunk', 'done' ) ) {
            $vendor_handles[] = 'magiccl-utils-chunk';
        }
        
        return $vendor_handles;
    }
    
    /**
     * Localize data for admin React apps
     */
    private function localize_admin_data() {
        $handle = $this->is_dev_mode ? 'magiccl-react-admin-dev' : 'magiccl-react-admin';

        // Check if script has already been localized to prevent duplicates
        if ( wp_script_is( $handle, 'done' ) ) {
            return;
        }

        // Authorization: only proceed for users allowed on plugin admin pages.
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }
        
        $current_page = 'main';
        $page_params = array();
        
        $screen = get_current_screen();
        if ( $screen ) {
            switch ( $screen->id ) {
                case 'toplevel_page_magiccl_checklists':
                    $current_page = 'main';
                    break;
                case 'magicchecklists_page_magiccl_add_new':
                    $current_page = 'add_new';
                    // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Admin page routing parameters set by WordPress menu system; all values sanitized.
                    $page_params = array(
                        'type' => isset($_GET['type']) ? sanitize_text_field(wp_unslash($_GET['type'])) : '',
                        'checklist_id' => isset($_GET['checklist_id']) ? absint($_GET['checklist_id']) : 0,
                    );
                    // phpcs:enable WordPress.Security.NonceVerification.Recommended
                    break;
                case 'magicchecklists_page_magiccl_tours':
                    $current_page = 'tours';
                    // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Admin page routing parameters set by WordPress menu system; all values sanitized.
                    $page_params = array(
                        'edit' => isset($_GET['edit']) ? absint($_GET['edit']) : 0,
                        'create' => isset($_GET['create']) ? true : false,
                    );
                    // phpcs:enable WordPress.Security.NonceVerification.Recommended
                    break;
                case 'magicchecklists_page_magiccl_import':
                    $current_page = 'import';
                    break;
                case 'magicchecklists_page_magiccl_analytics':
                    $current_page = 'analytics';
                    break;
            }
        }

        // Get analytics data for admin pages
        $analytics_data = array();
        if (class_exists('MAGICCL_Analytics')) {
            $analytics = MAGICCL_Analytics::get_instance();
            
            // For the analytics page, get comprehensive data. For others, just summary.
            if ($current_page === 'analytics') {
                $analytics_data = $analytics->get_comprehensive_analytics();
            } else {
                $analytics_data = $analytics->get_analytics_summary();
            }
        }
        
        wp_localize_script( $handle, 'magicclAdminData', array(
            'ajaxurl' => admin_url( 'admin-ajax.php' ),
            'restUrl' => rest_url( 'magiccl/v1/' ),
            'nonces' => array(
                'wp_rest' => wp_create_nonce( 'wp_rest' ),
                'magiccl_admin' => wp_create_nonce( 'magiccl_admin_nonce' ),
                'magiccl_toggle_active' => wp_create_nonce( 'magiccl_toggle_active' ),
                'magiccl_save_theme_mode' => wp_create_nonce( 'magiccl_save_theme_mode' ),
                'magiccl_save_checklist' => wp_create_nonce( 'magiccl_save_checklist' ),
                'checkShortcut' => wp_create_nonce( 'magiccl_check_shortcut_nonce' ),
                'inviteLinks' => wp_create_nonce( 'magiccl_invite_links_nonce' ),
                'testWebhook' => wp_create_nonce( 'magiccl_test_webhook' ),
                'magiccl_import_checklist' => wp_create_nonce( 'magiccl_import_checklist' ),
                'magiccl_import_json_checklist' => wp_create_nonce( 'magiccl_import_json_checklist' ),
                'magiccl_export_txt' => wp_create_nonce( 'magiccl_export_txt' ),
                'magiccl_export_json' => wp_create_nonce( 'magiccl_export_json' ),
                'magiccl_export_pdf' => wp_create_nonce( 'magiccl_export_pdf' ),
                'magiccl_save_pdf_settings' => wp_create_nonce( 'magiccl_save_pdf_settings' ),
                'magiccl_get_comprehensive_analytics' => wp_create_nonce( 'magiccl_get_comprehensive_analytics' ),
                'magiccl_cleanup_test_data' => wp_create_nonce( 'magiccl_cleanup_test_data' ),
                'magiccl_tour_admin' => wp_create_nonce( 'magiccl_tour_admin' ),
                'magiccl_kanban' => wp_create_nonce( 'magiccl_admin_nonce' ),
            ),
            'currentUser' => wp_get_current_user()->ID,
            'savedTheme' => get_user_meta( get_current_user_id(), 'magiccl_theme', true ),
            'isAdmin' => is_admin(),
            'isDev' => $this->is_dev_mode,
            'pluginUrl' => MAGIC_CHECKLISTS_PLUGIN_URL,
            'admin_url' => admin_url(),
            'dashboard_url' => admin_url('index.php'),
            'currentPage' => $current_page,
            'pageParams' => $page_params,
            'analytics' => $analytics_data,
            'i18n' => $this->get_localization_data(),
            'tutorialExists' => $this->check_tutorial_exists(),
        ));
    }

    /**
     * Check if tutorial checklist exists
     *
     * @return bool
     */
    private function check_tutorial_exists() {
        if (!class_exists('MAGICCL_Tutorial')) {
            require_once MAGIC_CHECKLISTS_PLUGIN_PATH . 'includes/class-mcl-tutorial.php';
        }
        return MAGICCL_Tutorial::get_instance()->tutorial_exists();
    }
    
    /**
     * Get localization data from i18n class
     * 
     * @return array
     */
    private function get_localization_data() {
        // Include the i18n class if not already loaded
        if (!class_exists('MAGICCL_I18n')) {
            require_once MAGIC_CHECKLISTS_PLUGIN_PATH . 'includes/class-mcl-i18n.php';
        }
        
        return MAGICCL_I18n::get_all_translations();
    }
    
    /**
     * Localize data for public React apps
     */
    private function localize_public_data( $public_handle_suffix = '' ) {
        $handle = $this->is_dev_mode ? 'magiccl-react-public-dev' . $public_handle_suffix : 'magiccl-react-public' . $public_handle_suffix;
        
        // Check if script has already been localized to prevent duplicates
        if ( wp_script_is( $handle, 'done' ) ) {
            return;
        }
        
        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Admin/public page routing parameters from bookmarkable URLs; all sanitized with absint/sanitize_text_field.
        $is_tour_mode = isset($_GET['magiccl_tour_mode']) && absint($_GET['magiccl_tour_mode']) === 1;
        $continue_tour_id = isset($_GET['magiccl_continue_tour']) ? absint($_GET['magiccl_continue_tour']) : 0;
        $has_tour_id = isset($_GET['tour_id']) ? absint($_GET['tour_id']) : 0;
        $continue_step = isset($_GET['magiccl_continue_step']) ? absint($_GET['magiccl_continue_step']) : 0;
        // phpcs:enable WordPress.Security.NonceVerification.Recommended
        $tour_mode_detected = $is_tour_mode || $continue_tour_id || $has_tour_id;
        
        // Base public data
        global $magiccl_public_instance;

        $is_pagebuilder_context = false;
        if ( $magiccl_public_instance && method_exists( $magiccl_public_instance, 'is_inside_pagebuilder_context' ) ) {
            $is_pagebuilder_context = (bool) $magiccl_public_instance->is_inside_pagebuilder_context();
        }

        $is_iframe_request = $this->is_iframe_like_request();

        $public_data = array(
            'ajaxurl' => admin_url( 'admin-ajax.php' ),
            'restUrl' => rest_url( 'magiccl/v1/' ),
            'nonces' => array(
                'wp_rest' => wp_create_nonce( 'wp_rest' ),
                'magiccl_admin' => wp_create_nonce( 'magiccl_admin_nonce' ),
                'magiccl_ajax' => wp_create_nonce( 'magiccl_ajax_nonce' ),
                'magiccl_ajax_nopriv' => wp_create_nonce( 'magiccl_ajax_nopriv_nonce' ),
                'magiccl_tour_public' => wp_create_nonce( 'magiccl_tour_public' ),
            ),
            'currentUser' => wp_get_current_user()->ID,
            'isLoggedIn' => is_user_logged_in(),
            'isAdmin' => current_user_can( 'manage_options' ),
            'isDev' => $this->is_dev_mode,
            'pluginUrl' => MAGIC_CHECKLISTS_PLUGIN_URL,
            'context' => array(
                'isPageBuilder' => $is_pagebuilder_context,
                'isIframeRequest' => $is_iframe_request,
            ),
            'priorityColors' => class_exists('MAGICCL_Priority_Utils') ? MAGICCL_Priority_Utils::get_priority_colors() : array(),
            'priorityNumbers' => class_exists('MAGICCL_Priority_Utils') ? MAGICCL_Priority_Utils::get_priority_numbers() : array(),
            'i18n' => $this->get_localization_data()
        );
        
        // Add tour-specific data when in tour mode
        if ($tour_mode_detected) {
            $public_data['nonces']['magiccl_tour_admin'] = wp_create_nonce( 'magiccl_tour_admin' );
            $public_data['nonces']['magiccl_tour_public'] = wp_create_nonce( 'magiccl_tour_public' );
            $public_data['dashboard_url'] = admin_url( 'index.php' );
            $public_data['admin_url'] = admin_url();
        }
        
        // Always add tour data if tours are available for the current page
        $tour_data = $this->get_tour_data_for_js($is_tour_mode, $continue_tour_id, $has_tour_id, $continue_step);
        if (!empty($tour_data['tours'])) {
            
            // Use the same object name that TourPlayback expects
            wp_localize_script( $handle, 'magicclTourPlaybackData', $tour_data );
        }
        
        wp_localize_script( $handle, 'magicclPublicData', $public_data );
    }
    
    /**
     * Get tour data for JavaScript localization
     */
    private function get_tour_data_for_js($is_tour_mode, $continue_tour_id, $has_tour_id, $continue_step = 0) {

        $tours_data = array();

        // Handle tour continuation
        if ($continue_tour_id) {
            $tour = get_post($continue_tour_id);
            if ($tour && $tour->post_type === 'magiccl_tour') {
                $steps = get_post_meta($continue_tour_id, '_magiccl_tour_steps', true) ?: array();
                $settings = get_post_meta($continue_tour_id, '_magiccl_tour_settings', true) ?: array();
                
                $tours_data[] = array(
                    'id' => $continue_tour_id,
                    'title' => $tour->post_title,
                    'steps' => $steps,
                    'settings' => $settings,
                    'autostart' => true,
                    'active' => true,
                    'continue_from_step' => $continue_step
                );
                
            }
        } 
        
        // Handle tour creator mode - load specific tour if provided
        elseif ($is_tour_mode && $has_tour_id) {
            $tour = get_post($has_tour_id);
            if ($tour && $tour->post_type === 'magiccl_tour') {
                $steps = get_post_meta($has_tour_id, '_magiccl_tour_steps', true) ?: array();
                $settings = get_post_meta($has_tour_id, '_magiccl_tour_settings', true) ?: array();
                
                $tours_data[] = array(
                    'id' => $has_tour_id,
                    'title' => $tour->post_title,
                    'steps' => $steps,
                    'settings' => $settings,
                    'autostart' => false,
                    'active' => true,
                    'trigger_type' => get_post_meta($has_tour_id, '_magiccl_tour_trigger_type', true) ?: 'page',
                    'trigger_value' => get_post_meta($has_tour_id, '_magiccl_tour_trigger_value', true) ?: ''
                );
                
            }
        }
        
        // Normal tour loading (only if not in creator mode or continuation mode)
        elseif (!$is_tour_mode && !$continue_tour_id) {
            // Only load normal tours if we have the Tour CPT class available
            if (class_exists('MAGICCL_Tour_CPT')) {
                $active_tours = MAGICCL_Tour_CPT::get_active_tours_for_context();
                
                foreach ($active_tours as $tour) {
                    $tour_id = $tour->ID;
                    $steps = get_post_meta($tour_id, '_magiccl_tour_steps', true) ?: array();
                    $settings = get_post_meta($tour_id, '_magiccl_tour_settings', true) ?: array();
                    
                    // Get autostart from settings first, then fall back to meta field
                    $autostart = false;
                    if (isset($settings['autostart'])) {
                        $autostart = $settings['autostart'];
                    } else {
                        $autostart_meta = get_post_meta($tour_id, '_magiccl_tour_autostart', true);
                        $autostart = !empty($autostart_meta);
                    }
                    
                    $trigger_type = get_post_meta($tour_id, '_magiccl_tour_trigger_type', true) ?: 'page';
                    $trigger_value = get_post_meta($tour_id, '_magiccl_tour_trigger_value', true) ?: '';
                    $user_condition = get_post_meta($tour_id, '_magiccl_tour_user_condition', true) ?: 'all_users';
                    $specific_users = get_post_meta($tour_id, '_magiccl_tour_specific_users', true) ?: array();
                    $specific_roles = get_post_meta($tour_id, '_magiccl_tour_specific_roles', true) ?: array();
                    $show_once = get_post_meta($tour_id, '_magiccl_tour_show_once', true);
                    
                    $tours_data[] = array(
                        'id' => $tour_id,
                        'title' => $tour->post_title,
                        'steps' => $steps,
                        'settings' => $settings,
                        'autostart' => $autostart,
                        'active' => true,
                        'trigger_type' => $trigger_type,
                        'trigger_value' => $trigger_value,
                        'user_condition' => $user_condition,
                        'specific_users' => $specific_users,
                        'specific_roles' => $specific_roles,
                        'show_once' => !empty($show_once)
                    );
                    
                }
            }
        }
        
        return array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => $is_tour_mode ? wp_create_nonce('magiccl_tour_admin') : wp_create_nonce('magiccl_tour_public'),
            'tours' => $tours_data,
            'is_tour_mode' => $is_tour_mode,
            'continue_tour_id' => $continue_tour_id,
            'user_id' => get_current_user_id(),
            'is_logged_in' => is_user_logged_in(),
            'current_url' => $this->get_current_page_url(),
            'user_roles' => is_user_logged_in() ? wp_get_current_user()->roles : array()
        );
    }
    
    /**
     * Get current page URL for tour matching
     */
    private function get_current_page_url() {
        if (is_admin()) {
            // For admin pages, use the full URL including query parameters
            $protocol = is_ssl() ? 'https://' : 'http://';
            $current_url = $protocol . sanitize_text_field(wp_unslash(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '')) . esc_url_raw(wp_unslash(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''));
        } else {
            // For frontend pages, use WordPress functions
            global $wp;
            $current_url = home_url(add_query_arg(array(), $wp->request));
        }
        
        return $current_url;
    }
    
    /**
     * Add script isolation to prevent React render loops when both admin and public apps are loaded
     */
    private function add_script_isolation_for_dual_loading( $public_handle_suffix = '' ) {
        $public_handle = $this->is_dev_mode ? 'magiccl-react-public-dev' . $public_handle_suffix : 'magiccl-react-public' . $public_handle_suffix;

        // Only add once per handle
        if ( did_action( 'magiccl_isolation_added_' . $public_handle ) ) {
            return;
        }
        do_action( 'magiccl_isolation_added_' . $public_handle );

        $isolation_script = "
        (function() {
            // Flag to indicate admin React presence
            window.magicclAdminReactPresent = true;

            // Store original public data temporarily
            if (typeof window.magicclPublicData !== 'undefined') {
                window.magicclPublicDataOriginal = { ...window.magicclPublicData };
                window.magicclPublicData.delayInit = true;
                window.magicclPublicData.dualLoadMode = true;

                let maxWaitTime = 2000;
                let startTime = Date.now();

                const checkAdminReady = function() {
                    const adminRoot = document.querySelector('#magiccl-admin-root');
                    if (adminRoot && adminRoot.children.length > 0) {
                        return true;
                    }
                    return Date.now() - startTime > maxWaitTime;
                };

                const initPublicReact = function() {
                    if (window.magicclPublicDataOriginal) {
                        window.magicclPublicDataOriginal.delayInit = false;
                        window.magicclPublicDataOriginal.dualLoadMode = true;
                        const evt = new CustomEvent('magicclInitPublicReact', { detail: window.magicclPublicDataOriginal });
                        document.dispatchEvent(evt);
                    }
                };

                const waitLoop = function() {
                    if (checkAdminReady()) {
                        initPublicReact();
                    } else {
                        setTimeout(waitLoop, 100);
                    }
                };

                if (document.readyState === 'loading') {
                    document.addEventListener('DOMContentLoaded', function() { setTimeout(waitLoop, 100); });
                } else {
                    waitLoop();
                }
            }
        })();
        ";

        wp_add_inline_script( $public_handle, $isolation_script, 'before' );
    }

    /**
     * Add tour script isolation to prevent driver.js conflicts when multiple instances load
     */
    private function add_tour_script_isolation( $handle_suffix = '' ) {
        $tour_handle = 'magiccl-driver-js' . $handle_suffix;

        // Only add once per handle
        if ( did_action( 'magiccl_tour_isolation_added_' . $tour_handle ) ) {
            return;
        }
        do_action( 'magiccl_tour_isolation_added_' . $tour_handle );

        $tour_script = "
        (function() {
            if (window.magicclDriverInstance || window.magicclDriverInitializing) { return; }
            window.magicclDriverInitializing = true;
            document.addEventListener('DOMContentLoaded', function() {
                setTimeout(function() {
                    if (typeof window.Driver !== 'undefined' && !window.magicclDriverInstance) {
                        window.magicclDriverInstance = new window.Driver();
                    }
                    window.magicclDriverInitializing = false;
                }, 100);
            });
        })();
        ";

        wp_add_inline_script( $tour_handle, $tour_script, 'before' );
    }

    /**
     * Get development status
     */
    public function is_development_mode() {
        return $this->is_dev_mode;
    }
    
    /**
     * Output the Vite React Refresh preamble snippet for HMR
     */
    public function vite_refresh_preamble() {
        // HMR preamble required by @vitejs/plugin-react
        $refresh_script = 'import RefreshRuntime from "' . esc_url( $this->vite_dev_server ) . '/@react-refresh";'
            . 'RefreshRuntime.injectIntoGlobalHook(window);'
            . 'window.$RefreshReg$ = () => {};'
            . 'window.$RefreshSig$ = () => type => type;';
        wp_register_script( 'magiccl-vite-refresh', false, array(), '1.0.0', false );
        wp_enqueue_script( 'magiccl-vite-refresh' );
        wp_add_inline_script( 'magiccl-vite-refresh', $refresh_script );
    }
    
    /**
     * Add React root element to the DOM
     */
    public function add_react_root_elements() {
        // Prevent multiple root additions
        static $roots_added = false;
        if ( $roots_added ) {
            return;
        }
        
        // Get the MAGICCL_Public instance to leverage its existing logic
        global $magiccl_public_instance;
        if ( ! $magiccl_public_instance ) {
            return; // No point adding roots if MAGICCL_Public isn't even loaded
        }
        
        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Public/admin page routing parameters from bookmarkable URLs; all sanitized with absint().
        $is_tour_mode = isset($_GET['magiccl_tour_mode']) && absint($_GET['magiccl_tour_mode']) === 1;
        $continue_tour_id = isset($_GET['magiccl_continue_tour']) ? absint($_GET['magiccl_continue_tour']) : 0;
        $has_tour_id = isset($_GET['tour_id']) ? absint($_GET['tour_id']) : 0;
        // phpcs:enable WordPress.Security.NonceVerification.Recommended

        // Check for active tours via Tour CPT
        $has_active_tours = false;
        if (class_exists('MAGICCL_Tour_CPT')) {
            $active_tours = MAGICCL_Tour_CPT::get_active_tours_for_context();
            $has_active_tours = !empty($active_tours);
        }
        
        // Force React roots for tour mode, regardless of checklist conditions
        $force_load_for_tours = $is_tour_mode || $continue_tour_id || $has_tour_id || $has_active_tours;
        
        // Check tour mode cookie as fallback
        if (!$force_load_for_tours && isset($_COOKIE['magiccl_tour_mode']) && sanitize_text_field(wp_unslash($_COOKIE['magiccl_tour_mode'])) === '1') {
            $force_load_for_tours = true;
        }
        
        if ($force_load_for_tours) {
        }
        
        if ( ! is_admin() ) {
            // For frontend pages, check if we should add public root
            if ( $force_load_for_tours || $magiccl_public_instance->should_load_assets() ) {
                // Add public root element on frontend pages
                echo '<div id="magiccl-public-root"></div>';
                $roots_added = true;
            }
        } else {
            // Check if this is a plugin admin page
            $screen = get_current_screen();
            if ( $screen ) {
                $plugin_pages = array(
                    'toplevel_page_magic_plugins',        // Main MagicPlugins landing page
                    'magicplugins_page_magiccl_checklists',    // MagicChecklists main page
                    'magicplugins_page_magiccl_manage_license' // License management page
                );
                
                if ( in_array( $screen->id, $plugin_pages ) ) {
                    // Only add public root if there are actual checklists that need drawer/floating buttons
                    // MAGICCL_Admin already creates the magiccl-admin-root div in page content
                    if ( $force_load_for_tours || $magiccl_public_instance->should_load_assets() ) {
                        echo '<div id="magiccl-public-root"></div>';
                        $roots_added = true;
                    }
                } else {
                    // For non-plugin admin pages, check if we should add public root
                    if ( $force_load_for_tours || $magiccl_public_instance->should_load_assets() ) {
                        // Public React handles drawer/floating buttons on admin pages
                        echo '<div id="magiccl-public-root"></div>';
                        $roots_added = true;
                    }
                }
            }
        }
    }
    
    /**
     * Add admin styles for React integration
     */
    public function add_admin_styles() {
        // Only add styles on plugin pages - check specific hook names
        $screen = get_current_screen();
        if ( ! $screen ) {
            return;
        }
        
        $plugin_pages = array(
            'toplevel_page_magic_plugins',        // Main MagicPlugins landing page
            'magicplugins_page_magiccl_checklists',    // MagicChecklists main page
            'magicplugins_page_magiccl_manage_license' // License management page
        );
        
        if ( ! in_array( $screen->id, $plugin_pages ) ) {
            return;
        }
        
        ?>
        <?php
        $admin_root_css = '#magiccl-admin-root { width: 100%; min-height: 100%; margin: 0; padding: 0; background: transparent; }
        .wrap #magiccl-admin-root { margin: 0; }
        @media screen and (max-width: 782px) { #magiccl-admin-root { min-height: calc(100vh - 46px); } }
        #wpfooter { display: none !important; }
        #wpcontent { padding: 0 !important; }
        #wpbody-content { padding-bottom: 0 !important; }
        html:not(.dark) body, html:not(.dark) #wpwrap { background-color: #f4f4f4 !important; }
        html.dark body, html.dark #wpwrap { background-color: #011326 !important; }';
        wp_register_style('magiccl-admin-root-inline', false);
        wp_enqueue_style('magiccl-admin-root-inline');
        wp_add_inline_style('magiccl-admin-root-inline', $admin_root_css);
        ?>
        <?php
    }

    /**
     * Check if current admin page is a plugin admin page
     */
    private function is_plugin_admin_page() {
        if ( ! is_admin() ) {
            return false;
        }
        
        $screen = get_current_screen();
        if ( ! $screen ) {
            return false;
        }
        
        $plugin_pages = array(
            'toplevel_page_magic_plugins',        // Main MagicPlugins landing page
            'magicplugins_page_magiccl_checklists',    // MagicChecklists main page
            'magicplugins_page_magiccl_manage_license' // License management page
        );
        
        return in_array( $screen->id, $plugin_pages );
    }

    private function should_load_tour_assets() {
        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Public/admin page routing parameters from bookmarkable URLs; all sanitized with absint().
        $is_tour_mode = isset($_GET['magiccl_tour_mode']) && absint($_GET['magiccl_tour_mode']) === 1;
        $continue_tour_id = isset($_GET['magiccl_continue_tour']) ? absint($_GET['magiccl_continue_tour']) : 0;
        $has_tour_id = isset($_GET['tour_id']) ? absint($_GET['tour_id']) : 0;
        // phpcs:enable WordPress.Security.NonceVerification.Recommended
        
        // Check tour mode cookie as fallback
        $tour_cookie = isset($_COOKIE['magiccl_tour_mode']) && sanitize_text_field(wp_unslash($_COOKIE['magiccl_tour_mode'])) === '1';
        
        return $is_tour_mode || $continue_tour_id || $has_tour_id || $tour_cookie;
    }

    /**
     * Enqueue driver.js and related tour assets when needed
     */
    private function enqueue_tour_assets() {
        // Only enqueue if not already loaded - check multiple possible handles
        if (wp_script_is('driver-js', 'enqueued') || wp_script_is('driver-js', 'done') ||
            wp_script_is('magiccl-driver-js', 'enqueued') || wp_script_is('magiccl-driver-js', 'done')) {
            return;
        }
        
        // Determine handle suffix based on context to prevent conflicts
        $handle_suffix = '';
        if (is_admin() && $this->is_plugin_admin_page()) {
            $handle_suffix = '-admin';
        } elseif (isset($_GET['magiccl_tour_mode']) || isset($_GET['magiccl_continue_tour']) || isset($_GET['tour_id'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Existence check only for handle suffix; no values used.
            $handle_suffix = '-tour';
        }
        
        // Enqueue driver.js with unique handle
        wp_enqueue_script(
            'magiccl-driver-js' . $handle_suffix,
            MAGIC_CHECKLISTS_PUBLIC_URL . 'assets/js/vendor/driver.js.iife.js',
            array(),
            '1.3.1',
            true
        );

        // Only enqueue CSS once globally (no conflicts with CSS)
        if (!wp_style_is('magiccl-driver-css', 'enqueued') && !wp_style_is('magiccl-driver-css', 'done')) {
            wp_enqueue_style(
                'magiccl-driver-css',
                MAGIC_CHECKLISTS_PUBLIC_URL . 'assets/js/vendor/driver.css',
                array(),
                '1.3.1'
            );

            // Enqueue tour public styles
            wp_enqueue_style(
                'magiccl-tour-driver',
                MAGIC_CHECKLISTS_PUBLIC_URL . 'assets/css/magiccl-tour-driver.css',
                array('magiccl-driver-css'),
                MAGIC_CHECKLISTS_VERSION
            );
        }
        
        // React isolation will be handled globally via enqueue_public_* methods
    }

    private function is_iframe_like_request() {
        if ( isset( $_SERVER['HTTP_SEC_FETCH_DEST'] ) && sanitize_text_field(wp_unslash($_SERVER['HTTP_SEC_FETCH_DEST'])) === 'iframe' ) {
            return true;
        }

        if ( isset( $_SERVER['HTTP_SEC_FETCH_MODE'] ) && sanitize_text_field(wp_unslash($_SERVER['HTTP_SEC_FETCH_MODE'])) === 'navigate' ) {
            return false;
        }

        if ( isset( $_SERVER['HTTP_SEC_FETCH_SITE'] ) && sanitize_text_field(wp_unslash($_SERVER['HTTP_SEC_FETCH_SITE'])) === 'same-origin' && isset( $_SERVER['HTTP_SEC_FETCH_DEST'] ) && sanitize_text_field(wp_unslash($_SERVER['HTTP_SEC_FETCH_DEST'])) === 'nested-document' ) {
            return true;
        }

        return false;
    }
}
