<?php
/**
 * Plugin Activator for BotFend Anti-Bot Firewall
 *
 * @package BotFend\Core
 */

namespace BotFend\Core;

use BotFend\Database\Database;
use BotFend\Security\ConnectionFingerprint;
use BotFend\Utilities\Utilities;

defined('ABSPATH') || exit;

class Activator {

    public function activate(): void {
        try {
            $this->check_requirements();
            $this->create_tables();
            $this->set_default_options();
            $this->schedule_cron_jobs();
            $this->setup_firewall_environment();
            $this->clear_caches();
            $this->log_activation();
            do_action('botfend_defender_activated');
        } catch (\Throwable $e) {
            $this->handle_activation_failure($e);
        }
    }

    private function check_requirements(): void {
        global $wp_version;
        $errors = [];
        if (version_compare(PHP_VERSION, '8.0', '<')) {
            $errors[] = sprintf(esc_html__('PHP 8.0+ required (Running %s)', 'botfend-anti-bot-firewall'), PHP_VERSION);
        }
        if (version_compare($wp_version, '6.9', '<')) {
            $errors[] = sprintf(esc_html__('WordPress 6.9+ required (Running %s)', 'botfend-anti-bot-firewall'), $wp_version);
        }
        $required_extensions = ['json', 'mysqli', 'pcre'];
        foreach ($required_extensions as $ext) {
            if (!extension_loaded($ext)) {
                $errors[] = sprintf(esc_html__('Missing PHP extension: %s', 'botfend-anti-bot-firewall'), $ext);
            }
        }
        if (!empty($errors)) {
            throw new \Exception(implode(' | ', $errors));
        }
    }

    private function create_tables(): void {
        $database = $this->get_database_instance();
        if ($database) {
            $database->create_tables();
        }
        $this->create_fingerprint_table();
        $this->create_file_guard_protection();
    }

    private function get_database_instance() {
        if (class_exists('BotFend\Database\Database')) {
            return new Database();
        }
        return null;
    }

    private function get_utilities_instance() {
        if (class_exists('BotFend\Utilities\Utilities')) {
            return new Utilities();
        }
        return null;
    }

    private function create_fingerprint_table(): void {
        if (!class_exists('BotFend\Security\ConnectionFingerprint')) return;
        $database = $this->get_database_instance();
        $utilities = $this->get_utilities_instance();
        if ($database && $utilities) {
            try {
                $fingerprint = new ConnectionFingerprint($utilities, $database);
                if (method_exists($fingerprint, 'create_fingerprint_table')) {
                    $fingerprint->create_fingerprint_table();
                    return;
                }
            } catch (\Throwable $e) {
                error_log('BotFend: Failed to create fingerprint table: ' . $e->getMessage());
            }
        }
        if (method_exists(ConnectionFingerprint::class, 'create_fingerprint_table')) {
            ConnectionFingerprint::create_fingerprint_table();
        }
    }

    private function create_file_guard_protection(): void {
        $config = Config::get_instance();
        if (!$config->get_bool('protect_uploads', false)) return;
        $logger = null;
        $database = $this->get_database_instance();
        $utilities = $this->get_utilities_instance();
        if (class_exists('BotFend\Logging\Logger') && $database) {
            $logger = new \BotFend\Logging\Logger($database);
        }
        if ($logger && $database && class_exists('BotFend\Security\FileGuard') && class_exists('BotFend\Core\Core')) {
            $core = new \BotFend\Core\Core($utilities, $database);
            $file_guard = new \BotFend\Security\FileGuard($logger, $core);
            if (method_exists($file_guard, 'secure_uploads_directory')) {
                $file_guard->secure_uploads_directory();
            }
        }
    }

    private function setup_firewall_environment(): void {
        if (!class_exists('BotFend\Core\FirewallSetup')) {
            $firewall_file = BOTFEND_PATH . 'includes/core/FirewallSetup.php';
            if (file_exists($firewall_file)) {
                require_once $firewall_file;
            } else {
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    error_log('BotFend: FirewallSetup.php not found - early firewall unavailable');
                }
                return;
            }
        }
        if (!class_exists('BotFend\Core\FirewallSetup')) return;
        try {
            $config = Config::get_instance();
            $utilities = $this->get_utilities_instance() ?: new Utilities();
            $firewall_setup = new \BotFend\Core\FirewallSetup($config, $utilities);
            $database = $this->get_database_instance();
            if ($database) {
                $firewall_setup->set_database($database);
            }
            $dir_result = $firewall_setup->create_firewall_directory();
            if (!$dir_result['success']) {
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    error_log('BotFend: Firewall directory creation failed - ' . $dir_result['message']);
                }
                return;
            }
            $firewall_setup->sync_cache_files();
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log('BotFend: Firewall environment setup complete');
            }
        } catch (\Throwable $e) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log('BotFend: Firewall setup error - ' . $e->getMessage());
            }
        }
    }

    private function set_default_options(): void {
        $config = Config::get_instance();
        if (method_exists($config, 'migrate_all')) {
            $config->migrate_all();
        }
        $definitions = $config->get_definitions();
        foreach ($definitions as $option_key => $definition) {
            if (false === get_option($option_key)) {
                $default = $definition['default'] ?? null;
                if (null === $default && $option_key === 'botfend_session_secure_cookie') {
                    $default = is_ssl();
                }
                $autoload = $definition['autoload'] ?? true;
                add_option($option_key, $default, '', $autoload ? 'yes' : 'no');
            }
        }
        update_option('botfend_version', BOTFEND_VERSION);
        if (false === get_option('botfend_activation_time')) {
            add_option('botfend_activation_time', time(), '', 'no');
        }
        if (false === get_option('botfend_whitelisted_paths')) {
            $default_paths = "/.well-known/traffic-advice\n/.well-known/security.txt\n/.well-known/assetlinks.json\n/.well-known/apple-app-site-association\n/.well-known/dnt-policy.txt\n/.well-known/pki-validation/\n/robots.txt\n/favicon.ico\n/sitemap.xml\n/sitemap_index.xml\n/humans.txt\n/ads.txt";
            add_option('botfend_whitelisted_paths', $default_paths, '', 'yes');
        }
        if (false === get_option('botfend_honeypot_urls')) {
            $default_honeypots = "/wp-admin.bak\n/wp-login.php.bak\n/license.txt\n/readme.html\n/xmlrpc.php.bak\n/admin.php\n/administrator/index.php\n/wp-content/uploads/.htaccess.bak\n/.env\n/config.php.bak\n/phpinfo.php\n/test.php";
            add_option('botfend_honeypot_urls', $default_honeypots, '', 'yes');
        }
    }

    private function schedule_cron_jobs(): void {
        $schedules = [
            'botfend_daily_maintenance' => 'daily',
            'botfend_update_threat_intel' => 'twicedaily',
            'botfend_update_tor_nodes' => 'daily',
            'botfend_auto_unblock' => 'hourly',
            'botfend_file_guard_weekly' => 'weekly',
            'botfend_cleanup_transients' => 'hourly',
            'botfend_calculate_enhanced_attack_level' => 'five_minutes',
        ];
        if (!wp_next_scheduled('botfend_calculate_enhanced_attack_level')) {
            wp_schedule_event(time(), 'five_minutes', 'botfend_calculate_enhanced_attack_level');
        }
        foreach ($schedules as $hook => $interval) {
            if (!wp_next_scheduled($hook)) {
                wp_schedule_event(time(), $interval, $hook);
            }
        }
        if (!wp_next_scheduled('botfend_import_tor_nodes')) {
            wp_schedule_single_event(time() + 30, 'botfend_import_tor_nodes');
        }
        if (!wp_next_scheduled('botfend_preload_threat_feeds')) {
            wp_schedule_single_event(time() + 60, 'botfend_preload_threat_feeds');
        }
    }

    private function clear_caches(): void {
        global $wpdb;
        $like_botfend = $wpdb->esc_like('_transient_botfend_') . '%';
        $like_timeout = $wpdb->esc_like('_transient_timeout_botfend_') . '%';
        $wpdb->query($wpdb->prepare(
            "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
            $like_botfend, $like_timeout
        ));
        $cache_groups = ['botfend_defender', 'botfend_admin', 'botfend_config', 'botfend_sessions'];
        foreach ($cache_groups as $group) {
            if (function_exists('wp_cache_flush_group')) {
                wp_cache_flush_group($group);
            }
        }
        $config = Config::get_instance();
        if (method_exists($config, 'clear_cache')) {
            $config->clear_cache();
        }
    }

    private function handle_activation_failure(\Throwable $e): void {
        error_log('BotFend Activation Error: ' . $e->getMessage());
        $error_message = sprintf(esc_html__('BotFend Anti-Bot Firewall could not be activated. Error: %s', 'botfend-anti-bot-firewall'), esc_html($e->getMessage()));
        wp_die(esc_html($error_message), esc_html__('Plugin Activation Error', 'botfend-anti-bot-firewall'), ['back_link' => true]);
    }

    private function log_activation(): void {
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log(sprintf('BotFend v%s Activated successfully at %s', BOTFEND_VERSION, current_time('mysql')));
        }
    }

    public static function get_plugin_version(): string {
        return defined('BOTFEND_VERSION') ? BOTFEND_VERSION : '1.0.0';
    }

    public static function was_just_activated(): bool {
        return get_transient('botfend_just_activated') === 'yes';
    }

    public static function mark_just_activated(): void {
        set_transient('botfend_just_activated', 'yes', 60);
    }

    public static function clear_just_activated(): void {
        delete_transient('botfend_just_activated');
    }
}