<?php
/**
 * Maintenance GENIUS - Main
 * Logique principale du mode maintenance
 * Version 2.9.126
 */

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

class MG_Main {

    /**
     * Instance des settings
     */
    private static $settings = null;

    /**
     * Debug logging wrapper — only logs when WP_DEBUG is enabled
     */
    private static function debug_log($message) {
        if (defined('WP_DEBUG') && WP_DEBUG) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug helper
            error_log('Maintenance GENIUS: ' . $message);
        }
    }

    /**
     * Initialize WP_Filesystem
     * @return WP_Filesystem_Base|false
     */
    private static function init_filesystem() {
        global $wp_filesystem;
        if (!function_exists('WP_Filesystem')) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }
        WP_Filesystem();
        return $wp_filesystem;
    }

    /**
     * Initialise le plugin
     */
    public static function init() {
        self::$settings = MG_Settings::load();

        self::maybe_upgrade_db();

        add_action('template_redirect', [__CLASS__, 'check_maintenance'], 1);

        add_action('upgrader_process_complete', [__CLASS__, 'on_upgrade'], 10, 2);

        if (!empty(self::$settings['maintenance_enabled'])) {
            self::install_mu_plugin();
            if (!get_transient('mg_init_purged')) {
                self::disable_cache_plugins();
                self::delete_directory_contents(ABSPATH . 'wp-content/cache/all/');
                self::delete_directory_contents(ABSPATH . 'wp-content/cache/wpfc-minified/');
                self::delete_directory_contents(ABSPATH . 'wp-content/cache/seraphinite-accelerator/');
                self::remove_wpfc_htaccess_rules();
                set_transient('mg_init_purged', 1, 3600);
            }
        } else {
            self::remove_mu_plugin();
        }
    }

    /**
     * Hook d'activation
     */
    public static function on_activation() {
        if (!get_option('mg_settings')) {
            $defaults = MG_Settings::get_defaults();
            $defaults['visitor_token'] = wp_generate_password(32, false);
            update_option('mg_settings', $defaults, false);
        }
        MG_Settings::migrate_stats_from_settings();
        MG_Settings::migrate_visitor_duration_to_seconds();
        MG_Settings::migrate_custom_bg_to_bg_image();
        MG_Settings::migrate_notification_emails_from_settings();
        MG_Settings::ensure_settings_autoload_off();
        update_option('mg_db_version', MG_VERSION, false);

        $settings = get_option('mg_settings', []);
        if (!empty($settings['maintenance_enabled'])) {
            self::install_mu_plugin();
        }
    }

    /**
     * v2.9.71 — Migration DB one-shot, déclenchée quand mg_db_version != MG_VERSION.
     * Idempotente : migrate_stats_from_settings() et ensure_settings_autoload_off()
     * ne font rien si déjà appliquées.
     */
    public static function maybe_upgrade_db() {
        if (get_option('mg_db_version') === MG_VERSION) {
            return;
        }
        MG_Settings::migrate_stats_from_settings();
        MG_Settings::migrate_visitor_duration_to_seconds();
        MG_Settings::migrate_custom_bg_to_bg_image();
        MG_Settings::migrate_notification_emails_from_settings();
        MG_Settings::ensure_settings_autoload_off();
        update_option('mg_db_version', MG_VERSION, false);
    }

    /**
     * Hook de mise à jour du plugin (v2.9.3)
     */
    public static function on_upgrade($upgrader, $options) {
        if (
            isset($options['action'], $options['type'], $options['plugins']) &&
            $options['action'] === 'update' &&
            $options['type'] === 'plugin' &&
            is_array($options['plugins'])
        ) {
            foreach ($options['plugins'] as $plugin) {
                if (strpos($plugin, 'maintenance-genius') !== false) {
                    $settings = get_option('mg_settings', []);
                    if (!empty($settings['maintenance_enabled'])) {
                        self::disable_cache_plugins();
                        self::install_mu_plugin();
                    }
                    break;
                }
            }
        }
    }

    /**
     * Installe le mu-plugin qui intercepte AVANT les plugins de cache (v2.9.3)
     * Les mu-plugins sont chargés avant les plugins normaux (y compris WPFC)
     */
    public static function install_mu_plugin() {
        $mu_dir = WPMU_PLUGIN_DIR;
        if (!is_dir($mu_dir)) {
            wp_mkdir_p( $mu_dir );
        }
        if (!is_dir($mu_dir)) return;

        $mu_file = $mu_dir . '/mg-cache-guard.php';
        
        $content = <<<'PHP'
<?php
/**
 * Maintenance GENIUS - Cache Guard (mu-plugin v2.9.42)
 * Intercepte AVANT les plugins de cache pour garantir l'affichage du MM.
 * Ce fichier est géré automatiquement par Maintenance GENIUS.
 * NE PAS MODIFIER - il sera recréé automatiquement.
 */
if (!defined('ABSPATH')) exit;

(function() {
    $uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ) );
    if (
        strpos($uri, '/wp-admin') !== false ||
        strpos($uri, '/wp-login.php') !== false ||
        strpos($uri, '/wp-cron.php') !== false ||
        strpos($uri, '/wp-json/') !== false ||
        strpos($uri, 'admin-ajax.php') !== false
    ) return;

    global $wpdb;
    if (!isset($wpdb) || !$wpdb) return;
    
    $row = $wpdb->get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = 'mg_settings' LIMIT 1");
    if (!$row) return;
    
    // d'objets PHP, neutralisant tout risque d'Object Injection même si la DB est compromise.
    // Retour false si pas serialized → fallback sur valeur brute (cas peu probable mais safe).
    $unserialized = @unserialize( $row, [ 'allowed_classes' => false ] );
    $settings = ( false !== $unserialized || $row === 'b:0;' ) ? $unserialized : $row;
    if (empty($settings) || !is_array($settings) || empty($settings['maintenance_enabled'])) return;

    if (!defined('DONOTCACHEPAGE')) define('DONOTCACHEPAGE', true);
    if (!defined('DONOTCACHEOBJECT')) define('DONOTCACHEOBJECT', true);
    if (!defined('DONOTCACHEDB')) define('DONOTCACHEDB', true);

    if (!headers_sent()) {
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        header('Pragma: no-cache');
        header('X-LiteSpeed-Cache-Control: no-cache');
        header('X-LiteSpeed-Purge: *');
    }

    $cache_dirs = [
        ABSPATH . 'wp-content/cache/all/',
        ABSPATH . 'wp-content/cache/wpfc-minified/',
        ABSPATH . 'wp-content/cache/wpfc-mobile-cache/',
        ABSPATH . 'wp-content/cache/wp-rocket/',
        ABSPATH . 'wp-content/cache/supercache/',
        ABSPATH . 'wp-content/cache/cache-enabler/',
        ABSPATH . 'wp-content/cache/seraphinite-accelerator/',
        ABSPATH . 'wp-content/litespeed/cssjs/',
        ABSPATH . 'wp-content/litespeed/page/',
    ];
    foreach ($cache_dirs as $dir) {
        if (is_dir($dir) && count(@scandir($dir)) > 2) {
            $it = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
                RecursiveIteratorIterator::CHILD_FIRST
            );
            foreach ($it as $f) {
                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- Iterator cleanup
                $f->isDir() ? @rmdir($f->getRealPath()) : wp_delete_file( $f->getRealPath() );
            }
        }
    }

    $guard_key = 'mg_guard_purged';
    $already = $wpdb->get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = '_transient_{$guard_key}' LIMIT 1");
    if ($already) return;

    set_transient($guard_key, 1, 3600);

    $htaccess = ABSPATH . '.htaccess';
    if (file_exists($htaccess) && is_writable($htaccess)) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable
        $ht_content = file_get_contents($htaccess);
        $ht_modified = false;
        if (strpos($ht_content, 'WpFastestCache') !== false) {
            $ht_content = preg_replace('/# BEGIN WpFastestCache.*?# END WpFastestCache\s*/s', '', $ht_content);
            $ht_content = preg_replace('/# BEGIN LBCWpFastestCache.*?# END LBCWpFastestCache\s*/s', '', $ht_content);
            $ht_content = preg_replace('/# BEGIN GzipWpFastestCache.*?# END GzipWpFastestCache\s*/s', '', $ht_content);
            $ht_modified = true;
        }
        if (strpos($ht_content, 'WPSuperCache') !== false) {
            $ht_content = preg_replace('/# BEGIN WPSuperCache.*?# END WPSuperCache\s*/s', '', $ht_content);
            $ht_modified = true;
        }
        if ($ht_modified) {
            file_put_contents($htaccess, $ht_content);
        }
    }

    $wpfc = $wpdb->get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = 'WpFastestCache' LIMIT 1");
    if ($wpfc) {
        $wpfc_data = @json_decode($wpfc, true);
        if ($wpfc_data && !empty($wpfc_data['wpFastestCacheStatus'])) {
            $saved = $wpdb->get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = 'mg_cache_saved_states' LIMIT 1");
            if (!$saved) {
                update_option('mg_cache_saved_states', ['wpfc' => $wpfc], false);
            }
            $wpfc_data['wpFastestCacheStatus'] = '';
            if (!empty($wpfc_data['wpFastestCachePreload'])) {
                $wpfc_data['wpFastestCachePreload'] = '';
            }
            update_option('WpFastestCache', json_encode($wpfc_data));
        }
    }

    if (function_exists('wp_cache_clear_cache')) {
        @wp_cache_clear_cache();
    }
    $wpdb->query($wpdb->prepare("UPDATE {$wpdb->options} SET option_value = %s WHERE option_name = %s LIMIT 1", '0', 'ossdl_off_cdn_url'));

    $wpdb->query($wpdb->prepare("UPDATE {$wpdb->options} SET option_value = %s WHERE option_name = %s LIMIT 1", '0', 'litespeed.conf.cache'));
})();
PHP;

        if (!file_exists($mu_file) || md5_file($mu_file) !== md5($content)) {
            $fs = self::init_filesystem();
            if ($fs) {
                $fs->put_contents($mu_file, $content, FS_CHMOD_FILE);
            }
        }
    }

    /**
     * Retire le mu-plugin (v2.9.3)
     */
    public static function remove_mu_plugin() {
        $mu_file = WPMU_PLUGIN_DIR . '/mg-cache-guard.php';
        if (file_exists($mu_file)) {
            wp_delete_file( $mu_file );
        }
    }

    /**
     * Vérifie si on doit afficher la page de maintenance
     */
    
    // CHECK MAINTENANCE — Point d'entrée principal (hook: template_redirect)
    // Ordre: planification → admin bypass → preview → token → cookie →
    //        rôle → IP whitelist → URL whitelist → géo-blocage → afficher
    public static function check_maintenance() {
        if (isset($_GET['mg_remote'])) {
            return;
        }
        
        self::check_countdown_auto_disable();
        
        self::$settings = MG_Settings::load();
        
        $request_uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ) );
        $client_ip = self::get_client_ip();
        $user_agent = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) );
        $referrer = sanitize_url( wp_unslash( $_SERVER['HTTP_REFERER'] ?? '' ) );

        if (!empty(self::$settings['blacklist_enabled'])) {
            $blocked = false;
            $reason = '';

            if (self::is_ip_in_list($client_ip, self::$settings['blacklist_ips'] ?? [])) {
                $blocked = true;
                $reason = 'IP';
            }

            if (!$blocked && self::is_in_list($user_agent, self::$settings['blacklist_user_agents'] ?? [])) {
                $blocked = true;
                $reason = 'User-Agent';
            }

            if (!$blocked && self::is_in_list($referrer, self::$settings['blacklist_referrers'] ?? [])) {
                $blocked = true;
                $reason = 'Referrer';
            }

            if (!$blocked && !empty(self::$settings['blacklist_countries'])) {
                $country = self::get_country_code($client_ip);
                if ($country && in_array($country, self::$settings['blacklist_countries'])) {
                    $blocked = true;
                    $reason = 'Country: ' . $country;
                }
            }

            if ($blocked) {
                if (!empty(self::$settings['blacklist_logging'])) {
                    self::log_blocked($client_ip, $user_agent, $reason);
                }
                self::show_blocked_page();
                exit;
            }
        }

        if (current_user_can('manage_options')) {
            if (isset($_GET['mg_preview']) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ?? '' ) ), 'mg_preview')) {
                self::show_maintenance_page();
                exit;
            }
            return;
        }

        $system_urls = ['/wp-admin', '/wp-login.php', '/wp-cron.php', '/admin-ajax.php', '/wp-json/'];
        foreach ($system_urls as $excluded) {
            if (strpos($request_uri, $excluded) !== false) {
                return;
            }
        }

        $is_maintenance_active = self::is_maintenance_active();
        if (!$is_maintenance_active) {
            return;
        }

        if (!get_transient('mg_cache_check')) {
            self::ensure_caches_disabled();
            set_transient('mg_cache_check', 1, 60);
        }

        if (!empty(self::$settings['whitelist_enabled'])) {
            
            $allowed_roles = self::$settings['whitelist_roles'] ?? ['administrator'];
            if (is_user_logged_in()) {
                $user = wp_get_current_user();
                foreach ($allowed_roles as $role) {
                    if (in_array($role, $user->roles)) {
                        return;
                    }
                }
            }

            if (self::is_ip_in_list($client_ip, self::$settings['whitelist_ips'] ?? [])) {
                return;
            }

            if (self::is_url_whitelisted($request_uri, self::$settings['whitelist_urls'] ?? [])) {
                return;
            }

            if (self::is_in_list($user_agent, self::$settings['whitelist_user_agents'] ?? [])) {
                return;
            }
        }

        if (isset($_GET['mg_access'])) {
            $token = sanitize_text_field( wp_unslash( $_GET['mg_access'] ) );
            $token_data = MG_Settings::validate_access_token($token, $client_ip);
            
            if ($token_data !== false) {
                MG_Settings::log_token_visit($token, $client_ip, $user_agent);
                
                $expiry = !empty($token_data['expires']) ? strtotime($token_data['expires']) : time() + DAY_IN_SECONDS;
                $cookie_hash = hash('sha256', $token . $expiry . SECURE_AUTH_KEY);
                $cookie_value = $token . '.' . $expiry . '.' . $cookie_hash;
                
                setcookie('mg_token_access', $cookie_value, [
                    'expires'  => $expiry,
                    'path'     => '/',
                    'secure'   => is_ssl(),
                    'httponly' => true,
                    'samesite' => 'Strict'
                ]);
                
                wp_safe_redirect(home_url());
                exit;
            }
        }
        
        if (isset( $_COOKIE['mg_token_access'] )) {
            $cookie_parts = explode('.', sanitize_text_field( wp_unslash( $_COOKIE['mg_token_access'] ) ));
            if (count($cookie_parts) === 3) {
                $token = $cookie_parts[0];
                $expiry = intval($cookie_parts[1]);
                $hash = $cookie_parts[2];
                
                if ($expiry > time()) {
                    $expected_hash = hash('sha256', $token . $expiry . SECURE_AUTH_KEY);
                    if (hash_equals($expected_hash, $hash)) {
                        $token_data = MG_Settings::validate_access_token($token, $client_ip);
                        if ($token_data !== false) {
                            return;
                        }
                    }
                }
            }
        }

        if (isset( $_COOKIE['mg_visitor_access'] )) {
            $cookie_parts = explode('.', sanitize_text_field( wp_unslash( $_COOKIE['mg_visitor_access'] ) ));
            if (count($cookie_parts) === 2) {
                $expiry = intval($cookie_parts[0]);
                $hash = $cookie_parts[1];
                $token = self::$settings['visitor_token'] ?? '';

                if ($expiry > time()) {
                    $expected_hash = hash('sha256', $expiry . $token . SECURE_AUTH_KEY);
                    if (hash_equals($expected_hash, $hash)) {
                        return;
                    }
                }
            }
        }

        register_shutdown_function([__CLASS__, 'purge_page_cache']);

        self::show_maintenance_page();
        exit;
    }

    /**
     * Vérifie si une IP est dans une liste (supporte wildcard et CIDR)
     */
    private static function is_ip_in_list($ip, $list) {
        if (empty($list)) return false;
        
        foreach ($list as $pattern) {
            $pattern = trim($pattern);
            if (empty($pattern)) continue;

            if ($pattern === $ip) return true;

            if (strpos($pattern, '*') !== false) {
                $regex = '/^' . str_replace(['*', '.'], ['.*', '\\.'], $pattern) . '$/';
                if (preg_match($regex, $ip)) return true;
            }

            if (strpos($pattern, '/') !== false) {
                if (self::ip_in_cidr($ip, $pattern)) return true;
            }
        }

        return false;
    }

    /**
     * Vérifie si une IP est dans un range CIDR
     */
    private static function ip_in_cidr($ip, $cidr) {
        list($subnet, $bits) = explode('/', $cidr);
        $ip_long = ip2long($ip);
        $subnet_long = ip2long($subnet);
        $mask = -1 << (32 - $bits);
        $subnet_long &= $mask;
        return ($ip_long & $mask) === $subnet_long;
    }

    /**
     * Vérifie si la maintenance est active (avec support programmation v2.6.28)
     * @return bool
     */
    
    // LOGIQUE ACTIVE — Vérifie si maintenance ON + planification
    private static function is_maintenance_active() {
        if (!empty(self::$settings['maintenance_enabled'])) {
            return true;
        }

        if (!empty(self::$settings['schedule_enabled'])) {
            $start_date = self::$settings['schedule_start_date'] ?? '';
            $start_time = self::$settings['schedule_start_time'] ?? '00:00';
            $end_date = self::$settings['schedule_end_date'] ?? '';
            $end_time = self::$settings['schedule_end_time'] ?? '23:59';
            $timezone = self::$settings['schedule_timezone'] ?? 'America/Montreal';

            if (!empty($start_date) && !empty($end_date)) {
                try {
                    $tz = new \DateTimeZone($timezone);
                    $now = new \DateTime('now', $tz);
                    
                    $start_datetime = \DateTime::createFromFormat('Y-m-d H:i', $start_date . ' ' . $start_time, $tz);
                    $end_datetime = \DateTime::createFromFormat('Y-m-d H:i', $end_date . ' ' . $end_time, $tz);

                    if ($start_datetime && $end_datetime) {
                        if ($now >= $start_datetime && $now <= $end_datetime) {
                            return true;
                        }
                    }
                } catch (\Exception $e) {
                    self::debug_log('Erreur de programmation - ' . $e->getMessage());
                }
            }
        }

        return false;
    }

    /**
     * Vérifie si une valeur contient un élément de la liste
     */
    private static function is_in_list($value, $list) {
        if (empty($list) || empty($value)) return false;
        
        $value_lower = strtolower($value);
        foreach ($list as $item) {
            $item = trim($item);
            if (empty($item)) continue;
            if (stripos($value_lower, strtolower($item)) !== false) {
                return true;
            }
        }
        return false;
    }

    /**
     * Vérifie si une URL est whitelistée (supporte wildcard)
     */
    private static function is_url_whitelisted($uri, $list) {
        if (empty($list)) return false;

        foreach ($list as $pattern) {
            $pattern = trim($pattern);
            if (empty($pattern)) continue;

            if ($pattern === $uri) return true;

            if (substr($pattern, -1) === '*') {
                $prefix = rtrim($pattern, '*');
                if (strpos($uri, $prefix) === 0) return true;
            }

            if (strpos($uri, $pattern) !== false) return true;
        }

        return false;
    }

    /**
     * Obtenir le code pays à partir de l'IP (si service dispo)
     */
    private static function get_country_code($ip) {
        if (!empty(sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ?? '' ) ))) {
            return strtoupper(sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ?? '' ) ));
        }

        return null;
    }

    /**
     * Logger un blocage
     */
    private static function log_blocked($ip, $user_agent, $reason) {
        $logs = get_option('mg_blacklist_logs', []);
        
        $logs[] = [
            'time' => current_time('mysql'),
            'ip' => $ip,
            'user_agent' => substr($user_agent, 0, 200),
            'reason' => $reason,
            'uri' => sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ) )
        ];

        if (count($logs) > 500) {
            $logs = array_slice($logs, -500);
        }

        update_option('mg_blacklist_logs', $logs, false);
    }

    /**
     * Obtenir l'IP du client
     */
    
    // UTILITAIRES IP — Détection, CIDR, wildcards, géo
    private static function get_client_ip() {
        $ip_keys = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR'];
        
        foreach ($ip_keys as $key) {
            if (!empty(sanitize_text_field( wp_unslash( $_SERVER[$key] ?? '' ) ))) {
                $ip = sanitize_text_field( wp_unslash( $_SERVER[$key] ?? '' ) );
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP)) {
                    return $ip;
                }
            }
        }
        
        return '0.0.0.0';
    }

    /**
     * Affiche la page de blocage (blacklist)
     */
    private static function show_blocked_page() {
        status_header(403);
        header('Content-Type: text/html; charset=utf-8');
        
        $message = self::$settings['blacklist_message'] ?? 'Access denied.';
        ?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="robots" content="noindex, nofollow">
    <title>403 - Access Denied</title>
    <style>
        body { 
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            background: #1a1a2e; 
            color: #fff; 
            display: flex; 
            align-items: center; 
            justify-content: center; 
            min-height: 100vh; 
            margin: 0;
        }
        .blocked { 
            text-align: center; 
            padding: 40px;
        }
        h1 { 
            font-size: 72px; 
            margin: 0 0 20px; 
            color: #e94560;
        }
        p { 
            font-size: 18px; 
            color: #b0b0b0;
        }
    </style>
</head>
<body>
    <div class="blocked">
        <h1>403</h1>
        <p><?php echo esc_html($message); ?></p>
    </div>
</body>
</html>
        <?php
    }

    /**
     * Vérifie si le countdown est terminé et désactive automatiquement la maintenance (v2.6.16)
     */
    
    // COUNTDOWN — Auto-disable + notifications email
    private static function check_countdown_auto_disable() {
        $settings = MG_Settings::load_fresh(); /* v2.9.127 — anti-cache périmé (Redis) */
        
        if (empty($settings['maintenance_enabled'])) {
            return;
        }
        
        if (empty($settings['countdown_enabled'])) {
            return;
        }
        
        if (empty($settings['countdown_auto_disable'])) {
            return;
        }
        
        if (empty($settings['countdown_date'])) {
            return;
        }
        
        $countdown_time = $settings['countdown_time'] ?? '00:00';
        $target_datetime = $settings['countdown_date'] . ' ' . $countdown_time . ':00';
        
        try {
            $wp_timezone = wp_timezone();
            $target_date = new DateTime($target_datetime, $wp_timezone);
            $target_timestamp = $target_date->getTimestamp();
        } catch (Exception $e) {
            return;
        }
        
        $now = time();
        
        if ($target_timestamp > $now) {
            return;
        }
        
        
        $notification_emails = MG_Settings::get_notification_emails();
        $email_count = count($notification_emails);
        
        self::debug_log('Countdown terminé - ' . $email_count . ' email(s) à notifier');
        
        $settings['maintenance_enabled'] = false;
        
        $settings['countdown_enabled'] = false;
        
        MG_Settings::save($settings);
        
        MG_Settings::set_notification_emails( [] );
        
        if (!empty($notification_emails)) {
            self::send_countdown_notifications($notification_emails);
        }
        
        self::debug_log('Maintenance désactivée automatiquement à ' . gmdate('Y-m-d H:i:s'));
        
        wp_safe_redirect(home_url());
        exit;
    }
    
    /**
     * Envoie les notifications email aux inscrits (v2.6.17)
     * @param array $emails Liste des emails à notifier
     */
    private static function send_countdown_notifications($emails) {
        if (empty($emails)) {
            self::debug_log('Aucun email à envoyer');
            return;
        }
        
        $site_name = get_bloginfo('name');
        $site_url = home_url();
        
        /* translators: %s: site name */
        $subject = sprintf(__('🎉 %s is now online!', 'maintenance-genius'), $site_name);
        
        $message = sprintf(
            /* translators: 1: site name, 2: site URL */
            __("Hello,\n\nGreat news! The site %1\$s is now online.\n\nYou can visit it right now:\n%2\$s\n\nThank you for your patience!\n\n---\nThis email was sent automatically because you requested to be notified.", 'maintenance-genius'),
            $site_name,
            $site_url
        );
        
        $headers = [
            'Content-Type: text/plain; charset=UTF-8',
            'From: ' . $site_name . ' <' . get_option('admin_email') . '>'
        ];
        
        $sent_count = 0;
        $failed_count = 0;
        
        foreach ($emails as $email_data) {
            $email = $email_data['email'] ?? '';
            if (!empty($email) && is_email($email)) {
                self::debug_log('Envoi email à ' . $email);
                if (wp_mail($email, $subject, $message, $headers)) {
                    $sent_count++;
                    self::debug_log('✓ Email envoyé à ' . $email);
                } else {
                    $failed_count++;
                    self::debug_log('✗ Échec envoi à ' . $email);
                }
            }
        }
        
        self::debug_log('Résultat - ' . $sent_count . ' envoyé(s), ' . $failed_count . ' échoué(s)');
    }

    /**
     * Affiche la page de maintenance
     */
    /**
     * Purge les fichiers cache après avoir servi la page de maintenance (v2.9.5)
     * Appelé via register_shutdown_function pour supprimer les caches
     * que WPFC ou d'autres plugins auraient pu créer pendant cette requête
     */
    
    // CACHE MANAGEMENT — Purge et désactivation des plugins cache
    // Compatible: WP Super Cache, W3TC, WP Rocket, LiteSpeed,
    //             WP Fastest Cache, Autoptimize, SG Optimizer, etc.
    public static function purge_page_cache() {
        $dirs = [
            ABSPATH . 'wp-content/cache/all/',
            ABSPATH . 'wp-content/cache/wpfc-minified/',
            ABSPATH . 'wp-content/cache/wpfc-mobile-cache/',
            ABSPATH . 'wp-content/cache/seraphinite-accelerator/',
        ];
        foreach ($dirs as $dir) {
            if (is_dir($dir)) {
                self::delete_directory_contents($dir);
            }
        }
    }

    
    // RENDU — Instancie MG_Frontend et affiche la page 503
    private static function show_maintenance_page() {
        if (!defined('DONOTMINIFY')) define('DONOTMINIFY', true);
        if (!defined('DONOTASYNCCSS')) define('DONOTASYNCCSS', true);
        if (!defined('DONOTCACHEPAGE')) define('DONOTCACHEPAGE', true);

        while (ob_get_level() > 0) {
            ob_end_clean();
        }

        status_header(503);
        header('Content-Type: text/html; charset=utf-8');
        header('Retry-After: 3600');
        
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        header('Pragma: no-cache');
        header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
        header('X-LiteSpeed-Cache-Control: no-cache');
        header('CDN-Cache-Control: no-store');

        require_once MG_PLUGIN_DIR . 'includes/class-frontend.php';
        $frontend = new MG_Frontend(self::$settings);
        $frontend->render();
    }

    /**
     * Vérifie et désactive les caches si MM est actif (v2.9.1)
     * Appelé une fois par minute via transient pour ne pas impacter la perf
     */
    private static function ensure_caches_disabled() {
        $wpfc = get_option('WpFastestCache');
        if ($wpfc) {
            $wpfc_data = @json_decode($wpfc, true);
            if ($wpfc_data && !empty($wpfc_data['wpFastestCacheStatus'])) {
                self::disable_cache_plugins();
                self::delete_directory_contents(ABSPATH . 'wp-content/cache/all/');
                self::delete_directory_contents(ABSPATH . 'wp-content/cache/wpfc-minified/');
                self::delete_directory_contents(ABSPATH . 'wp-content/cache/seraphinite-accelerator/');
                return;
            }
        }

        if (defined('WPCACHEHOME') && get_option('wpsupercache_disabled') != 1) {
            self::disable_cache_plugins();
            return;
        }

        if (get_option('litespeed.conf.cache') && get_option('litespeed.conf.cache') != 0) {
            self::disable_cache_plugins();
            return;
        }

        if (get_option('siteground_optimizer_enable_cache') == 1) {
            self::disable_cache_plugins();
            return;
        }

        $cache_dir = ABSPATH . 'wp-content/cache/all/';
        if (is_dir($cache_dir) && count(glob($cache_dir . '*')) > 0) {
            self::delete_directory_contents($cache_dir);
        }

        $htaccess = ABSPATH . '.htaccess';
        if (file_exists($htaccess)) {
            $fs = self::init_filesystem();
            $content = $fs ? $fs->get_contents($htaccess) : false;
            if ($content && strpos($content, 'WpFastestCache') !== false) {
                self::remove_wpfc_htaccess_rules();
            }
        }
    }

    /**
     * Gère les plugins de cache lors du toggle MM (v2.9.1)
     * MM ON  → sauvegarde l'état des caches, les désactive, purge les fichiers
     * MM OFF → restaure l'état sauvegardé des caches
     */
    public static function flush_all_caches() {
        self::$settings = MG_Settings::load();
        $is_active = !empty(self::$settings['maintenance_enabled']);

        if ($is_active) {
            self::disable_cache_plugins();
            self::install_mu_plugin();
        } else {
            self::restore_cache_plugins();
            self::remove_mu_plugin();
        }

        self::remove_htaccess_legacy();
        self::cleanup_dropin_legacy();

        $cache_dirs = [
            ABSPATH . 'wp-content/cache/all/',
            ABSPATH . 'wp-content/cache/wpfc-minified/',
            ABSPATH . 'wp-content/cache/wp-rocket/',
            ABSPATH . 'wp-content/cache/supercache/',
            ABSPATH . 'wp-content/cache/cache-enabler/',
            ABSPATH . 'wp-content/cache/seraphinite-accelerator/',
            ABSPATH . 'wp-content/litespeed/cssjs/',
        ];
        foreach ($cache_dirs as $dir) {
            if (is_dir($dir)) {
                self::delete_directory_contents($dir);
            }
        }

        if (function_exists('wpfc_clear_all_cache')) {
            wpfc_clear_all_cache(true);
        } elseif (isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')) {
            $GLOBALS['wp_fastest_cache']->deleteCache(true);
        }
        if (function_exists('wp_cache_clear_cache')) wp_cache_clear_cache();
        if (function_exists('w3tc_flush_all')) w3tc_flush_all();
        if (function_exists('rocket_clean_domain')) rocket_clean_domain();
        if (class_exists('LiteSpeed\Purge') || defined('LSCWP_V')) do_action('litespeed_purge_all');
        if (class_exists('autoptimizeCache')) autoptimizeCache::clearall();
        if (class_exists('Cache_Enabler')) Cache_Enabler::clear_total_cache();
        if (class_exists('Hummingbird\\Core\\Utils')) do_action('wphb_clear_page_cache');
        if (function_exists('sg_cachepress_purge_everything')) sg_cachepress_purge_everything();
        if (class_exists('Breeze_PurgeCache')) do_action('breeze_clear_all_cache');
        if (function_exists('wp_cache_flush')) wp_cache_flush();
    }

    /**
     * Désactive tous les plugins de cache détectés et sauvegarde leur état (v2.9.1)
     */
    private static function disable_cache_plugins() {
        $saved_states = [];

        $wpfc = get_option('WpFastestCache');
        if ($wpfc) {
            $wpfc_data = @json_decode($wpfc, true);
            if ($wpfc_data && !empty($wpfc_data['wpFastestCacheStatus'])) {
                $saved_states['wpfc'] = $wpfc;
                $wpfc_data['wpFastestCacheStatus'] = '';
                if (!empty($wpfc_data['wpFastestCachePreload'])) {
                    $wpfc_data['wpFastestCachePreload'] = '';
                }
                update_option('WpFastestCache', json_encode($wpfc_data));
                self::remove_wpfc_htaccess_rules();
            }
        }

        $wpsc = get_option('wpsupercache_disabled');
        if (defined('WPCACHEHOME') || get_option('ossdl_off_cdn_url')) {
            $saved_states['wpsc_disabled'] = $wpsc;
            update_option('wpsupercache_disabled', 1);
        }

        if (defined('W3TC') || class_exists('W3_Config')) {
            $w3tc_enabled = get_option('w3tc_pgcache_enabled');
            if ($w3tc_enabled) {
                $saved_states['w3tc_pgcache'] = $w3tc_enabled;
                update_option('w3tc_pgcache_enabled', 0);
            }
        }

        $wp_rocket = get_option('wp_rocket_settings');
        if ($wp_rocket && is_array($wp_rocket)) {
            $saved_states['wp_rocket'] = $wp_rocket;
            $wp_rocket['cache_mobile'] = 0;
            $wp_rocket['do_caching_mobile_files'] = 0;
            update_option('wp_rocket_settings', $wp_rocket);
        }

        $lscache = get_option('litespeed.conf.cache');
        if ($lscache !== false) {
            $saved_states['litespeed_cache'] = $lscache;
            update_option('litespeed.conf.cache', 0);
        }

        $ce_options = get_option('cache_enabler');
        if ($ce_options && is_array($ce_options)) {
            $saved_states['cache_enabler'] = $ce_options;
            $ce_options['cache_expires'] = 0;
            update_option('cache_enabler', $ce_options);
        }

        $hb_settings = get_option('wphb_settings');
        if ($hb_settings && is_array($hb_settings)) {
            $saved_states['hummingbird'] = $hb_settings;
            if (isset($hb_settings['page_cache'])) {
                $hb_settings['page_cache']['enabled'] = false;
                update_option('wphb_settings', $hb_settings);
            }
        }

        $sg_cache = get_option('siteground_optimizer_enable_cache');
        if ($sg_cache !== false) {
            $saved_states['sg_optimizer'] = $sg_cache;
            update_option('siteground_optimizer_enable_cache', 0);
        }

        $breeze = get_option('breeze_basic_settings');
        if ($breeze && is_array($breeze)) {
            $saved_states['breeze'] = $breeze;
            $breeze['breeze-active'] = '0';
            update_option('breeze_basic_settings', $breeze);
        }

        if (!empty($saved_states)) {
            update_option('mg_cache_saved_states', $saved_states, false);
        }
    }

    /**
     * Restaure l'état des plugins de cache sauvegardé (v2.9.1)
     */
    private static function restore_cache_plugins() {
        $saved_states = get_option('mg_cache_saved_states', []);
        if (empty($saved_states)) return;

        if (isset($saved_states['wpfc'])) {
            update_option('WpFastestCache', $saved_states['wpfc']);
        }

        if (isset($saved_states['wpsc_disabled'])) {
            update_option('wpsupercache_disabled', $saved_states['wpsc_disabled']);
        }

        if (isset($saved_states['w3tc_pgcache'])) {
            update_option('w3tc_pgcache_enabled', $saved_states['w3tc_pgcache']);
        }

        if (isset($saved_states['wp_rocket'])) {
            update_option('wp_rocket_settings', $saved_states['wp_rocket']);
        }

        if (isset($saved_states['litespeed_cache'])) {
            update_option('litespeed.conf.cache', $saved_states['litespeed_cache']);
        }

        if (isset($saved_states['cache_enabler'])) {
            update_option('cache_enabler', $saved_states['cache_enabler']);
        }

        if (isset($saved_states['hummingbird'])) {
            update_option('wphb_settings', $saved_states['hummingbird']);
        }

        if (isset($saved_states['sg_optimizer'])) {
            update_option('siteground_optimizer_enable_cache', $saved_states['sg_optimizer']);
        }

        if (isset($saved_states['breeze'])) {
            update_option('breeze_basic_settings', $saved_states['breeze']);
        }

        delete_option('mg_cache_saved_states');
        delete_transient('mg_cache_check');
        delete_transient('mg_init_purged');
        delete_transient('mg_guard_purged');
    }

    /**
     * Supprime les règles .htaccess de WPFC (v2.9.1)
     */
    private static function remove_wpfc_htaccess_rules() {
        $htaccess_file = ABSPATH . '.htaccess';
        if (!file_exists($htaccess_file) || !is_writable($htaccess_file)) return; // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable

        $fs = self::init_filesystem();
        if (!$fs) return;

        $content = $fs->get_contents($htaccess_file);
        if ($content === false) return;

        $new_content = preg_replace('/# BEGIN WpFastestCache.*?# END WpFastestCache\s*/s', '', $content);
        $new_content = preg_replace('/# BEGIN LBCWpFastestCache.*?# END LBCWpFastestCache\s*/s', '', $new_content);
        $new_content = preg_replace('/# BEGIN GzipWpFastestCache.*?# END GzipWpFastestCache\s*/s', '', $new_content);

        if ($new_content !== $content) {
            $fs->put_contents($htaccess_file, $new_content, FS_CHMOD_FILE);
        }
    }

    /**
     * Supprime récursivement le contenu d'un dossier
     */
    private static function delete_directory_contents($dir) {
        if (!is_dir($dir)) return;
        $files = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS),
            \RecursiveIteratorIterator::CHILD_FIRST
        );
        foreach ($files as $file) {
            if ($file->isDir()) {
                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- Cleanup iterator
                @rmdir($file->getRealPath());
            } else {
                wp_delete_file( $file->getRealPath() );
            }
        }
    }

    /**
     * Nettoyage drop-in legacy v2.9.0
     */
    private static function cleanup_dropin_legacy() {
        $flag_file = WP_CONTENT_DIR . '/mg-cache-bypass.php';
        $dropin_file = WP_CONTENT_DIR . '/advanced-cache.php';

        if (file_exists($flag_file)) {
            wp_delete_file( $flag_file );
        }

        if (file_exists($dropin_file)) {
            $fs = self::init_filesystem();
            $content = $fs ? $fs->get_contents($dropin_file) : false;
            if ($content && strpos($content, 'Maintenance GENIUS') !== false) {
                if (strpos($content, 'Maintenance GENIUS - Advanced Cache Drop-in') !== false
                    && substr_count($content, '<?php') <= 2) {
                    wp_delete_file( $dropin_file );
                } else {
                    $content = preg_replace(
                        '/\<\?php\s*\n\/\/ Maintenance GENIUS Cache Bypass.*?define\(\'DONOTCACHEPAGE\'.*?\?\>\s*\n/s',
                        '',
                        $content
                    );
                    if ($fs) {
                        $fs->put_contents($dropin_file, $content, FS_CHMOD_FILE);
                    }
                }
            }
        }
    }

    /**
     * Nettoie les règles .htaccess legacy v2.8.8-2.8.10
     */
    private static function remove_htaccess_legacy() {
        $htaccess_file = ABSPATH . '.htaccess';
        if (!file_exists($htaccess_file) || !is_writable($htaccess_file)) return; // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable

        $fs = self::init_filesystem();
        if (!$fs) return;

        $content = $fs->get_contents($htaccess_file);
        if ($content === false || strpos($content, '# BEGIN Maintenance GENIUS') === false) return;

        $new_content = preg_replace('/# BEGIN Maintenance GENIUS.*?# END Maintenance GENIUS\s*/s', '', $content);
        if ($new_content !== $content) {
            $fs->put_contents($htaccess_file, $new_content, FS_CHMOD_FILE);
        }
    }

    /**
     * Getter pour les settings (utile pour d'autres classes)
     */
    public static function get_settings() {
        if (self::$settings === null) {
            self::$settings = MG_Settings::load();
        }
        return self::$settings;
    }
}
