<?php
/**
 * Firewall Setup Handler for BotFend Anti-Bot Firewall
 *
 * @package BotFend\Core
 * @version 4.8.1
 */

namespace BotFend\Core;

use BotFend\Utilities\Utilities;

defined('ABSPATH') || exit;

class FirewallSetup {

    private $config;
    private $utilities;
    private $database = null;
    private $firewall_dir;
    private $bootstrap_file;

    public function __construct(Config $config, Utilities $utilities) {
        $this->config = $config;
        $this->utilities = $utilities;
        $this->firewall_dir = WP_CONTENT_DIR . '/botfend-firewall';
        $this->bootstrap_file = $this->firewall_dir . '/botfend-firewall.php';
    }

    public function set_database($database): void {
        $this->database = $database;
    }

    public function detect_environment(): array {
        $sapi = php_sapi_name();
        $env = [
            'sapi' => $sapi,
            'server_software' => isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : 'unknown',
            'can_use_user_ini' => $this->can_use_user_ini(),
            'can_use_htaccess' => $this->can_use_htaccess(),
            'current_prepend' => ini_get('auto_prepend_file') ?: null,
            'php_version' => PHP_VERSION,
            'wordpress_version' => get_bloginfo('version'),
            'abspath' => ABSPATH,
            'wp_content_dir' => WP_CONTENT_DIR,
            'firewall_dir' => $this->firewall_dir,
            'is_apache' => $this->is_apache(),
            'is_litespeed' => $this->is_litespeed(),
            'is_nginx' => $this->is_nginx(),
            'is_fpm' => $this->is_fpm(),
        ];
        return $env;
    }

    private function can_use_user_ini(): bool {
        $sapi = php_sapi_name();
        if (in_array($sapi, array('cgi-fcgi', 'fpm-fcgi', 'litespeed'), true)) {
            $user_ini_file = ABSPATH . '.user.ini';
            if (file_exists($user_ini_file)) {
                return is_writable($user_ini_file);
            }
            return is_writable(ABSPATH);
        }
        return false;
    }

    private function can_use_htaccess(): bool {
        if (!$this->is_apache() && !$this->is_litespeed()) {
            return false;
        }
        $htaccess_file = ABSPATH . '.htaccess';
        if (file_exists($htaccess_file)) {
            return is_writable($htaccess_file);
        }
        return is_writable(ABSPATH);
    }

    private function is_apache(): bool {
        $server = isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '';
        return strpos($server, 'Apache') !== false;
    }

    private function is_litespeed(): bool {
        $server = isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '';
        return strpos($server, 'LiteSpeed') !== false;
    }

    private function is_nginx(): bool {
        $server = isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '';
        return strpos($server, 'nginx') !== false;
    }

    private function is_fpm(): bool {
        $sapi = php_sapi_name();
        return $sapi === 'fpm-fcgi';
    }

    public function get_status(): array {
        $env = $this->detect_environment();
        $configured = $this->is_configured();
        $active = $this->is_active();
        $pending = get_transient('botfend_firewall_pending');
        if ($pending && $active) {
            delete_transient('botfend_firewall_pending');
            $pending = false;
        }
        $status = [
            'configured' => $configured,
            'active' => $active,
            'pending' => (bool) $pending,
            'mode' => $active ? 'full' : $this->get_current_mode(),
            'bootstrap_exists' => file_exists($this->bootstrap_file),
            'firewall_dir_exists' => is_dir($this->firewall_dir),
            'environment' => $env,
            'has_conflict' => $this->has_existing_prepend_conflict(),
            'recommended_method' => $this->get_recommended_method(),
        ];
        return $status;
    }

    public function is_configured(): bool {
        $current_prepend = ini_get('auto_prepend_file');
        if (empty($current_prepend)) {
            return false;
        }
        $current_path = $this->normalize_path($current_prepend);
        $bootstrap_path = $this->normalize_path($this->bootstrap_file);
        return $current_path === $bootstrap_path;
    }

    public function is_active(): bool {
        return $this->is_configured() && file_exists($this->bootstrap_file);
    }

    private function get_current_mode(): string {
        $mu_plugin_file = WPMU_PLUGIN_DIR . '/0-botfend-anti-bot-firewall.php';
        if (file_exists($mu_plugin_file)) {
            return 'basic';
        }
        return 'none';
    }

    public function has_existing_prepend_conflict(): bool {
        $current_prepend = ini_get('auto_prepend_file');
        if (empty($current_prepend)) {
            return false;
        }
        $current_path = $this->normalize_path($current_prepend);
        $bootstrap_path = $this->normalize_path($this->bootstrap_file);
        return $current_path !== $bootstrap_path;
    }

    public function get_recommended_method(): string {
        $env = $this->detect_environment();
        if ($env['can_use_user_ini']) {
            return 'user_ini';
        }
        if ($env['can_use_htaccess']) {
            return 'htaccess';
        }
        return 'manual';
    }

    public function configure($method = '') {
        if (empty($method)) {
            $method = $this->get_recommended_method();
        }
        $dir_result = $this->create_firewall_directory();
        if (!$dir_result['success']) {
            return $dir_result;
        }
        $bootstrap_result = $this->create_bootstrap_file();
        if (!$bootstrap_result['success']) {
            return $bootstrap_result;
        }
        $this->sync_cache_files();
        switch ($method) {
            case 'user_ini':
                return $this->configure_user_ini();
            case 'htaccess':
                return $this->configure_htaccess();
            default:
                return [
                    'success' => false,
                    'message' => esc_html__('Manual configuration required.', 'botfend-anti-bot-firewall'),
                    'method' => 'manual',
                    'instructions' => $this->get_manual_instructions($method),
                ];
        }
    }

    public function create_firewall_directory() {
        if (!file_exists($this->firewall_dir)) {
            if (!wp_mkdir_p($this->firewall_dir)) {
                return [
                    'success' => false,
                    'message' => sprintf(esc_html__('Could not create firewall directory: %s', 'botfend-anti-bot-firewall'), $this->firewall_dir),
                ];
            }
        }
        $cache_dir = $this->firewall_dir . '/cache';
        if (!file_exists($cache_dir)) {
            wp_mkdir_p($cache_dir);
        }
        $ratelimit_dir = $cache_dir . '/ratelimit';
        if (!file_exists($ratelimit_dir)) {
            wp_mkdir_p($ratelimit_dir);
        }
        $logs_dir = $this->firewall_dir . '/logs';
        if (!file_exists($logs_dir)) {
            wp_mkdir_p($logs_dir);
        }
        $this->write_htaccess_protection();
        return [
            'success' => true,
            'message' => esc_html__('Firewall directory created successfully.', 'botfend-anti-bot-firewall'),
        ];
    }

    private function write_htaccess_protection(): void {
        $htaccess_main = $this->firewall_dir . '/.htaccess';
        file_put_contents($htaccess_main, "Order Deny,Allow\nDeny from all\n");
        $htaccess_cache = $this->firewall_dir . '/cache/.htaccess';
        file_put_contents($htaccess_cache, "Order Deny,Allow\nDeny from all\n");
        $htaccess_logs = $this->firewall_dir . '/logs/.htaccess';
        file_put_contents($htaccess_logs, "Order Deny,Allow\nDeny from all\n");
        file_put_contents($this->firewall_dir . '/index.php', '<?php // Silence is golden.');
        file_put_contents($this->firewall_dir . '/cache/index.php', '<?php // Silence is golden.');
        file_put_contents($this->firewall_dir . '/logs/index.php', '<?php // Silence is golden.');
    }

    public function sync_cache_files(): void {
        $this->update_whitelist_cache();
        $this->sync_blocklist_from_database();
    }

    public function update_whitelist_cache(): bool {
        $whitelist_file = $this->firewall_dir . '/cache/whitelist.cache';
        if (!is_dir(dirname($whitelist_file))) {
            wp_mkdir_p(dirname($whitelist_file));
        }
        $whitelist = get_option('botfend_whitelist_ips', '');
        $result = file_put_contents($whitelist_file, $whitelist, LOCK_EX);
        if ($result !== false) {
            if (method_exists($this->config, 'clear_cache')) {
                $this->config->clear_cache('whitelist_ips');
            }
            wp_cache_delete('botfend_whitelist_ips', 'options');
        }
        return $result !== false;
    }

    public function sync_blocklist_from_database(): bool {
        $blocklist_file = $this->firewall_dir . '/cache/blocklist.cache';
        if (!is_dir(dirname($blocklist_file))) {
            wp_mkdir_p(dirname($blocklist_file));
        }
        $blocked_ips = [];
        if ($this->database && method_exists($this->database, 'get_blocklist')) {
            $active_blocks = $this->database->get_blocklist([], 1000);
            if (is_array($active_blocks)) {
                foreach ($active_blocks as $block) {
                    $ip = $block->ip;
                    $expires = 0;
                    if (!empty($block->expires) && $block->expires !== '0000-00-00 00:00:00') {
                        $expires = strtotime($block->expires);
                    }
                    $blocked_ips[$ip] = $expires;
                }
            }
        }
        $permanent_blocklist = get_option('botfend_permanent_blocklist', '');
        if (!empty($permanent_blocklist)) {
            $lines = explode("\n", str_replace("\r\n", "\n", $permanent_blocklist));
            foreach ($lines as $line) {
                $line = trim($line);
                if (empty($line) || strpos($line, '#') === 0) {
                    continue;
                }
                if (!isset($blocked_ips[$line])) {
                    $blocked_ips[$line] = 0;
                }
            }
        }
        $lines = [];
        foreach ($blocked_ips as $ip => $expires) {
            $lines[] = $ip . '|' . $expires;
        }
        $result = file_put_contents($blocklist_file, implode("\n", $lines), LOCK_EX);
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('BotFend Firewall: Synced ' . count($lines) . ' IPs to blocklist.cache');
        }
        return $result !== false;
    }

    public function update_blocklist_cache($blocked_ips = null): bool {
        $blocklist_file = $this->firewall_dir . '/cache/blocklist.cache';
        if (!is_dir(dirname($blocklist_file))) {
            wp_mkdir_p(dirname($blocklist_file));
        }
        if ($blocked_ips === null) {
            return $this->sync_blocklist_from_database();
        }
        $lines = [];
        foreach ($blocked_ips as $ip => $expires) {
            $lines[] = $ip . '|' . $expires;
        }
        return file_put_contents($blocklist_file, implode("\n", $lines), LOCK_EX) !== false;
    }

    private function create_bootstrap_file() {
        $content = $this->get_bootstrap_template();
        $result = file_put_contents($this->bootstrap_file, $content, LOCK_EX);
        if (false === $result) {
            return [
                'success' => false,
                'message' => sprintf(esc_html__('Could not write bootstrap file to %s', 'botfend-anti-bot-firewall'), $this->bootstrap_file),
            ];
        }
        @chmod($this->bootstrap_file, 0644);
        if (!is_readable($this->bootstrap_file)) {
            return [
                'success' => false,
                'message' => esc_html__('Bootstrap file created but is not readable by the web server. Check file permissions.', 'botfend-anti-bot-firewall'),
            ];
        }
        return [
            'success' => true,
            'message' => esc_html__('Bootstrap file created successfully.', 'botfend-anti-bot-firewall'),
        ];
    }


private function get_bootstrap_template() {

    $existing_prepend = ini_get('auto_prepend_file');

    $has_conflict = $existing_prepend
        && $this->normalize_path($existing_prepend) !== $this->normalize_path($this->bootstrap_file);

    $include_existing = '';

    if ($has_conflict && file_exists($existing_prepend)) {

        $safe_path = str_replace(["\\", "'"], ["/", "\\'"], $existing_prepend);

        $include_existing = "
if (file_exists('{$safe_path}')) {
    include_once '{$safe_path}';
}
";
    }

    $css_url = defined('BOTFEND_ASSETS_URL') 
        ? BOTFEND_ASSETS_URL . 'css/botfend-block-page.css' 
        : plugins_url('assets/css/botfend-block-page.css', dirname(__DIR__, 2) . '/botfend-anti-bot-firewall.php');

    return '<?php
if (!defined("BOTFEND_EARLY_FIREWALL")) {
    define("BOTFEND_EARLY_FIREWALL", true);
}

define("BOTFEND_CACHE_DIR", __DIR__ . "/cache");

class BotfendEarlyFirewall {

    public static function init(): void {

        if (self::is_admin_request()) return;

        $ip = self::get_client_ip();
        if (!$ip) return;

        if (self::is_whitelisted($ip)) return;

        if (self::is_blocked($ip)) {
            self::render_block_page($ip, "blocked");
            exit;
        }

        if (self::check_rate_limit($ip)) {
            self::render_block_page($ip, "rate_limit");
            exit;
        }
    }

    private static function is_admin_request(): bool {
        $uri = $_SERVER["REQUEST_URI"] ?? "";
        return strpos($uri, "/wp-admin") === 0 || strpos($uri, "/wp-login.php") === 0;
    }

    private static function get_client_ip(): ?string {
        foreach (["HTTP_CF_CONNECTING_IP","HTTP_X_FORWARDED_FOR","REMOTE_ADDR"] as $k) {
            if (!empty($_SERVER[$k])) {
                $ip = trim(explode(",", $_SERVER[$k])[0]);
                if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
            }
        }
        return null;
    }

    private static function parse_cache(string $file): array {

        $key = "botfend_cache_" . md5($file);

        if (function_exists("apcu_fetch")) {
            $cached = apcu_fetch($key, $hit);
            if ($hit) return $cached;
        }

        if (!file_exists($file)) return [[], []];

        $lines = @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if (!$lines) return [[], []];

        $exact = [];
        $cidr  = [];
        $now = time();

        foreach ($lines as $line) {

            $parts = explode("|", $line);
            if (count($parts) < 2) continue;

            $ip = trim($parts[0]);
            $exp = (int)$parts[1];

            if ($exp > 0 && $exp < $now) continue;

            if (strpos($ip, "/") === false) {
                $exact[$ip] = true;
            } else {
                $cidr[] = $ip;
            }
        }

        $result = [$exact, $cidr];

        if (function_exists("apcu_store")) {
            apcu_store($key, $result, 10);
        }

        return $result;
    }

    private static function is_whitelisted(string $ip): bool {
        $file = BOTFEND_CACHE_DIR . "/whitelist.cache";
        list($exact, $cidr) = self::parse_cache($file);

        if (isset($exact[$ip])) return true;

        foreach ($cidr as $range) {
            if (self::ip_in_range($ip, $range)) return true;
        }

        return false;
    }

    private static function is_blocked(string $ip): bool {
        $file = BOTFEND_CACHE_DIR . "/blocklist.cache";
        list($exact, $cidr) = self::parse_cache($file);

        if (isset($exact[$ip])) return true;

        foreach ($cidr as $range) {
            if (self::ip_in_range($ip, $range)) return true;
        }

        return false;
    }

    private static function check_rate_limit(string $ip): bool {

        $limit = 100;
        $window = 60;

        $dir = BOTFEND_CACHE_DIR . "/ratelimit";
        if (!is_dir($dir)) return false;

        $file = $dir . "/" . md5($ip) . ".cache";
        $now = time();
        $window_start = $now - $window;

        $requests = [];

        if (file_exists($file)) {
            $data = @file_get_contents($file);
            $requests = json_decode($data, true) ?: [];
        }

        $requests = array_filter($requests, fn($t) => $t > $window_start);
        $requests[] = $now;

        @file_put_contents($file, json_encode($requests), LOCK_EX);

        return count($requests) > $limit;
    }

    private static function ip_in_range(string $ip, string $cidr): bool {

        if (strpos($cidr, "/") === false) return false;

        list($subnet, $mask) = explode("/", $cidr);
        $mask = (int)$mask;

        // IPv4
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            if ($mask < 0 || $mask > 32) return false;
            $ip_long = @ip2long($ip);
            $subnet_long = @ip2long($subnet);
            if ($ip_long === false || $subnet_long === false) return false;
            $mask_long = ~((1 << (32 - $mask)) - 1);
            return ($ip_long & $mask_long) === ($subnet_long & $mask_long);
        }

        // IPv6
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            if ($mask < 0 || $mask > 128) return false;
            $ip_bin = @inet_pton($ip);
            $subnet_bin = @inet_pton($subnet);
            if ($ip_bin === false || $subnet_bin === false) return false;
            $bytes_to_check = (int)($mask / 8);
            $bits_remaining = $mask % 8;
            for ($i = 0; $i < $bytes_to_check; $i++) {
                if ($ip_bin[$i] !== $subnet_bin[$i]) return false;
            }
            if ($bits_remaining > 0) {
                $mask_byte = ~((1 << (8 - $bits_remaining)) - 1) & 0xFF;
                if ((ord($ip_bin[$bytes_to_check]) & $mask_byte) !== (ord($subnet_bin[$bytes_to_check]) & $mask_byte)) return false;
            }
            return true;
        }

        return false;
    }

    private static function render_block_page(string $ip, string $reason): void {

        if (headers_sent()) return;

        http_response_code(403);

        header("Content-Type: text/html; charset=utf-8");
        header("Cache-Control: no-store, no-cache, must-revalidate");
        header("X-Frame-Options: DENY");
        header("X-Content-Type-Options: nosniff");
        header("Referrer-Policy: no-referrer");

        echo \'<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<title>Access Denied - BotFend Anti-Bot Firewall</title>
<link rel="stylesheet" href="' . $css_url . '">
</head>
<body>
<div class="box">
<div class="icon">&#128737;</div>
<h2>Access Denied</h2>
<p>Your request has been blocked by our security firewall.</p>
<div class="info-row">
<b>IP:</b><code>' . htmlspecialchars($ip, ENT_QUOTES) . '</code>
</div>
<div class="info-row">
<b>Reason:</b><code>' . htmlspecialchars($reason, ENT_QUOTES) . '</code>
</div>
<p class="footer">Protected by BotFend Anti-Bot Firewall</p>
</div>
</body>
</html>\';
    }
}

BotfendEarlyFirewall::init();
' . $include_existing;
}


    private function configure_user_ini() {
        $user_ini_file = ABSPATH . '.user.ini';
        $bootstrap_realpath = realpath($this->bootstrap_file);
        if (!$bootstrap_realpath) {
            $bootstrap_realpath = wp_normalize_path($this->bootstrap_file);
        }
        $directive = 'auto_prepend_file = "' . addslashes($bootstrap_realpath) . '"';
        if (!is_writable(ABSPATH) && (file_exists($user_ini_file) && !is_writable($user_ini_file))) {
            return [
                'success' => false,
                'message' => esc_html__('.user.ini file or WordPress root directory is not writable. Manual configuration required.', 'botfend-anti-bot-firewall'),
                'method' => 'manual',
                'instructions' => $this->get_manual_instructions('user_ini'),
            ];
        }
        $current_content = file_exists($user_ini_file) ? file_get_contents($user_ini_file) : '';
        $current_content = preg_replace('/^; BotFend Anti-Bot Firewall.*$/m', '', $current_content);
        $current_content = preg_replace('/^auto_prepend_file\s*=.*$/m', '', $current_content);
        $current_content = trim($current_content);
        $new_content = $current_content . "\n; BotFend Anti-Bot Firewall\n" . $directive . "\n";
        $result = file_put_contents($user_ini_file, $new_content, LOCK_EX);
        if (false === $result) {
            return [
                'success' => false,
                'message' => esc_html__('Could not write to .user.ini file.', 'botfend-anti-bot-firewall'),
                'method' => 'manual',
                'instructions' => $this->get_manual_instructions('user_ini'),
            ];
        }
        if (function_exists('opcache_invalidate')) {
            opcache_invalidate($user_ini_file, true);
        }
        set_transient('botfend_firewall_pending', true, 5 * MINUTE_IN_SECONDS);
        return [
            'success' => true,
            'message' => esc_html__('Firewall configured via .user.ini. Changes may take up to 5 minutes to apply.', 'botfend-anti-bot-firewall'),
        ];
    }

    private function configure_htaccess() {
        $htaccess_file = ABSPATH . '.htaccess';
        if (file_exists($htaccess_file) && !is_writable($htaccess_file)) {
            return [
                'success' => false,
                'message' => esc_html__('.htaccess file is not writable. Manual configuration required.', 'botfend-anti-bot-firewall'),
                'method' => 'manual',
                'instructions' => $this->get_manual_instructions('htaccess'),
            ];
        }
        if (!file_exists($htaccess_file) && !is_writable(ABSPATH)) {
            return [
                'success' => false,
                'message' => esc_html__('WordPress root directory is not writable. Cannot create .htaccess.', 'botfend-anti-bot-firewall'),
                'method' => 'manual',
                'instructions' => $this->get_manual_instructions('htaccess'),
            ];
        }
        $directive = 'php_value auto_prepend_file "' . $this->bootstrap_file . '"';
        $marker_start = '# BotFend Firewall - DO NOT EDIT';
        $marker_end = '# End BotFend Firewall';
        $block = $marker_start . "\n<IfModule mod_php7.c>\n" . $directive . "\n</IfModule>\n<IfModule mod_php.c>\n" . $directive . "\n</IfModule>\n" . $marker_end . "\n";
        $current_content = file_exists($htaccess_file) ? file_get_contents($htaccess_file) : '';
        $pattern = '/# BotFend Firewall.*?# End BotFend Firewall\n/s';
        $current_content = preg_replace($pattern, '', $current_content);
        if (preg_match('/RewriteEngine\s+On/i', $current_content)) {
            $current_content = preg_replace('/(RewriteEngine\s+On\s*\n)/i', "$1\n" . $block, $current_content);
        } else {
            $current_content = $block . $current_content;
        }
        $result = file_put_contents($htaccess_file, $current_content, LOCK_EX);
        if (false === $result) {
            return [
                'success' => false,
                'message' => esc_html__('Could not write to .htaccess file.', 'botfend-anti-bot-firewall'),
                'method' => 'manual',
                'instructions' => $this->get_manual_instructions('htaccess'),
            ];
        }
        return [
            'success' => true,
            'message' => esc_html__('Firewall configured via .htaccess.', 'botfend-anti-bot-firewall'),
        ];
    }

    public function disable($delete_files = false) {
        $errors = [];
        $user_ini_file = ABSPATH . '.user.ini';
        if (file_exists($user_ini_file) && is_writable($user_ini_file)) {
            $content = file_get_contents($user_ini_file);
            $content = preg_replace('/^; BotFend Anti-Bot Firewall.*$/m', '', $content);
            $content = preg_replace('/^auto_prepend_file\s*=.*$/m', '', $content);
            $content = preg_replace("/\n{3,}/", "\n\n", trim($content));
            if (false === file_put_contents($user_ini_file, $content)) {
                $errors[] = esc_html__('Could not update .user.ini.', 'botfend-anti-bot-firewall');
            }
        } elseif (file_exists($user_ini_file)) {
            $errors[] = esc_html__('.user.ini is not writable. Please remove the auto_prepend_file line manually.', 'botfend-anti-bot-firewall');
        }
        $htaccess_file = ABSPATH . '.htaccess';
        if (file_exists($htaccess_file) && is_writable($htaccess_file)) {
            $content = file_get_contents($htaccess_file);
            $pattern = '/# BotFend Firewall.*?# End BotFend Firewall\n/s';
            $content = preg_replace($pattern, '', $content);
            if (false === file_put_contents($htaccess_file, $content)) {
                $errors[] = esc_html__('Could not update .htaccess.', 'botfend-anti-bot-firewall');
            }
        } elseif (file_exists($htaccess_file)) {
            $errors[] = esc_html__('.htaccess is not writable. Please remove the BotFend block manually.', 'botfend-anti-bot-firewall');
        }
        if ($delete_files) {
            if (file_exists($this->bootstrap_file)) {
                @unlink($this->bootstrap_file);
            }
            if (is_dir($this->firewall_dir)) {
                $this->recursive_rmdir($this->firewall_dir);
            }
        }
        delete_transient('botfend_firewall_pending');
        if (!empty($errors)) {
            return ['success' => false, 'message' => implode(' ', $errors)];
        }
        return [
            'success' => true,
            'message' => esc_html__('Firewall disabled.', 'botfend-anti-bot-firewall') . ($delete_files ? ' ' . esc_html__('Firewall files removed.', 'botfend-anti-bot-firewall') : ''),
        ];
    }

    public function enable_basic_protection() {
        $mu_plugin_dir = WPMU_PLUGIN_DIR;
        $mu_plugin_file = $mu_plugin_dir . '/0-botfend-anti-bot-firewall.php';
        $wp_content_dir = dirname($mu_plugin_dir);
        if (!is_writable($wp_content_dir)) {
            return [
                'success' => false,
                'message' => sprintf(esc_html__('Cannot create MU-plugins directory. %s is not writable.', 'botfend-anti-bot-firewall'), $wp_content_dir),
            ];
        }
        if (!file_exists($mu_plugin_dir)) {
            if (!wp_mkdir_p($mu_plugin_dir)) {
                return [
                    'success' => false,
                    'message' => esc_html__('Could not create MU-plugins directory. Check permissions.', 'botfend-anti-bot-firewall'),
                ];
            }
            @chmod($mu_plugin_dir, 0755);
        }
        if (file_exists($mu_plugin_file) && !is_writable($mu_plugin_file)) {
            return [
                'success' => false,
                'message' => esc_html__('MU-plugin file exists but is not writable. Please delete it manually via FTP.', 'botfend-anti-bot-firewall'),
            ];
        }
        $content = '<?php
/**
 * Plugin Name: BotFend Anti-Bot Firewall (Auto-generated)
 * Description: Loads BotFend before other plugins (Basic Protection)
 * Version: 1.0
 */

define( "BOTFEND_EARLY_LOAD", true );

$plugin_file = WP_PLUGIN_DIR . "/botfend-anti-bot-firewall/botfend.php";
if ( file_exists( $plugin_file ) ) {
    require_once $plugin_file;
}
';
        $result = file_put_contents($mu_plugin_file, $content, LOCK_EX);
        if (false === $result) {
            return [
                'success' => false,
                'message' => esc_html__('Could not write MU-plugin file. Check file permissions.', 'botfend-anti-bot-firewall'),
            ];
        }
        @chmod($mu_plugin_file, 0644);
        return [
            'success' => true,
            'message' => esc_html__('Basic Protection enabled.', 'botfend-anti-bot-firewall'),
        ];
    }

    public function disable_basic_protection() {
        $mu_plugin_file = WPMU_PLUGIN_DIR . '/0-botfend-anti-bot-firewall.php';
        if (!file_exists($mu_plugin_file)) {
            return [
                'success' => true,
                'message' => esc_html__('Basic Protection already disabled.', 'botfend-anti-bot-firewall'),
            ];
        }
        if (!is_writable($mu_plugin_file) && !is_writable(dirname($mu_plugin_file))) {
            $disabled_file = $mu_plugin_file . '.disabled';
            if (!rename($mu_plugin_file, $disabled_file)) {
                return [
                    'success' => false,
                    'message' => sprintf(esc_html__('Cannot delete or rename MU-plugin file. Please remove %s manually via FTP.', 'botfend-anti-bot-firewall'), $mu_plugin_file),
                ];
            }
            return [
                'success' => true,
                'message' => esc_html__('Basic Protection disabled (file renamed).', 'botfend-anti-bot-firewall'),
            ];
        }
        if (!unlink($mu_plugin_file)) {
            return [
                'success' => false,
                'message' => esc_html__('Could not remove MU-plugin file.', 'botfend-anti-bot-firewall'),
            ];
        }
        return [
            'success' => true,
            'message' => esc_html__('Basic Protection disabled.', 'botfend-anti-bot-firewall'),
        ];
    }

    public function get_manual_instructions($method = '') {
        if (empty($method)) {
            $method = $this->get_recommended_method();
        }
        $bootstrap_path = $this->bootstrap_file;
        switch ($method) {
            case 'user_ini':
                $directive = 'auto_prepend_file = "' . $bootstrap_path . '"';
                return sprintf('<p>%s</p><pre>%s</pre><p>%s</p>',
                    esc_html__('Add the following line to your .user.ini file:', 'botfend-anti-bot-firewall'),
                    esc_html($directive),
                    esc_html__('The .user.ini file is located in your WordPress root directory.', 'botfend-anti-bot-firewall')
                );
            case 'htaccess':
                $directive = 'php_value auto_prepend_file "' . $bootstrap_path . '"';
                return sprintf('<p>%s</p><pre>&lt;IfModule mod_php7.c&gt;<br>%s<br>&lt;/IfModule&gt;<br>&lt;IfModule mod_php.c&gt;<br>%s<br>&lt;/IfModule&gt;</pre>',
                    esc_html__('Add the following to your .htaccess file:', 'botfend-anti-bot-firewall'),
                    esc_html($directive), esc_html($directive)
                );
            case 'php_ini':
                return sprintf('<p>%s</p><pre>auto_prepend_file = "%s"</pre>',
                    esc_html__('Add the following line to your php.ini file:', 'botfend-anti-bot-firewall'),
                    esc_html($bootstrap_path)
                );
            default:
                return sprintf('<p>%s</p><pre>auto_prepend_file = "%s"</pre>',
                    esc_html__('Configure the following PHP directive:', 'botfend-anti-bot-firewall'),
                    esc_html($bootstrap_path)
                );
        }
    }

    public function clear_ratelimit_cache() {
        $ratelimit_dir = $this->firewall_dir . '/cache/ratelimit';
        if (!is_dir($ratelimit_dir)) return true;
        $files = glob($ratelimit_dir . '/*.cache');
        if (is_array($files)) {
            foreach ($files as $file) {
                if (is_file($file)) unlink($file);
            }
        }
        return true;
    }

    private function normalize_path($path) {
        if (function_exists('realpath')) {
            $real = realpath($path);
            if ($real) $path = $real;
        }
        return strtolower(str_replace('\\', '/', $path));
    }

    private function recursive_rmdir($dir) {
        if (!is_dir($dir)) return false;
        $files = array_diff(scandir($dir), array('.', '..'));
        foreach ($files as $file) {
            $path = $dir . '/' . $file;
            is_dir($path) ? $this->recursive_rmdir($path) : unlink($path);
        }
        return rmdir($dir);
    }
}