<?php
/**
 * Plugin Name: Jabali Cache
 * Plugin URI: https://github.com/shukiv/jabali-panel
 * Description: High-performance caching for WordPress - Redis object cache, nginx page cache, lazy loading, and more.
 * Version: 2.6.0
 * Author: Jabali Panel
 * Author URI: https://github.com/shukiv/jabali-panel
 * License: GPL-2.0+
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: jabali-cache
 *
 * @package Jabali_Cache
 */

defined('ABSPATH') || exit;

class Jabali_Cache_Plugin {

    const VERSION = '2.6.0';
    const OPTION_KEY = 'jabali_cache_settings';

    private static $instance = null;
    private $settings = [];

    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        $this->settings = $this->get_settings();

        add_action('admin_menu', [$this, 'add_admin_menu']);
        add_action('admin_init', [$this, 'register_settings']);
        add_action('admin_init', [$this, 'handle_actions']);
        add_action('admin_bar_menu', [$this, 'add_admin_bar_menu'], 100);
        add_filter('plugin_action_links_' . plugin_basename(__FILE__), [$this, 'add_action_links']);
        add_action('admin_enqueue_scripts', [$this, 'admin_styles']);

        // Initialize optimization features
        $this->init_optimizations();

        // Initialize plugin compatibility hooks for cache invalidation
        $this->init_plugin_compatibility();

        // Initialize smart page cache purge hooks
        $this->init_page_cache_purge_hooks();
    }

    /**
     * Initialize hooks for smart page cache purging
     * Automatically purges nginx cache when content changes
     */
    private function init_page_cache_purge_hooks() {
        // Only initialize if page cache is enabled
        if (!$this->settings['page_cache']) {
            return;
        }

        // Post changes
        add_action('save_post', [$this, 'purge_post_cache'], 10, 3);
        add_action('wp_trash_post', [$this, 'purge_post_cache_on_delete']);
        add_action('delete_post', [$this, 'purge_post_cache_on_delete']);
        add_action('edit_post', [$this, 'purge_post_cache_on_edit'], 10, 2);

        // Comment changes
        add_action('comment_post', [$this, 'purge_comment_cache'], 10, 2);
        add_action('edit_comment', [$this, 'purge_comment_cache']);
        add_action('wp_set_comment_status', [$this, 'purge_comment_cache']);

        // Menu changes
        add_action('wp_update_nav_menu', [$this, 'purge_all_cache']);

        // Theme/Customizer changes
        add_action('switch_theme', [$this, 'purge_all_cache']);
        add_action('customize_save_after', [$this, 'purge_all_cache']);
        add_action('update_option_theme_mods_' . get_template(), [$this, 'purge_all_cache']);

        // Sidebar/Widget changes
        add_action('update_option_sidebars_widgets', [$this, 'purge_all_cache']);

        // Permalink structure changes
        add_action('update_option_permalink_structure', [$this, 'purge_all_cache']);

        // WooCommerce specific hooks
        if (class_exists('WooCommerce')) {
            add_action('woocommerce_product_set_stock', [$this, 'purge_woocommerce_product']);
            add_action('woocommerce_variation_set_stock', [$this, 'purge_woocommerce_product']);
            add_action('woocommerce_product_set_stock_status', [$this, 'purge_woocommerce_product_stock_status'], 10, 3);
            add_action('woocommerce_update_product', [$this, 'purge_woocommerce_product_by_id']);
            add_action('woocommerce_new_product', [$this, 'purge_woocommerce_product_by_id']);
            add_action('woocommerce_delete_product', [$this, 'purge_woocommerce_product_by_id']);
            add_action('woocommerce_trash_product', [$this, 'purge_woocommerce_product_by_id']);
        }
    }

    /**
     * Purge cache for a specific post and related pages
     */
    public function purge_post_cache($post_id, $post = null, $update = true) {
        // Skip autosaves and revisions
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }

        if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
            return;
        }

        if (!$post) {
            $post = get_post($post_id);
        }

        if (!$post || $post->post_status === 'auto-draft') {
            return;
        }

        $paths_to_purge = $this->get_post_related_paths($post);
        $this->purge_paths($paths_to_purge);
    }

    /**
     * Purge cache when post is deleted or trashed
     */
    public function purge_post_cache_on_delete($post_id) {
        $post = get_post($post_id);
        if (!$post) {
            return;
        }

        $paths_to_purge = $this->get_post_related_paths($post);
        $this->purge_paths($paths_to_purge);
    }

    /**
     * Purge cache on post edit
     */
    public function purge_post_cache_on_edit($post_id, $post) {
        $this->purge_post_cache($post_id, $post, true);
    }

    /**
     * Purge cache when a comment changes
     */
    public function purge_comment_cache($comment_id, $approved = null) {
        $comment = get_comment($comment_id);
        if (!$comment) {
            return;
        }

        $post = get_post($comment->comment_post_ID);
        if ($post) {
            $paths_to_purge = [get_permalink($post)];
            $this->purge_paths($paths_to_purge);
        }
    }

    /**
     * Get all paths related to a post that should be purged
     */
    private function get_post_related_paths($post) {
        $paths = [];

        // Post URL
        $permalink = get_permalink($post);
        if ($permalink) {
            $paths[] = $permalink;
        }

        // Home page
        $paths[] = home_url('/');

        // Blog page (if different from home)
        $blog_page_id = get_option('page_for_posts');
        if ($blog_page_id) {
            $paths[] = get_permalink($blog_page_id);
        }

        // Category archives
        $categories = get_the_category($post->ID);
        if ($categories) {
            foreach ($categories as $category) {
                $paths[] = get_category_link($category->term_id);
            }
        }

        // Tag archives
        $tags = get_the_tags($post->ID);
        if ($tags) {
            foreach ($tags as $tag) {
                $paths[] = get_tag_link($tag->term_id);
            }
        }

        // Author archive
        $paths[] = get_author_posts_url($post->post_author);

        // Date archives
        $post_date = strtotime($post->post_date);
        $paths[] = get_year_link(date('Y', $post_date));
        $paths[] = get_month_link(date('Y', $post_date), date('m', $post_date));
        $paths[] = get_day_link(date('Y', $post_date), date('m', $post_date), date('d', $post_date));

        // Post type archive (for custom post types)
        if ($post->post_type !== 'post' && $post->post_type !== 'page') {
            $archive_link = get_post_type_archive_link($post->post_type);
            if ($archive_link) {
                $paths[] = $archive_link;
            }
        }

        // Taxonomy archives for custom post types
        $taxonomies = get_object_taxonomies($post->post_type);
        foreach ($taxonomies as $taxonomy) {
            if ($taxonomy !== 'category' && $taxonomy !== 'post_tag') {
                $terms = get_the_terms($post->ID, $taxonomy);
                if ($terms && !is_wp_error($terms)) {
                    foreach ($terms as $term) {
                        $paths[] = get_term_link($term);
                    }
                }
            }
        }

        // Remove duplicates and filter
        $paths = array_unique(array_filter($paths, function($path) {
            return !is_wp_error($path) && !empty($path);
        }));

        return $paths;
    }

    /**
     * Purge cache for WooCommerce product (from stock change)
     */
    public function purge_woocommerce_product($product) {
        if (is_numeric($product)) {
            $product_id = $product;
        } else {
            $product_id = $product->get_id();
        }
        $this->purge_woocommerce_product_by_id($product_id);
    }

    /**
     * Purge cache for WooCommerce product stock status change
     */
    public function purge_woocommerce_product_stock_status($product_id, $stock_status, $product) {
        $this->purge_woocommerce_product_by_id($product_id);
    }

    /**
     * Purge cache for WooCommerce product by ID
     */
    public function purge_woocommerce_product_by_id($product_id) {
        $paths = [];

        // Product URL
        $permalink = get_permalink($product_id);
        if ($permalink) {
            $paths[] = $permalink;
        }

        // Home page
        $paths[] = home_url('/');

        // Shop page
        $shop_page_id = wc_get_page_id('shop');
        if ($shop_page_id > 0) {
            $paths[] = get_permalink($shop_page_id);
        }

        // Product categories
        $terms = get_the_terms($product_id, 'product_cat');
        if ($terms && !is_wp_error($terms)) {
            foreach ($terms as $term) {
                $paths[] = get_term_link($term);
            }
        }

        // Product tags
        $tags = get_the_terms($product_id, 'product_tag');
        if ($tags && !is_wp_error($tags)) {
            foreach ($tags as $tag) {
                $paths[] = get_term_link($tag);
            }
        }

        $paths = array_unique(array_filter($paths, function($path) {
            return !is_wp_error($path) && !empty($path);
        }));

        $this->purge_paths($paths);
    }

    /**
     * Purge all cache (for site-wide changes)
     */
    public function purge_all_cache() {
        $this->purge_paths(['/']);
    }

    /**
     * Send purge request to Jabali Panel API
     */
    private function purge_paths(array $paths) {
        if (empty($paths)) {
            return false;
        }

        // Get domain from site URL
        $site_url = get_site_url();
        $parsed = parse_url($site_url);
        $domain = $parsed['host'] ?? '';

        if (empty($domain)) {
            return false;
        }

        // Generate secret from AUTH_KEY
        $secret = defined('AUTH_KEY') ? substr(md5(AUTH_KEY), 0, 32) : '';
        if (empty($secret)) {
            return false;
        }

        // Convert full URLs to paths
        $normalized_paths = [];
        foreach ($paths as $url) {
            if ($url === '/') {
                $normalized_paths[] = '/';
            } else {
                $parsed_url = parse_url($url);
                $path = $parsed_url['path'] ?? '/';
                $normalized_paths[] = $path;
            }
        }

        $normalized_paths = array_unique($normalized_paths);

        // Check if we should purge all (if home is in the list)
        $purge_all = in_array('/', $normalized_paths) && count($normalized_paths) > 5;

        // Call Jabali Panel internal API
        $response = wp_remote_post('https://127.0.0.1/api/internal/page-cache-purge', [
            'timeout' => 10,
            'sslverify' => false,
            'headers' => [
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
            ],
            'body' => json_encode([
                'domain' => $domain,
                'paths' => $purge_all ? [] : $normalized_paths,
                'purge_all' => $purge_all,
                'secret' => $secret,
            ]),
        ]);

        if (is_wp_error($response)) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log('Jabali Cache: Failed to purge page cache - ' . $response->get_error_message());
            }
            return false;
        }

        $code = wp_remote_retrieve_response_code($response);
        if ($code !== 200) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                $body = wp_remote_retrieve_body($response);
                error_log('Jabali Cache: Failed to purge page cache - HTTP ' . $code . ' - ' . $body);
            }
            return false;
        }

        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('Jabali Cache: Purged ' . count($normalized_paths) . ' paths');
        }

        return true;
    }

    /**
     * Initialize hooks for theme/plugin asset regeneration
     * Uses general WordPress hooks instead of plugin-specific ones
     */
    private function init_plugin_compatibility() {
        // General: Catch ALL option updates that might trigger CSS/JS regeneration
        add_action('updated_option', [$this, 'on_option_updated'], 10, 3);

        // General: Theme/plugin updates
        add_action('upgrader_process_complete', [$this, 'flush_all_builder_cache'], 10, 2);
        add_action('switch_theme', [$this, 'flush_all_builder_cache']);
        add_action('customize_save_after', [$this, 'flush_all_builder_cache']);

        // General: When any cache clear action is triggered by popular builders
        // These are catch-all hooks that most builders fire
        add_action('wp_cache_flush', [$this, 'flush_all_builder_cache']);
        add_action('litespeed_purge_all', [$this, 'flush_all_builder_cache']);

        // WooCommerce product changes (affects displayed content)
        add_action('woocommerce_delete_product_transients', [$this, 'flush_woocommerce_cache']);
        add_action('woocommerce_clear_product_transients', [$this, 'flush_woocommerce_cache']);
    }

    /**
     * Patterns in option names that indicate CSS/JS regeneration needed
     */
    private function get_builder_option_patterns(): array {
        return [
            // Page builders
            'elementor', 'uagb', 'spectra', 'fl_builder', 'beaver', 'et_divi', 'et_builder',
            'vc_', 'wpb_', 'generateblocks', 'kadence', 'brizy', 'oxygen', 'breakdance',
            // Themes
            'astra', 'theme_mods_', 'flavor',
            // Optimization plugins
            'autoptimize', 'wp_rocket', 'sg_optimizer', 'litespeed', 'w3tc', 'wp_optimize',
            // CSS/JS settings
            '_css', '_js', '_style', '_script', '_assets', '_cache',
        ];
    }

    /**
     * Check if option update should trigger cache flush
     */
    public function on_option_updated($option, $old_value, $new_value) {
        // Skip if values are identical
        if ($old_value === $new_value) {
            return;
        }

        $option_lower = strtolower($option);
        foreach ($this->get_builder_option_patterns() as $pattern) {
            if (strpos($option_lower, $pattern) !== false) {
                $this->flush_all_builder_cache();
                return;
            }
        }
    }

    /**
     * Flush ALL builder-related transients and page cache
     * Single method that handles all builders/themes
     */
    public function flush_all_builder_cache($upgrader = null, $options = null) {
        // Prevent multiple flushes in same request
        static $flushed = false;
        if ($flushed) {
            return;
        }
        $flushed = true;

        // Flush Redis transients matching any builder pattern
        $patterns = [
            // Page builders
            'elementor_', '_elementor', 'uagb_', '_uagb', 'spectra_', '_spectra',
            'fl_builder_', '_fl_builder', 'et_core_', 'et_builder_', '_et_core', '_et_builder',
            'vc_', '_vc_', 'generateblocks_', 'kadence_', 'kt_', 'brizy_', 'oxygen_', 'breakdance_',
            // Themes
            'astra_', '_astra', 'theme_mod_',
            // Optimization
            'autoptimize_', 'wprocket_', 'litespeed_',
            // Generic
            '_css_', '_js_', '_style_', '_assets_',
        ];

        $this->flush_transients_by_patterns($patterns);

        // Purge nginx page cache
        if ($this->settings['page_cache']) {
            $this->purge_all_cache();
        }

        $this->log_cache_flush('Builder/Theme');
    }

    /**
     * Flush WooCommerce related transients
     */
    public function flush_woocommerce_cache() {
        $this->flush_transients_by_patterns(['wc_', '_wc_', 'woocommerce_']);
        $this->log_cache_flush('WooCommerce');
    }

    /**
     * Flush transients matching specific patterns from Redis
     *
     * @param array $patterns Array of patterns to match (e.g., ['uagb_', 'spectra_'])
     * @return int Number of keys deleted
     */
    private function flush_transients_by_patterns(array $patterns) {
        if (!$this->is_redis_connected()) {
            return 0;
        }

        try {
            $redis = new Redis();
            $host = defined('JABALI_CACHE_HOST') ? JABALI_CACHE_HOST : '127.0.0.1';
            $port = defined('JABALI_CACHE_PORT') ? JABALI_CACHE_PORT : 6379;
            $db = defined('JABALI_CACHE_DATABASE') ? JABALI_CACHE_DATABASE : 0;
            $prefix = defined('JABALI_CACHE_PREFIX') ? JABALI_CACHE_PREFIX : '';

            if (!$redis->connect($host, $port, 2)) {
                return 0;
            }

            // Authenticate if credentials are defined
            if (defined('JABALI_CACHE_REDIS_USER') && defined('JABALI_CACHE_REDIS_PASS')) {
                $redis->auth(['user' => JABALI_CACHE_REDIS_USER, 'pass' => JABALI_CACHE_REDIS_PASS]);
            } elseif (defined('JABALI_CACHE_REDIS_PASS') && JABALI_CACHE_REDIS_PASS) {
                $redis->auth(JABALI_CACHE_REDIS_PASS);
            }

            $redis->select($db);

            $deleted = 0;
            foreach ($patterns as $pattern) {
                // Search for transient keys matching the pattern
                // WordPress stores transients as: {prefix}transient_{name} and {prefix}_transient_{name}
                $scan_patterns = [
                    $prefix . '*transient*' . $pattern . '*',
                    $prefix . '*' . $pattern . '*transient*',
                    $prefix . '*' . $pattern . '*',
                ];

                foreach ($scan_patterns as $scan_pattern) {
                    $cursor = null;
                    do {
                        $keys = $redis->scan($cursor, $scan_pattern, 100);
                        if ($keys !== false && !empty($keys)) {
                            foreach ($keys as $key) {
                                $redis->del($key);
                                $deleted++;
                            }
                        }
                    } while ($cursor > 0);
                }
            }

            $redis->close();
            return $deleted;

        } catch (Exception $e) {
            error_log('Jabali Cache: Failed to flush transients - ' . $e->getMessage());
            return 0;
        }
    }

    /**
     * Log cache flush event for debugging
     */
    private function log_cache_flush($plugin_name) {
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log(sprintf('Jabali Cache: Flushed Redis transients triggered by %s asset regeneration', $plugin_name));
        }
    }

    public function get_settings() {
        $defaults = [
            'page_cache' => true,
            'object_cache' => true,
            'html_minify' => false,
            'minify_css' => true,
            'minify_js' => true,
            'lazy_load' => false,
            'lazy_load_iframes' => false,
            'browser_cache' => false,
            'expired_cache' => false,
            'remove_query_strings' => false,
            'disable_emojis' => false,
            'disable_embeds' => false,
            'defer_js' => false,
            'cache_debug' => true,
            'local_google_fonts' => false,
            // LCP Optimization settings
            'lcp_preload' => true,
            'preconnect_hints' => true,
            'preload_fonts' => true,
            'delay_third_party' => false,
        ];
        $saved = get_option(self::OPTION_KEY, []);
        return array_merge($defaults, $saved);
    }

    public function init_optimizations() {
        // Page Cache bypass - send no-cache headers when disabled
        if (!$this->settings['page_cache'] && !is_admin()) {
            add_action('send_headers', [$this, 'disable_page_cache_headers'], 1);
        }

        // HTML Minification
        if ($this->settings['html_minify'] && !is_admin()) {
            add_action('template_redirect', [$this, 'start_html_buffer'], 1);
        }

        // CSS Minification
        if ($this->settings['minify_css'] && !is_admin()) {
            add_filter('style_loader_tag', [$this, 'minify_inline_css'], 10, 4);
            add_action('wp_head', [$this, 'start_css_capture'], 1);
            add_action('wp_head', [$this, 'end_css_capture'], 999);
        }

        // JS Minification
        if ($this->settings['minify_js'] && !is_admin()) {
            add_filter('script_loader_tag', [$this, 'minify_inline_js'], 10, 3);
        }

        // Defer JS
        if ($this->settings['defer_js'] && !is_admin()) {
            add_filter('script_loader_tag', [$this, 'defer_js'], 10, 3);
        }

        // Lazy Loading
        if ($this->settings['lazy_load'] && !is_admin()) {
            add_filter('the_content', [$this, 'add_lazy_loading']);
            add_filter('post_thumbnail_html', [$this, 'add_lazy_loading']);
            add_filter('get_avatar', [$this, 'add_lazy_loading']);
            add_filter('widget_text', [$this, 'add_lazy_loading']);
        }

        // Lazy Load iframes
        if ($this->settings['lazy_load_iframes'] && !is_admin()) {
            add_filter('the_content', [$this, 'add_lazy_loading_iframes']);
            add_filter('embed_oembed_html', [$this, 'add_lazy_loading_iframes']);
        }

        // Remove Query Strings
        if ($this->settings['remove_query_strings'] && !is_admin()) {
            add_filter('script_loader_src', [$this, 'remove_query_strings'], 15);
            add_filter('style_loader_src', [$this, 'remove_query_strings'], 15);
        }

        // Disable Emojis
        if ($this->settings['disable_emojis']) {
            $this->disable_emojis();
        }

        // Disable Embeds
        if ($this->settings['disable_embeds']) {
            $this->disable_embeds();
        }

        // Expired Cache (No-Cache Headers)
        if ($this->settings['expired_cache'] && !is_admin()) {
            add_action('template_redirect', [$this, 'send_expired_cache_headers'], 1);
            add_action('send_headers', [$this, 'send_expired_cache_headers']);
        }

        // Debug mode - add debug info for admins
        if ($this->settings['cache_debug'] && !is_admin()) {
            add_action('wp_footer', [$this, 'output_debug_info'], 999);
        }

        // Local Google Fonts
        if ($this->settings['local_google_fonts'] && !is_admin()) {
            add_filter('style_loader_src', [$this, 'localize_google_fonts_css'], 10, 2);
            add_filter('wp_resource_hints', [$this, 'remove_google_fonts_preconnect'], 10, 2);
        }

        // LCP Image Optimization (preload + fetchpriority)
        if ($this->settings['lcp_preload'] && !is_admin()) {
            add_filter('the_content', [$this, 'optimize_lcp_image'], 5);
            add_filter('post_thumbnail_html', [$this, 'optimize_lcp_image'], 5);
            add_action('wp_head', [$this, 'output_lcp_preload'], 1);
        }

        // Preconnect Hints
        if ($this->settings['preconnect_hints'] && !is_admin()) {
            add_action('wp_head', [$this, 'output_preconnect_hints'], 1);
        }

        // Font Preload
        if ($this->settings['preload_fonts'] && !is_admin()) {
            add_action('wp_head', [$this, 'output_font_preload'], 2);
        }

        // Delay Third-Party Scripts
        if ($this->settings['delay_third_party'] && !is_admin()) {
            add_filter('script_loader_tag', [$this, 'delay_third_party_scripts'], 10, 3);
        }
    }

    /**
     * CSS Minification - minify inline styles in style tags
     */
    public function minify_inline_css($html, $handle, $href, $media) {
        return $html; // Return unchanged, we don't minify external CSS files
    }

    private $css_buffer_active = false;

    public function start_css_capture() {
        // Not implemented - inline CSS minification would require output buffering
        // which conflicts with page cache. External files are better cached by nginx.
    }

    public function end_css_capture() {
        // Not implemented
    }

    /**
     * Minify inline JS within script tags
     */
    public function minify_inline_js($tag, $handle, $src) {
        // Don't touch external scripts
        if (!empty($src)) {
            return $tag;
        }

        // Skip certain handles that shouldn't be minified
        $skip_handles = ['jquery-core', 'jquery-migrate', 'wp-embed'];
        if (in_array($handle, $skip_handles)) {
            return $tag;
        }

        // Simple minification for inline scripts - just collapse whitespace
        // Being conservative to avoid breaking scripts
        $tag = preg_replace_callback('/<script([^>]*)>(.*?)<\/script>/is', function($match) {
            $attrs = $match[1];
            $content = $match[2];

            // Skip if it contains JSON or data
            if (strpos($content, 'application/json') !== false || strpos($content, 'application/ld+json') !== false) {
                return $match[0];
            }

            // Very conservative minification - only collapse multiple spaces/newlines
            $content = preg_replace('/\s{2,}/', ' ', $content);
            $content = trim($content);

            return '<script' . $attrs . '>' . $content . '</script>';
        }, $tag);

        return $tag;
    }

    /**
     * Output debug info for admins
     */
    public function output_debug_info() {
        // Only show for admins with cache_debug param or setting enabled
        if (!current_user_can('manage_options')) {
            return;
        }

        // Check if ?cache_debug=1 is set
        if (!isset($_GET['cache_debug']) && !$this->settings['cache_debug']) {
            return;
        }

        // Only output if explicitly requested via query param
        if (!isset($_GET['cache_debug']) || $_GET['cache_debug'] !== '1') {
            return;
        }

        $debug_info = [];
        $debug_info['plugin_version'] = self::VERSION;
        $debug_info['page_cache'] = $this->settings['page_cache'] ? 'enabled' : 'disabled';
        $debug_info['object_cache'] = $this->is_drop_in_installed() ? 'enabled' : 'disabled';
        $debug_info['redis_connected'] = $this->is_redis_connected() ? 'yes' : 'no';
        $debug_info['minify_css'] = $this->settings['minify_css'] ? 'enabled' : 'disabled';
        $debug_info['minify_js'] = $this->settings['minify_js'] ? 'enabled' : 'disabled';
        $debug_info['defer_js'] = $this->settings['defer_js'] ? 'enabled' : 'disabled';
        $debug_info['lazy_load'] = $this->settings['lazy_load'] ? 'enabled' : 'disabled';
        $debug_info['logged_in'] = is_user_logged_in() ? 'yes' : 'no';
        $debug_info['bypass_reason'] = $this->get_cache_bypass_reason();
        $debug_info['page_generated'] = date('Y-m-d H:i:s');
        $debug_info['queries'] = get_num_queries();
        $debug_info['memory_peak'] = size_format(memory_get_peak_usage(true));

        echo "\n<!-- Jabali Cache Debug Info\n";
        foreach ($debug_info as $key => $value) {
            echo "  {$key}: {$value}\n";
        }
        echo "-->\n";
    }

    /**
     * Get reason why page cache might be bypassed
     */
    private function get_cache_bypass_reason() {
        if (is_user_logged_in()) {
            return 'logged_in_user';
        }

        if (isset($_POST) && !empty($_POST)) {
            return 'post_request';
        }

        if (is_admin()) {
            return 'admin_page';
        }

        // Check for WooCommerce cart/checkout
        if (function_exists('is_cart') && is_cart()) {
            return 'woocommerce_cart';
        }
        if (function_exists('is_checkout') && is_checkout()) {
            return 'woocommerce_checkout';
        }
        if (function_exists('is_account_page') && is_account_page()) {
            return 'woocommerce_account';
        }

        // Check for cookies that trigger bypass
        if (isset($_COOKIE['wordpress_logged_in']) || isset($_COOKIE['wp-postpass'])) {
            return 'bypass_cookie';
        }
        if (isset($_COOKIE['woocommerce_cart_hash']) || isset($_COOKIE['woocommerce_items_in_cart'])) {
            return 'woocommerce_cookie';
        }

        return 'none';
    }

    // HTML Minification
    public function start_html_buffer() {
        ob_start([$this, 'minify_html']);
    }

    public function minify_html($html) {
        if (empty($html)) {
            return $html;
        }

        // Don't minify feeds, sitemaps, or admin
        if (is_feed() || is_admin()) {
            return $html;
        }

        // Preserve scripts and styles
        $preserved = [];
        $html = preg_replace_callback('/<(script|style|pre|textarea)[^>]*>.*?<\/\1>/is', function($match) use (&$preserved) {
            $key = '<!--PRESERVE:' . count($preserved) . '-->';
            $preserved[$key] = $match[0];
            return $key;
        }, $html);

        // Remove HTML comments (except IE conditionals and PRESERVE markers)
        $html = preg_replace('/<!--(?!\[if|PRESERVE:).*?-->/s', '', $html);

        // Remove whitespace between tags
        $html = preg_replace('/>\s+</', '><', $html);

        // Remove extra whitespace
        $html = preg_replace('/\s{2,}/', ' ', $html);

        // Remove whitespace around block elements
        $html = preg_replace('/\s*(<\/?(?:html|head|body|div|section|article|header|footer|nav|aside|main|p|h[1-6]|ul|ol|li|table|tr|td|th|form|fieldset|dl|dt|dd|blockquote|hr|br)[^>]*>)\s*/i', '$1', $html);

        // Restore preserved content
        $html = str_replace(array_keys($preserved), array_values($preserved), $html);

        return trim($html);
    }

    // Lazy Loading
    public function add_lazy_loading($content) {
        if (empty($content)) {
            return $content;
        }

        // Add loading="lazy" to images that don't have it
        $content = preg_replace_callback('/<img([^>]+)>/i', function($match) {
            $img = $match[0];

            // Skip if already has loading attribute
            if (strpos($img, 'loading=') !== false) {
                return $img;
            }

            // Skip base64 images and SVGs
            if (strpos($img, 'data:image') !== false || strpos($img, '.svg') !== false) {
                return $img;
            }

            // Add loading="lazy"
            return str_replace('<img', '<img loading="lazy"', $img);
        }, $content);

        return $content;
    }

    public function add_lazy_loading_iframes($content) {
        if (empty($content)) {
            return $content;
        }

        // Add loading="lazy" to iframes
        $content = preg_replace_callback('/<iframe([^>]+)>/i', function($match) {
            $iframe = $match[0];

            if (strpos($iframe, 'loading=') !== false) {
                return $iframe;
            }

            return str_replace('<iframe', '<iframe loading="lazy"', $iframe);
        }, $content);

        return $content;
    }

    // Remove Query Strings
    public function remove_query_strings($src) {
        if (strpos($src, '?ver=') !== false) {
            $src = remove_query_arg('ver', $src);
        }
        return $src;
    }

    // Disable Emojis
    public function disable_emojis() {
        remove_action('wp_head', 'print_emoji_detection_script', 7);
        remove_action('admin_print_scripts', 'print_emoji_detection_script');
        remove_action('wp_print_styles', 'print_emoji_styles');
        remove_action('admin_print_styles', 'print_emoji_styles');
        remove_filter('the_content_feed', 'wp_staticize_emoji');
        remove_filter('comment_text_rss', 'wp_staticize_emoji');
        remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
        add_filter('tiny_mce_plugins', function($plugins) {
            return is_array($plugins) ? array_diff($plugins, ['wpemoji']) : [];
        });
        add_filter('wp_resource_hints', function($urls, $relation_type) {
            if ('dns-prefetch' === $relation_type) {
                $urls = array_filter($urls, function($url) {
                    return strpos($url, 'https://s.w.org/images/core/emoji/') === false;
                });
            }
            return $urls;
        }, 10, 2);
    }

    // Disable Embeds
    public function disable_embeds() {
        remove_action('rest_api_init', 'wp_oembed_register_route');
        remove_filter('oembed_dataparse', 'wp_filter_oembed_result', 10);
        remove_action('wp_head', 'wp_oembed_add_discovery_links');
        remove_action('wp_head', 'wp_oembed_add_host_js');
        add_filter('embed_oembed_discover', '__return_false');
        add_filter('tiny_mce_plugins', function($plugins) {
            return array_diff($plugins, ['wpembed']);
        });
        add_filter('rewrite_rules_array', function($rules) {
            foreach ($rules as $rule => $rewrite) {
                if (strpos($rewrite, 'embed=true') !== false) {
                    unset($rules[$rule]);
                }
            }
            return $rules;
        });
    }

    // =========================================================================
    // LCP OPTIMIZATION
    // =========================================================================

    private $lcp_image_url = null;
    private $lcp_image_srcset = null;
    private $lcp_image_sizes = null;
    private $lcp_processed = false;

    /**
     * Detect and optimize LCP image
     * Adds fetchpriority="high" and loading="eager" to the first large image
     * Also excludes it from lazy loading
     */
    public function optimize_lcp_image($content) {
        if (empty($content) || $this->lcp_processed) {
            return $content;
        }

        // Find all images in content
        preg_match_all('/<img[^>]+>/i', $content, $matches);

        if (empty($matches[0])) {
            return $content;
        }

        $first_image = true;
        foreach ($matches[0] as $img) {
            // Skip small images (icons, avatars, etc.)
            if ($this->is_small_image($img)) {
                continue;
            }

            // Skip images that already have fetchpriority
            if (strpos($img, 'fetchpriority') !== false) {
                continue;
            }

            // Skip lazy-loaded images from other plugins
            if (strpos($img, 'data-src') !== false && strpos($img, ' src=') === false) {
                continue;
            }

            if ($first_image) {
                // This is our LCP candidate
                $optimized_img = $img;

                // Add fetchpriority="high"
                if (strpos($optimized_img, 'fetchpriority') === false) {
                    $optimized_img = str_replace('<img', '<img fetchpriority="high"', $optimized_img);
                }

                // Change loading="lazy" to loading="eager" or add it
                if (strpos($optimized_img, 'loading="lazy"') !== false) {
                    $optimized_img = str_replace('loading="lazy"', 'loading="eager"', $optimized_img);
                } elseif (strpos($optimized_img, 'loading=') === false) {
                    $optimized_img = str_replace('<img', '<img loading="eager"', $optimized_img);
                }

                // Extract URL for preload
                if (preg_match('/src=["\']([^"\']+)["\']/i', $optimized_img, $src_match)) {
                    $this->lcp_image_url = $src_match[1];
                }

                // Extract srcset for preload
                if (preg_match('/srcset=["\']([^"\']+)["\']/i', $optimized_img, $srcset_match)) {
                    $this->lcp_image_srcset = $srcset_match[1];
                }

                // Extract sizes for preload
                if (preg_match('/sizes=["\']([^"\']+)["\']/i', $optimized_img, $sizes_match)) {
                    $this->lcp_image_sizes = $sizes_match[1];
                }

                $content = str_replace($img, $optimized_img, $content);
                $this->lcp_processed = true;
                $first_image = false;
            }
        }

        return $content;
    }

    /**
     * Check if image is likely small (icon, avatar, etc.)
     */
    private function is_small_image($img) {
        // Check for explicit small dimensions
        if (preg_match('/width=["\']?(\d+)/i', $img, $w_match)) {
            if ((int)$w_match[1] < 150) {
                return true;
            }
        }

        if (preg_match('/height=["\']?(\d+)/i', $img, $h_match)) {
            if ((int)$h_match[1] < 150) {
                return true;
            }
        }

        // Check for common small image classes
        $small_classes = ['avatar', 'icon', 'logo', 'emoji', 'thumbnail', 'wp-smiley'];
        foreach ($small_classes as $class) {
            if (stripos($img, $class) !== false) {
                return true;
            }
        }

        // Check for small image sizes in filename
        if (preg_match('/-(\d+)x(\d+)\./i', $img, $size_match)) {
            if ((int)$size_match[1] < 150 || (int)$size_match[2] < 150) {
                return true;
            }
        }

        return false;
    }

    /**
     * Output LCP image preload link in head
     */
    public function output_lcp_preload() {
        // If we haven't processed content yet, try to get featured image
        if (!$this->lcp_image_url && is_singular()) {
            $post_id = get_the_ID();
            if ($post_id && has_post_thumbnail($post_id)) {
                $thumbnail_id = get_post_thumbnail_id($post_id);
                $this->lcp_image_url = wp_get_attachment_image_url($thumbnail_id, 'large');

                // Get srcset for responsive preload
                $this->lcp_image_srcset = wp_get_attachment_image_srcset($thumbnail_id, 'large');
                $this->lcp_image_sizes = wp_get_attachment_image_sizes($thumbnail_id, 'large');
            }
        }

        if (!$this->lcp_image_url) {
            return;
        }

        // Build preload link
        $preload = '<link rel="preload" as="image" href="' . esc_url($this->lcp_image_url) . '"';

        if ($this->lcp_image_srcset) {
            $preload .= ' imagesrcset="' . esc_attr($this->lcp_image_srcset) . '"';
        }

        if ($this->lcp_image_sizes) {
            $preload .= ' imagesizes="' . esc_attr($this->lcp_image_sizes) . '"';
        }

        $preload .= ' fetchpriority="high">';

        echo $preload . "\n";
    }

    // =========================================================================
    // PRECONNECT HINTS
    // =========================================================================

    /**
     * Output preconnect hints for external domains
     */
    public function output_preconnect_hints() {
        $domains = $this->get_preconnect_domains();

        foreach ($domains as $domain) {
            echo '<link rel="preconnect" href="' . esc_url($domain) . '" crossorigin>' . "\n";
        }
    }

    /**
     * Get list of domains that should have preconnect hints
     */
    private function get_preconnect_domains() {
        $domains = [];
        $site_host = parse_url(home_url(), PHP_URL_HOST);

        // Common CDN and font domains
        $common_domains = [
            'fonts.gstatic.com',
            'cdnjs.cloudflare.com',
            'cdn.jsdelivr.net',
            'unpkg.com',
            'ajax.googleapis.com',
            'www.googletagmanager.com',
            'www.google-analytics.com',
            'connect.facebook.net',
            'platform.twitter.com',
        ];

        // Check if local Google Fonts is disabled (then we need preconnect for Google)
        if (!$this->settings['local_google_fonts']) {
            $domains[] = 'https://fonts.googleapis.com';
            $domains[] = 'https://fonts.gstatic.com';
        }

        // Check for common CDN usage in theme
        $template_uri = get_template_directory_uri();
        $template_host = parse_url($template_uri, PHP_URL_HOST);
        if ($template_host && $template_host !== $site_host) {
            $domains[] = 'https://' . $template_host;
        }

        // Check WooCommerce
        if (class_exists('WooCommerce')) {
            // WooCommerce uses some external resources
            // Usually handled locally, but check for PayPal, Stripe, etc.
        }

        // Remove duplicates
        $domains = array_unique($domains);

        // Limit to 4 most important (too many preconnects hurt performance)
        return array_slice($domains, 0, 4);
    }

    // =========================================================================
    // FONT PRELOAD
    // =========================================================================

    /**
     * Preload critical fonts
     */
    public function output_font_preload() {
        // If using local Google Fonts, preload the first cached font file
        if ($this->settings['local_google_fonts']) {
            $cache_dir = WP_CONTENT_DIR . '/cache/jabali/fonts';
            $cache_url = content_url('/cache/jabali/fonts');

            if (is_dir($cache_dir)) {
                $fonts = glob($cache_dir . '/*.woff2');
                if (!empty($fonts)) {
                    // Preload first 2 font files (usually regular and bold)
                    $count = 0;
                    foreach ($fonts as $font) {
                        if ($count >= 2) break;
                        $font_url = $cache_url . '/' . basename($font);
                        echo '<link rel="preload" as="font" type="font/woff2" href="' . esc_url($font_url) . '" crossorigin>' . "\n";
                        $count++;
                    }
                }
            }
        }
    }

    // =========================================================================
    // IMPROVED DEFER JS WITH EXCLUSIONS
    // =========================================================================

    /**
     * Default list of script handles that should NOT be deferred
     */
    private function get_defer_js_exclusions() {
        return [
            // Core jQuery - many inline scripts depend on it
            'jquery-core',
            'jquery-migrate',
            'jquery',

            // WordPress core
            'wp-polyfill',
            'wp-hooks',

            // WooCommerce critical scripts
            'wc-cart-fragments',
            'wc-checkout',
            'wc-add-to-cart',
            'wc-single-product',
            'woocommerce',

            // Elementor critical
            'elementor-frontend',
            'elementor-pro-frontend',

            // Spectra/UAG critical
            'uagb-block-positioning-js',
            'uagb-js',

            // Astra theme
            'astra-theme-js',
            'astra-addon-js',

            // Common sliders that need to run early
            'swiper',
            'slick',
            'owl-carousel',

            // Critical UI libraries
            'lodash',
            'underscore',
            'backbone',
        ];
    }

    /**
     * Defer non-critical JavaScript with proper exclusions
     */
    public function defer_js($tag, $handle, $src) {
        // Skip if no src (inline script)
        if (empty($src)) {
            return $tag;
        }

        // Get exclusion list
        $exclusions = $this->get_defer_js_exclusions();

        // Allow filtering exclusions
        $exclusions = apply_filters('jabali_cache_defer_js_exclusions', $exclusions);

        // Don't defer excluded scripts
        if (in_array($handle, $exclusions)) {
            return $tag;
        }

        // Don't defer if already has defer or async
        if (strpos($tag, ' defer') !== false || strpos($tag, ' async') !== false) {
            return $tag;
        }

        // Don't defer scripts with dependencies that aren't deferred
        // (this is a simplified check)
        if (strpos($handle, 'jquery') !== false && strpos($handle, 'jquery-core') === false) {
            // jQuery-dependent scripts should check if jQuery is available
            // For safety, we let them through but they'll have defer
        }

        // Add defer attribute
        return str_replace(' src=', ' defer src=', $tag);
    }

    // =========================================================================
    // DELAY THIRD-PARTY SCRIPTS
    // =========================================================================

    /**
     * Third-party script domains that should be delayed
     */
    private function get_third_party_domains() {
        return [
            'google-analytics.com',
            'googletagmanager.com',
            'facebook.net',
            'connect.facebook.com',
            'platform.twitter.com',
            'snap.licdn.com',
            'static.hotjar.com',
            'script.hotjar.com',
            'widget.intercom.io',
            'js.intercomcdn.com',
            'cdn.segment.com',
            'js.hs-scripts.com',
            'js.hs-analytics.net',
            'cdn.heapanalytics.com',
            'cdn.mxpnl.com',
            'rum-static.pingdom.net',
            'newrelic.com',
            'nr-data.net',
            'fullstory.com',
            'clarity.ms',
            'browser.sentry-cdn.com',
            'cdn.onesignal.com',
            'cdn.pushwoosh.com',
            'cdn.tawk.to',
            'embed.tawk.to',
            'static.zdassets.com',
            'widget.drift.com',
            'js.driftt.com',
            'beacon-v2.helpscout.net',
            'app.chatwoot.com',
        ];
    }

    /**
     * Delay third-party scripts until user interaction
     */
    public function delay_third_party_scripts($tag, $handle, $src) {
        if (empty($src)) {
            return $tag;
        }

        $third_party_domains = $this->get_third_party_domains();
        $is_third_party = false;

        foreach ($third_party_domains as $domain) {
            if (strpos($src, $domain) !== false) {
                $is_third_party = true;
                break;
            }
        }

        if (!$is_third_party) {
            return $tag;
        }

        // Convert to delayed loading
        // Replace src with data-src and add class for delayed loading
        $tag = str_replace(' src=', ' data-jabali-delay-src=', $tag);
        $tag = str_replace('<script', '<script type="text/plain" data-jabali-delayed', $tag);

        // Add the delay loader script if not already added
        static $loader_added = false;
        if (!$loader_added) {
            add_action('wp_footer', [$this, 'output_delay_loader_script'], 999);
            $loader_added = true;
        }

        return $tag;
    }

    /**
     * Output script that loads delayed scripts on user interaction
     */
    public function output_delay_loader_script() {
        ?>
        <script>
        (function() {
            var loaded = false;
            function loadDelayedScripts() {
                if (loaded) return;
                loaded = true;
                document.querySelectorAll('script[data-jabali-delayed]').forEach(function(script) {
                    var newScript = document.createElement('script');
                    if (script.getAttribute('data-jabali-delay-src')) {
                        newScript.src = script.getAttribute('data-jabali-delay-src');
                    }
                    newScript.async = true;
                    Array.from(script.attributes).forEach(function(attr) {
                        if (attr.name !== 'type' && attr.name !== 'data-jabali-delayed' && attr.name !== 'data-jabali-delay-src') {
                            newScript.setAttribute(attr.name, attr.value);
                        }
                    });
                    if (script.innerHTML) {
                        newScript.innerHTML = script.innerHTML;
                    }
                    script.parentNode.replaceChild(newScript, script);
                });
            }
            ['scroll', 'mousemove', 'touchstart', 'keydown', 'click'].forEach(function(event) {
                window.addEventListener(event, loadDelayedScripts, {once: true, passive: true});
            });
            setTimeout(loadDelayedScripts, 5000);
        })();
        </script>
        <?php
    }

    /**
     * Localize Google Fonts - intercept and serve locally
     */
    public function localize_google_fonts_css($src, $handle) {
        // Only process Google Fonts CSS URLs
        if (strpos($src, 'fonts.googleapis.com/css') === false) {
            return $src;
        }

        // Generate a cache key based on the URL
        $cache_key = 'jabali_fonts_' . md5($src);
        $cache_dir = WP_CONTENT_DIR . '/cache/jabali/fonts';
        $cache_url = content_url('/cache/jabali/fonts');

        // Check if we have a cached version
        $cached_file = $cache_dir . '/' . $cache_key . '.css';
        if (file_exists($cached_file) && (time() - filemtime($cached_file)) < WEEK_IN_SECONDS) {
            return $cache_url . '/' . $cache_key . '.css';
        }

        // Create cache directory if it doesn't exist
        if (!is_dir($cache_dir)) {
            wp_mkdir_p($cache_dir);
        }

        // Fetch Google Fonts CSS with a modern user agent to get woff2
        $response = wp_remote_get($src, [
            'timeout' => 15,
            'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        ]);

        if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
            return $src; // Fall back to original URL
        }

        $css = wp_remote_retrieve_body($response);

        // Parse and download font files
        $css = $this->download_and_replace_font_urls($css, $cache_dir, $cache_url);

        // Save the modified CSS
        file_put_contents($cached_file, $css);

        return $cache_url . '/' . $cache_key . '.css';
    }

    /**
     * Download font files and replace URLs in CSS
     */
    private function download_and_replace_font_urls($css, $cache_dir, $cache_url) {
        // Find all font URLs in the CSS
        preg_match_all('/url\((https:\/\/fonts\.gstatic\.com\/[^)]+)\)/i', $css, $matches);

        if (empty($matches[1])) {
            return $css;
        }

        $font_urls = array_unique($matches[1]);

        foreach ($font_urls as $font_url) {
            // Generate local filename
            $font_hash = md5($font_url);
            $extension = pathinfo(parse_url($font_url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'woff2';
            $local_filename = $font_hash . '.' . $extension;
            $local_path = $cache_dir . '/' . $local_filename;
            $local_url = $cache_url . '/' . $local_filename;

            // Download font if not cached
            if (!file_exists($local_path)) {
                $font_response = wp_remote_get($font_url, [
                    'timeout' => 30,
                ]);

                if (!is_wp_error($font_response) && wp_remote_retrieve_response_code($font_response) === 200) {
                    file_put_contents($local_path, wp_remote_retrieve_body($font_response));
                } else {
                    continue; // Skip this font, keep original URL
                }
            }

            // Replace URL in CSS
            $css = str_replace($font_url, $local_url, $css);
        }

        return $css;
    }

    /**
     * Remove Google Fonts preconnect hints
     */
    public function remove_google_fonts_preconnect($hints, $relation_type) {
        if ($relation_type === 'preconnect' || $relation_type === 'dns-prefetch') {
            $hints = array_filter($hints, function($hint) {
                $url = is_array($hint) ? ($hint['href'] ?? '') : $hint;
                return strpos($url, 'fonts.googleapis.com') === false
                    && strpos($url, 'fonts.gstatic.com') === false;
            });
        }
        return $hints;
    }

    /**
     * Get local Google Fonts cache stats
     */
    public function get_local_fonts_stats() {
        $cache_dir = WP_CONTENT_DIR . '/cache/jabali/fonts';
        $stats = [
            'enabled' => $this->settings['local_google_fonts'],
            'cached_files' => 0,
            'cache_size' => 0,
        ];

        if (is_dir($cache_dir)) {
            $files = glob($cache_dir . '/*');
            $stats['cached_files'] = count($files);
            foreach ($files as $file) {
                $stats['cache_size'] += filesize($file);
            }
        }

        return $stats;
    }

    // Expired Cache - Send no-cache headers
    public function send_expired_cache_headers() {
        // Skip if headers already sent
        if (headers_sent()) {
            return;
        }

        // Skip admin pages
        if (is_admin()) {
            return;
        }

        // Set headers to prevent caching
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0', true);
        header('Pragma: no-cache', true);
        header('Expires: Thu, 01 Jan 1970 00:00:00 GMT', true);
        header('X-Jabali-Cache: no-cache', true);
    }

    // Disable Page Cache - Send headers to bypass nginx fastcgi_cache
    public function disable_page_cache_headers() {
        // Skip if headers already sent
        if (headers_sent()) {
            return;
        }

        // Skip admin pages
        if (is_admin()) {
            return;
        }

        // Set headers to tell nginx to not cache this response
        // and to bypass the cache when serving
        header('Cache-Control: no-store, no-cache, must-revalidate, private, max-age=0', true);
        header('Pragma: no-cache', true);
        header('X-Jabali-Skip-Cache: 1', true);
        header('X-Accel-Expires: 0', true); // nginx-specific: don't cache
    }

    // Admin Menu
    public function add_admin_menu() {
        add_options_page(
            __('Jabali Cache', 'jabali-cache'),
            __('Jabali Cache', 'jabali-cache'),
            'manage_options',
            'jabali-cache',
            [$this, 'render_admin_page']
        );
    }

    public function register_settings() {
        register_setting(self::OPTION_KEY, self::OPTION_KEY, [
            'sanitize_callback' => [$this, 'sanitize_settings']
        ]);
    }

    public function sanitize_settings($input) {
        $sanitized = [];
        $checkboxes = [
            'page_cache', 'object_cache', 'html_minify', 'minify_css', 'minify_js',
            'lazy_load', 'lazy_load_iframes', 'browser_cache', 'expired_cache',
            'remove_query_strings', 'disable_emojis', 'disable_embeds', 'defer_js', 'cache_debug',
            'local_google_fonts',
            // LCP Optimization settings
            'lcp_preload', 'preconnect_hints', 'preload_fonts', 'delay_third_party'
        ];

        foreach ($checkboxes as $key) {
            $sanitized[$key] = !empty($input[$key]);
        }

        // Sync page cache with Jabali Panel (nginx FastCGI cache)
        $old_settings = $this->get_settings();
        if ($sanitized['page_cache'] !== $old_settings['page_cache']) {
            $this->sync_page_cache_with_jabali($sanitized['page_cache']);
        }

        // Clear object cache for this option to ensure fresh read on next load
        wp_cache_delete(self::OPTION_KEY, 'options');
        wp_cache_delete('alloptions', 'options');

        return $sanitized;
    }

    /**
     * Sync page cache setting with Jabali Panel
     * This enables/disables nginx FastCGI cache for this domain
     */
    private function sync_page_cache_with_jabali($enabled) {
        // Get domain from site URL
        $site_url = get_site_url();
        $parsed = parse_url($site_url);
        $domain = $parsed['host'] ?? '';

        if (empty($domain)) {
            return false;
        }

        // Generate secret from AUTH_KEY
        $secret = defined('AUTH_KEY') ? substr(md5(AUTH_KEY), 0, 32) : '';
        if (empty($secret)) {
            return false;
        }

        // Call Jabali Panel internal API (HTTPS with SSL verify disabled for localhost)
        $response = wp_remote_post('https://127.0.0.1/api/internal/page-cache', [
            'timeout' => 10,
            'sslverify' => false,
            'headers' => [
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
            ],
            'body' => json_encode([
                'domain' => $domain,
                'enabled' => $enabled,
                'secret' => $secret,
            ]),
        ]);

        if (is_wp_error($response)) {
            error_log('Jabali Cache: Failed to sync page cache - ' . $response->get_error_message());
            return false;
        }

        $code = wp_remote_retrieve_response_code($response);
        if ($code !== 200) {
            $body = wp_remote_retrieve_body($response);
            error_log('Jabali Cache: Failed to sync page cache - HTTP ' . $code . ' - ' . $body);
            return false;
        }

        return true;
    }

    /**
     * Disable page cache when plugin is deactivated
     */
    public function disable_page_cache_on_deactivation() {
        return $this->sync_page_cache_with_jabali(false);
    }

    /**
     * Enable page cache when plugin is activated (if enabled in settings)
     */
    public function enable_page_cache_on_activation() {
        return $this->sync_page_cache_with_jabali(true);
    }

    public function admin_styles($hook) {
        if ($hook !== 'settings_page_jabali-cache') {
            return;
        }
        ?>
        <style>
            .jabali-header {
                display: flex;
                align-items: center;
                gap: 16px;
                margin: 20px 0;
                padding-bottom: 20px;
                border-bottom: 1px solid #c3c4c7;
            }
            .jabali-logo {
                width: 48px;
                height: 48px;
                flex-shrink: 0;
            }
            .jabali-header-text h1 {
                margin: 0 0 4px;
                font-size: 23px;
                font-weight: 400;
                line-height: 1.3;
            }
            .jabali-header-text p {
                margin: 0;
                color: #646970;
            }
            .jabali-grid {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
                gap: 20px;
                margin-top: 20px;
            }
            @media (max-width: 782px) {
                .jabali-grid {
                    grid-template-columns: 1fr;
                }
            }
            .jabali-card {
                background: #fff;
                border: 1px solid #c3c4c7;
                box-shadow: 0 1px 1px rgba(0,0,0,.04);
            }
            .jabali-card-header {
                display: flex;
                align-items: center;
                gap: 10px;
                padding: 12px 16px;
                background: #f6f7f7;
                border-bottom: 1px solid #c3c4c7;
            }
            .jabali-card-header .dashicons {
                color: #2271b1;
                font-size: 20px;
                width: 20px;
                height: 20px;
            }
            .jabali-card-header h2 {
                margin: 0;
                font-size: 14px;
                font-weight: 600;
            }
            .jabali-card-body {
                padding: 16px;
            }
            .jabali-setting-row {
                display: flex;
                align-items: flex-start;
                justify-content: space-between;
                padding: 12px 0;
                border-bottom: 1px solid #f0f0f1;
            }
            .jabali-setting-row:last-child {
                border-bottom: none;
                padding-bottom: 0;
            }
            .jabali-setting-row:first-child {
                padding-top: 0;
            }
            .jabali-setting-info {
                flex: 1;
                padding-right: 16px;
            }
            .jabali-setting-label {
                display: block;
                font-weight: 600;
                margin-bottom: 4px;
                color: #1d2327;
            }
            .jabali-setting-desc {
                font-size: 13px;
                color: #646970;
                line-height: 1.5;
            }
            .jabali-toggle {
                position: relative;
                width: 36px;
                height: 18px;
                flex-shrink: 0;
                margin-top: 2px;
            }
            .jabali-toggle input {
                opacity: 0;
                width: 0;
                height: 0;
            }
            .jabali-toggle-slider {
                position: absolute;
                cursor: pointer;
                inset: 0;
                background: #8c8f94;
                border-radius: 18px;
                transition: 0.2s;
            }
            .jabali-toggle-slider:before {
                content: '';
                position: absolute;
                width: 14px;
                height: 14px;
                left: 2px;
                bottom: 2px;
                background: #fff;
                border-radius: 50%;
                transition: 0.2s;
            }
            .jabali-toggle input:checked + .jabali-toggle-slider {
                background: #2271b1;
            }
            .jabali-toggle input:checked + .jabali-toggle-slider:before {
                transform: translateX(18px);
            }
            .jabali-toggle input:focus + .jabali-toggle-slider {
                box-shadow: 0 0 0 2px #fff, 0 0 0 4px #2271b1;
            }
            .jabali-stats-grid {
                display: grid;
                grid-template-columns: repeat(3, 1fr);
                gap: 12px;
                margin-bottom: 16px;
            }
            .jabali-stat-box {
                text-align: center;
                padding: 12px 8px;
                background: #f6f7f7;
                border: 1px solid #c3c4c7;
            }
            .jabali-stat-value {
                font-size: 20px;
                font-weight: 600;
                color: #1d2327;
            }
            .jabali-stat-value.success { color: #00a32a; }
            .jabali-stat-value.warning { color: #dba617; }
            .jabali-stat-value.error { color: #d63638; }
            .jabali-stat-label {
                font-size: 11px;
                color: #646970;
                text-transform: uppercase;
                margin-top: 4px;
            }
            .jabali-actions {
                display: flex;
                gap: 8px;
                margin-top: 16px;
                padding-top: 16px;
                border-top: 1px solid #f0f0f1;
            }
            .jabali-info-notice {
                background: #f0f6fc;
                border-left: 4px solid #72aee6;
                padding: 12px;
                margin-top: 12px;
            }
            .jabali-info-notice p {
                margin: 0;
                font-size: 13px;
            }
            .jabali-warning-notice {
                background: #fcf9e8;
                border-left: 4px solid #dba617;
                padding: 12px;
                margin-bottom: 12px;
            }
            .jabali-warning-notice p {
                margin: 0;
                font-size: 13px;
            }
            .jabali-submit-row {
                display: flex;
                align-items: center;
                gap: 12px;
                margin-top: 20px;
                padding-top: 20px;
                border-top: 1px solid #c3c4c7;
            }
            .jabali-footer {
                margin-top: 30px;
                padding: 20px;
                background: #fff;
                border: 1px solid #c3c4c7;
            }
            .jabali-footer h3 {
                margin: 0 0 8px;
                font-size: 14px;
            }
            .jabali-footer p {
                margin: 0 0 8px;
                color: #646970;
            }
            .jabali-footer p:last-child {
                margin-bottom: 0;
            }
        </style>
        <?php
    }

    public function add_admin_bar_menu($wp_admin_bar) {
        if (!current_user_can('manage_options')) {
            return;
        }

        $connected = $this->is_redis_connected();

        $wp_admin_bar->add_node([
            'id' => 'jabali-cache',
            'title' => sprintf(
                '<span style="color: %s;">●</span> %s',
                $connected ? '#46b450' : '#dc3232',
                __('Jabali Cache', 'jabali-cache')
            ),
            'href' => admin_url('options-general.php?page=jabali-cache'),
        ]);

        $wp_admin_bar->add_node([
            'parent' => 'jabali-cache',
            'id' => 'jabali-cache-clear-all',
            'title' => __('Clear All Caches', 'jabali-cache'),
            'href' => wp_nonce_url(
                admin_url('options-general.php?page=jabali-cache&action=clear_all'),
                'jabali_cache_clear_all'
            ),
        ]);

        $wp_admin_bar->add_node([
            'parent' => 'jabali-cache',
            'id' => 'jabali-cache-flush',
            'title' => __('Flush Object Cache', 'jabali-cache'),
            'href' => wp_nonce_url(
                admin_url('options-general.php?page=jabali-cache&action=flush'),
                'jabali_cache_flush'
            ),
        ]);

        $wp_admin_bar->add_node([
            'parent' => 'jabali-cache',
            'id' => 'jabali-cache-purge-page',
            'title' => __('Purge Page Cache', 'jabali-cache'),
            'href' => wp_nonce_url(
                admin_url('options-general.php?page=jabali-cache&action=purge_page'),
                'jabali_cache_purge_page'
            ),
        ]);
    }

    public function add_action_links($links) {
        $settings_link = sprintf(
            '<a href="%s">%s</a>',
            admin_url('options-general.php?page=jabali-cache'),
            __('Settings', 'jabali-cache')
        );
        array_unshift($links, $settings_link);
        return $links;
    }

    public function handle_actions() {
        if (!isset($_GET['page']) || $_GET['page'] !== 'jabali-cache' || !isset($_GET['action'])) {
            return;
        }

        $action = sanitize_text_field($_GET['action']);

        switch ($action) {
            case 'flush':
                if (!wp_verify_nonce($_GET['_wpnonce'] ?? '', 'jabali_cache_flush')) {
                    wp_die(__('Security check failed', 'jabali-cache'));
                }
                wp_cache_flush();
                wp_redirect(admin_url('options-general.php?page=jabali-cache&flushed=1'));
                exit;

            case 'enable':
                if (!wp_verify_nonce($_GET['_wpnonce'] ?? '', 'jabali_cache_enable')) {
                    wp_die(__('Security check failed', 'jabali-cache'));
                }
                $this->enable_drop_in();
                wp_redirect(admin_url('options-general.php?page=jabali-cache&enabled=1'));
                exit;

            case 'disable':
                if (!wp_verify_nonce($_GET['_wpnonce'] ?? '', 'jabali_cache_disable')) {
                    wp_die(__('Security check failed', 'jabali-cache'));
                }
                $this->disable_drop_in();
                wp_redirect(admin_url('options-general.php?page=jabali-cache&disabled=1'));
                exit;

            case 'clear_all':
                if (!wp_verify_nonce($_GET['_wpnonce'] ?? '', 'jabali_cache_clear_all')) {
                    wp_die(__('Security check failed', 'jabali-cache'));
                }
                $this->clear_all_caches();
                wp_redirect(admin_url('options-general.php?page=jabali-cache&cleared=1'));
                exit;

            case 'purge_page':
                if (!wp_verify_nonce($_GET['_wpnonce'] ?? '', 'jabali_cache_purge_page')) {
                    wp_die(__('Security check failed', 'jabali-cache'));
                }
                $this->purge_all_cache();
                wp_redirect(admin_url('options-general.php?page=jabali-cache&purged=1'));
                exit;
        }
    }

    /**
     * Clear all caches - combined CSS/JS files and object cache
     */
    public function clear_all_caches() {
        // Clear combined CSS/JS cache files
        $cache_dir = WP_CONTENT_DIR . '/cache/jabali';
        if (is_dir($cache_dir)) {
            $files = glob($cache_dir . '/*');
            foreach ($files as $file) {
                if (is_file($file)) {
                    @unlink($file);
                }
            }
        }

        // Flush object cache (Redis)
        if (function_exists('wp_cache_flush')) {
            wp_cache_flush();
        }

        // Purge page cache
        $this->purge_all_cache();
    }

    public function is_drop_in_installed() {
        $drop_in = WP_CONTENT_DIR . '/object-cache.php';
        if (!file_exists($drop_in)) {
            return false;
        }
        $content = file_get_contents($drop_in);
        return strpos($content, 'Jabali_Redis_Object_Cache') !== false;
    }

    public function enable_drop_in() {
        $source = plugin_dir_path(__FILE__) . 'object-cache.php';
        $dest = WP_CONTENT_DIR . '/object-cache.php';
        if (file_exists($source)) {
            @copy($source, $dest);
        }
    }

    public function disable_drop_in() {
        $drop_in = WP_CONTENT_DIR . '/object-cache.php';
        if (file_exists($drop_in)) {
            @unlink($drop_in);
        }
    }

    public function is_redis_connected() {
        if (!class_exists('Redis')) {
            return false;
        }
        try {
            $redis = new Redis();
            $host = defined('JABALI_CACHE_HOST') ? JABALI_CACHE_HOST : '127.0.0.1';
            $port = defined('JABALI_CACHE_PORT') ? JABALI_CACHE_PORT : 6379;
            $db = defined('JABALI_CACHE_DATABASE') ? JABALI_CACHE_DATABASE : 0;

            if (!$redis->connect($host, $port, 1)) {
                return false;
            }

            // Authenticate if credentials are defined
            if (defined('JABALI_CACHE_REDIS_USER') && defined('JABALI_CACHE_REDIS_PASS')) {
                $redis->auth(['user' => JABALI_CACHE_REDIS_USER, 'pass' => JABALI_CACHE_REDIS_PASS]);
            } elseif (defined('JABALI_CACHE_REDIS_PASS') && JABALI_CACHE_REDIS_PASS) {
                $redis->auth(JABALI_CACHE_REDIS_PASS);
            }

            // Select database
            $redis->select($db);

            return $redis->ping() ? true : false;
        } catch (Exception $e) {
            return false;
        }
    }

    public function get_cache_stats() {
        global $wp_object_cache;

        $stats = [
            'hits' => 0,
            'misses' => 0,
            'ratio' => 0,
            'connected' => false,
            'total_keys' => 0,
            'memory' => 'N/A',
        ];

        if (method_exists($wp_object_cache, 'stats')) {
            $cache_stats = $wp_object_cache->stats();
            if (is_array($cache_stats)) {
                $stats = array_merge($stats, $cache_stats);
            }
        } elseif (isset($wp_object_cache->cache_hits)) {
            $stats['hits'] = $wp_object_cache->cache_hits;
            $stats['misses'] = $wp_object_cache->cache_misses ?? 0;
        }

        // Calculate ratio
        $total = $stats['hits'] + $stats['misses'];
        if ($total > 0) {
            $stats['ratio'] = round(($stats['hits'] / $total) * 100, 1);
        }

        return $stats;
    }

    public function render_admin_page() {
        $stats = $this->get_cache_stats();
        $drop_in_installed = $this->is_drop_in_installed();
        $redis_available = class_exists('Redis');
        $redis_connected = $this->is_redis_connected();
        ?>
        <div class="wrap">
            <?php if (isset($_GET['flushed'])): ?>
            <div class="notice notice-success is-dismissible">
                <p><?php _e('Object cache flushed successfully.', 'jabali-cache'); ?></p>
            </div>
            <?php endif; ?>

            <?php if (isset($_GET['cleared'])): ?>
            <div class="notice notice-success is-dismissible">
                <p><?php _e('All caches cleared successfully.', 'jabali-cache'); ?></p>
            </div>
            <?php endif; ?>

            <?php if (isset($_GET['purged'])): ?>
            <div class="notice notice-success is-dismissible">
                <p><?php _e('Page cache purged successfully.', 'jabali-cache'); ?></p>
            </div>
            <?php endif; ?>

            <?php if (isset($_GET['enabled'])): ?>
            <div class="notice notice-success is-dismissible">
                <p><?php _e('Object cache enabled successfully.', 'jabali-cache'); ?></p>
            </div>
            <?php endif; ?>

            <?php if (isset($_GET['disabled'])): ?>
            <div class="notice notice-success is-dismissible">
                <p><?php _e('Object cache disabled successfully.', 'jabali-cache'); ?></p>
            </div>
            <?php endif; ?>

            <?php if (isset($_GET['settings-updated'])): ?>
            <div class="notice notice-success is-dismissible">
                <p><?php _e('Settings saved successfully.', 'jabali-cache'); ?></p>
            </div>
            <?php endif; ?>

            <!-- Header with Logo -->
            <div class="jabali-header">
                <svg class="jabali-logo" viewBox="0 0 147.26 96.573" xmlns="http://www.w3.org/2000/svg">
                    <g transform="translate(-34.391 -47.118)">
                        <g transform="translate(-3.541 -25.332)">
                            <path fill="#2271b1" d="m79.472 73.244c-4.0065 0.95163-8.277 4.0636-9.2604 8.2021h1.8521v0.52917c-5.293 0.24188-10.217 5.6941-15.081 7.7231-1.114 0.46467-4.676 1.2393-5.1043 2.4417-0.38218 1.073 1.0399 2.7743 1.5975 3.5935 2.4662 3.6227 5.8771 5.0144 10.121 3.9687-1.5506 5.3455-7.6205 6.9269-11.24 2.3802-3.2616-4.0969-3.312-10.11-3.312-15.08h0.26458v0.52917h0.26458l-1.0583-2.9104h-0.26458c-0.70254 1.8212-1.2726 3.6092-1.5118 5.5562-0.11276 0.91811 0.18619 2.2623-0.34767 3.0641-1.4776 2.2192-6.4692 0.93492-8.4593 0.37544 0.20517 2.3499 1.304 8.2501 3.0454 9.9049 1.8549 1.7628 6.4774 1.7367 8.8609 1.7367v0.26459l-3.175 0.52916v0.26459c7.2825 4.4949 15.112 11.721 18.785 19.579h0.26458c-0.01183-4.2856-2.0574-7.5834-4.2333-11.112 4.5342 3.0843 9.258 7.8497 14.552 9.525l-1.5875-5.2917h0.26458c0.84444 4.7343 6.8962 10.084 11.377 11.377-1.2956-5.6515-1.6033-9.8179 0.52917-15.346h0.26458c-2.5132 10.202 3.9699 16.869 9.2604 24.606l-14.023-5.5226-9.7896-7.1774c1.5844 2.7814 4.9469 6.0214 5.4293 9.2604 0.40039 2.6886-0.9934 6.31-2.0295 8.7312-2.8259 6.6039-7.6431 11.451-13.189 15.927-2.8919 2.334-6.6625 4.4647-8.9958 7.3563 4.0856 0 8.6528 1.3244 10.054-3.4396h0.26458v2.3812l6.6146-4.986 10.236-8.6639 1.5197-3.2003 5.9717-2.2681 4.4979-2.888 3.175-2.6291 5.5562 0.55836-3.9687-7.6729c3.7228 2.2978 7.9806 5.5165 10.332 9.2604 1.5432 2.4574 1.9452 5.5757 3.5984 7.9375 2.1589 3.0843 5.4308 5.7197 8.1059 8.3544 1.9816 1.9517 4.3458 5.5336 7.0692 6.4219 1.6243 0.52978 3.1232-1.294 2.7832-2.87-0.2334-1.0821-1.2485-1.8971-1.9905-2.6458l2.3812 0.52917c-0.0648-2.6792-1.8771-2.9045-3.7042-4.3366-2.004-1.5708-4.6598-4.1729-5.7406-6.5113-0.71228-1.5411-0.50959-3.8743-0.63288-5.5562-0.29051-3.9631-0.28284-8.2826-1.1249-12.171-0.40549-1.8724-2.2649-3.3993-3.2295-5.0271-1.422-2.3996-2.1467-5.1916-2.5013-7.9375h0.26458c0.93579 2.8711 2.3848 5.5274 4.2064 7.9375 1.0104 1.3367 2.6091 2.627 3.1628 4.2333 0.62267 1.8067 0.73913 4.1838 0.82253 6.0854 0.0342 0.77985-0.23556 2.0716 0.43464 2.6489 1.1663 1.0046 4.7066 0.78333 6.1904 0.79049 5.8026 0.028 12.063-0.25522 17.462-2.6456-0.77197-2.0367-2.2275-3.7778-3.0552-5.8208-1.5912-3.928-1.4637-7.2919-0.91359-11.377h0.26458c0 4.5242 1.0259 8.7475 3.2881 12.7 2.2975 4.0142 6.1699 8.2606 5.6616 13.229-0.88324 8.6337-11.013 11.804-12.918 19.844 3.1087 0 5.5125 0.6513 6.8792-2.6458h0.26458v1.8521c2.9712-1.5415 3.1185-4.5507 5.0836-6.8792 2.8528-3.3803 8.621-6.0668 10.516-10.054 0.93566-1.9692-1.193-4.2544-5e-3 -6.35 1.0544-1.8601 3.0177-3.2355 4.2421-5.0271 3.2956-4.822 5.503-10.318 6.0481-16.14 0.21876-2.3368-0.37598-5.0017-1.2819-7.1438-0.44877-1.0612-1.8038-2.5236-1.6796-3.7042 0.1146-1.0894 1.3436-2.0376 1.9205-2.9104 1.0226-1.5471 1.8056-3.4197 1.8682-5.2917 0.0962-2.8782-1.4065-5.0444-3.432-6.9241-0.85752-0.79578-2.9299-2.2711-2.5035-3.6541 0.34257-1.1112 1.5139-1.3081 2.5074-1.3268 1.6838-0.03161 3.4012 0.16952 5.0271-0.36094 2.3027-0.75128 3.8049-2.2333 6.35-2.2861-1.7653-2.0607-4.7845-2.9032-7.4083-2.9104l1.3229-1.0583v-0.26458c-1.7525 0-3.572-0.1527-5.2917 0.23498-1.0777 0.24295-2.2263 0.49727-3.175 1.0865-5.9935 3.7225-0.17836 9.6913 1.4638 14.024 1.0121 2.6706-0.24648 6.0015-3.0513 7.0055-1.3226 0.47346-2.5954-0.66607-3.7042-1.2419-2.3547-1.2228-4.8913-2.1202-7.4083-2.9406-8.2756-2.6974-17.5-4.146-26.194-4.146v-0.26458l4.4979-1.8521c-3.7368-2.2824-9.3016-1.8521-13.494-1.8521v-0.26458l7.4083-3.175v-0.26458l-14.552-0.79375v-0.26458l5.8208-2.3812v-0.26458c-4.5419-0.36146-9.4692-1.8779-14.023-0.79375l7.6729-4.4979c-3.1942-1.2051-9.5711-1.7051-12.666 0.08023-1.0502 0.60585-1.5876 1.9605-2.4392 2.8055-1.8354 1.8212-4.3154 2.6495-6.8553 2.6705v-0.26458c7.3819-1.0902 9.4631-9.4281 7.1438-15.61-3.6173 0.74663-7.4063 2.0646-10.315 4.4103-1.2534 1.0109-2.7138 4.3127-4.257 4.5994-1.0995 0.20428-1.4526-1.0575-1.6183-1.8662-0.45208-2.2056 0.32443-4.3161 1.109-6.3498m-11.112 15.875c-0.98324 2.0589-2.9464 2.3799-5.0271 2.3812 0.97375-2.0991 2.7849-3.4588 5.0271-2.3812m-6.8792 25.4-0.26458 0.26458 0.26458-0.26458m108.48 17.727c-1.2104 4.4255-4.1608 9.5105-7.9375 12.171v0.52916c3.1505 1.7947 7.6489 3.4777 10.315 5.8698 4.7761 4.2855 6.0439 12.285 5.5601 18.207 4.1709 0 7.4428-0.0408 5.8208-5.0271l1.3229 0.79375c0.87387-3.6809-2.2376-6.5639-3.5443-9.7896-1.5868-3.9171-1.5007-8.3848-2.9653-12.16-0.67252-1.7337-3.2676-2.9299-4.5271-4.2674-1.79-1.9009-2.4102-4.4741-4.0445-6.3263m13.758 31.485-0.26459 0.26459 0.26459-0.26459m-38.629 1.8521-0.26458 0.26458z"/>
                        </g>
                    </g>
                </svg>
                <div class="jabali-header-text">
                    <h1><?php _e('Jabali Cache', 'jabali-cache'); ?></h1>
                    <p><?php _e('High-performance caching and optimization for WordPress', 'jabali-cache'); ?></p>
                </div>
            </div>

            <form method="post" action="options.php">
                <?php settings_fields(self::OPTION_KEY); ?>

                <div class="jabali-grid">
                    <!-- Page Cache Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-database"></span>
                            <h2><?php _e('Page Cache', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Enable Page Cache', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Full page caching via nginx. Dramatically speeds up page load times by serving cached HTML directly from the server.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[page_cache]" value="1" <?php checked($this->settings['page_cache']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-info-notice">
                                <p><strong><?php _e('Note:', 'jabali-cache'); ?></strong> <?php _e('Cache is automatically bypassed for logged-in users, POST requests, and WooCommerce cart/checkout pages. Content changes trigger automatic cache purging.', 'jabali-cache'); ?></p>
                            </div>
                        </div>
                    </div>

                    <!-- Object Cache Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-performance"></span>
                            <h2><?php _e('Object Cache (Redis)', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-stats-grid">
                                <div class="jabali-stat-box">
                                    <div class="jabali-stat-value <?php echo $redis_connected ? 'success' : 'error'; ?>">
                                        <?php echo $redis_connected ? __('Connected', 'jabali-cache') : __('Offline', 'jabali-cache'); ?>
                                    </div>
                                    <div class="jabali-stat-label"><?php _e('Status', 'jabali-cache'); ?></div>
                                </div>
                                <div class="jabali-stat-box">
                                    <div class="jabali-stat-value <?php echo $stats['ratio'] >= 80 ? 'success' : ($stats['ratio'] >= 50 ? 'warning' : 'error'); ?>">
                                        <?php echo $stats['ratio']; ?>%
                                    </div>
                                    <div class="jabali-stat-label"><?php _e('Hit Ratio', 'jabali-cache'); ?></div>
                                </div>
                                <div class="jabali-stat-box">
                                    <div class="jabali-stat-value">
                                        <?php echo number_format($stats['hits']); ?>
                                    </div>
                                    <div class="jabali-stat-label"><?php _e('Hits', 'jabali-cache'); ?></div>
                                </div>
                                <div class="jabali-stat-box">
                                    <div class="jabali-stat-value">
                                        <?php echo number_format($stats['misses']); ?>
                                    </div>
                                    <div class="jabali-stat-label"><?php _e('Misses', 'jabali-cache'); ?></div>
                                </div>
                            </div>

                            <?php if ($stats['ratio'] < 50 && ($stats['hits'] + $stats['misses']) > 100): ?>
                            <div class="jabali-warning-notice">
                                <p><strong><?php _e('Low Hit Ratio:', 'jabali-cache'); ?></strong> <?php _e('Consider reviewing your caching strategy. High misses may indicate frequent cache flushes or too many unique cache keys.', 'jabali-cache'); ?></p>
                            </div>
                            <?php endif; ?>

                            <div class="jabali-actions">
                                <?php if ($drop_in_installed): ?>
                                    <a href="<?php echo wp_nonce_url(admin_url('options-general.php?page=jabali-cache&action=flush'), 'jabali_cache_flush'); ?>" class="button button-primary">
                                        <?php _e('Flush Cache', 'jabali-cache'); ?>
                                    </a>
                                    <a href="<?php echo wp_nonce_url(admin_url('options-general.php?page=jabali-cache&action=disable'), 'jabali_cache_disable'); ?>" class="button">
                                        <?php _e('Disable', 'jabali-cache'); ?>
                                    </a>
                                <?php elseif ($redis_available): ?>
                                    <a href="<?php echo wp_nonce_url(admin_url('options-general.php?page=jabali-cache&action=enable'), 'jabali_cache_enable'); ?>" class="button button-primary">
                                        <?php _e('Enable Object Cache', 'jabali-cache'); ?>
                                    </a>
                                <?php else: ?>
                                    <p class="description"><?php _e('Redis PHP extension is not installed.', 'jabali-cache'); ?></p>
                                <?php endif; ?>
                            </div>
                        </div>
                    </div>

                    <!-- Minification Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-editor-code"></span>
                            <h2><?php _e('Minification', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('HTML Minification', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Remove whitespace and comments from HTML output.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[html_minify]" value="1" <?php checked($this->settings['html_minify']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('CSS Minification', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Minify inline CSS styles.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[minify_css]" value="1" <?php checked($this->settings['minify_css']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('JS Minification', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Minify inline JavaScript (conservative).', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[minify_js]" value="1" <?php checked($this->settings['minify_js']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                        </div>
                    </div>

                    <!-- Media Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-format-image"></span>
                            <h2><?php _e('Media', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Lazy Load Images', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Defer loading of images until they enter the viewport.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[lazy_load]" value="1" <?php checked($this->settings['lazy_load']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Lazy Load iframes', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Defer loading of embedded videos and iframes.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[lazy_load_iframes]" value="1" <?php checked($this->settings['lazy_load_iframes']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Local Google Fonts', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Download and serve Google Fonts locally for faster loading and GDPR compliance.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[local_google_fonts]" value="1" <?php checked($this->settings['local_google_fonts']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                        </div>
                    </div>

                    <!-- JavaScript Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-media-code"></span>
                            <h2><?php _e('JavaScript', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Defer JavaScript', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Add defer attribute to non-critical scripts for faster page rendering.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[defer_js]" value="1" <?php checked($this->settings['defer_js']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Remove Query Strings', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Remove version query strings from static resources.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[remove_query_strings]" value="1" <?php checked($this->settings['remove_query_strings']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                        </div>
                    </div>

                    <!-- Cleanup Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-trash"></span>
                            <h2><?php _e('Cleanup', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Disable Emojis', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Remove WordPress emoji scripts and styles.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[disable_emojis]" value="1" <?php checked($this->settings['disable_emojis']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Disable oEmbed', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Disable WordPress embed discovery and related scripts.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[disable_embeds]" value="1" <?php checked($this->settings['disable_embeds']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                        </div>
                    </div>

                    <!-- LCP Optimization Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-performance"></span>
                            <h2><?php _e('LCP Optimization', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Preload LCP Image', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Detect and preload the largest image above the fold. Adds fetchpriority="high" and loading="eager" to speed up LCP.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[lcp_preload]" value="1" <?php checked($this->settings['lcp_preload']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Preconnect Hints', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Add preconnect hints for external domains (fonts, CDN) to reduce connection time.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[preconnect_hints]" value="1" <?php checked($this->settings['preconnect_hints']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Preload Fonts', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Preload critical web fonts to prevent late text rendering. Works best with Local Google Fonts enabled.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[preload_fonts]" value="1" <?php checked($this->settings['preload_fonts']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Delay Third-Party Scripts', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Delay analytics, chat widgets, and tracking scripts until user interaction. Improves initial page load.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[delay_third_party]" value="1" <?php checked($this->settings['delay_third_party']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-info-notice">
                                <p><strong><?php _e('LCP Tips:', 'jabali-cache'); ?></strong> <?php _e('LCP (Largest Contentful Paint) measures when the main content is visible. Enable Page Cache + LCP Preload for best results. Test with GTmetrix or PageSpeed Insights.', 'jabali-cache'); ?></p>
                            </div>
                        </div>
                    </div>

                    <!-- Developer Card -->
                    <div class="jabali-card">
                        <div class="jabali-card-header">
                            <span class="dashicons dashicons-admin-tools"></span>
                            <h2><?php _e('Developer', 'jabali-cache'); ?></h2>
                        </div>
                        <div class="jabali-card-body">
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Development Mode', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Disable all caching. Use during development to always see changes immediately.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[expired_cache]" value="1" <?php checked($this->settings['expired_cache']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-setting-row">
                                <div class="jabali-setting-info">
                                    <span class="jabali-setting-label"><?php _e('Debug Mode', 'jabali-cache'); ?></span>
                                    <span class="jabali-setting-desc"><?php _e('Show cache debug info in HTML comments when ?cache_debug=1 is added to URL.', 'jabali-cache'); ?></span>
                                </div>
                                <label class="jabali-toggle">
                                    <input type="checkbox" name="<?php echo self::OPTION_KEY; ?>[cache_debug]" value="1" <?php checked($this->settings['cache_debug']); ?>>
                                    <span class="jabali-toggle-slider"></span>
                                </label>
                            </div>
                            <div class="jabali-info-notice">
                                <p><strong><?php _e('Tip:', 'jabali-cache'); ?></strong> <?php _e('Check response headers for X-Cache (HIT/MISS) and X-Cache-Reason to diagnose caching behavior.', 'jabali-cache'); ?></p>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="jabali-submit-row">
                    <?php submit_button(__('Save Settings', 'jabali-cache'), 'primary', 'submit', false); ?>
                    <a href="<?php echo wp_nonce_url(admin_url('options-general.php?page=jabali-cache&action=clear_all'), 'jabali_cache_clear_all'); ?>" class="button">
                        <?php _e('Clear All Caches', 'jabali-cache'); ?>
                    </a>
                    <a href="<?php echo wp_nonce_url(admin_url('options-general.php?page=jabali-cache&action=purge_page'), 'jabali_cache_purge_page'); ?>" class="button">
                        <?php _e('Purge Page Cache', 'jabali-cache'); ?>
                    </a>
                </div>
            </form>

            <div class="jabali-footer">
                <h3><?php _e('About Jabali Cache', 'jabali-cache'); ?></h3>
                <p><?php _e('Jabali Cache provides comprehensive caching and optimization for WordPress sites hosted on Jabali Panel. It includes Redis object caching, nginx page caching with smart auto-purging, HTML/CSS/JS minification, lazy loading, local Google Fonts, and various performance optimizations.', 'jabali-cache'); ?></p>
                <p>
                    <strong><?php _e('Version:', 'jabali-cache'); ?></strong> <?php echo self::VERSION; ?> &nbsp;|&nbsp;
                    <strong><?php _e('Smart Cache Purge:', 'jabali-cache'); ?></strong> <?php echo $this->settings['page_cache'] ? '<span style="color:#00a32a;">' . __('Active', 'jabali-cache') . '</span>' : '<span style="color:#646970;">' . __('Inactive', 'jabali-cache') . '</span>'; ?>
                </p>
            </div>
        </div>
        <?php
    }
}

// Initialize
Jabali_Cache_Plugin::get_instance();

// Activation - enable object cache and page cache
register_activation_hook(__FILE__, function() {
    $plugin = Jabali_Cache_Plugin::get_instance();

    // Enable Redis object cache if available
    if (class_exists('Redis')) {
        $plugin->enable_drop_in();
    }

    // Always enable nginx page cache when plugin is activated
    // This is the main purpose of the plugin - users activate it because they want caching
    $plugin->enable_page_cache_on_activation();

    // Initialize default settings if they don't exist
    $settings = get_option(Jabali_Cache_Plugin::OPTION_KEY);
    if ($settings === false) {
        update_option(Jabali_Cache_Plugin::OPTION_KEY, ['page_cache' => true]);
    }
});

// Deactivation - disable object cache AND page cache
register_deactivation_hook(__FILE__, function() {
    $plugin = Jabali_Cache_Plugin::get_instance();
    $plugin->disable_drop_in();

    // Also disable nginx page cache when plugin is deactivated
    $plugin->disable_page_cache_on_deactivation();
});
