<?php
/**
 * Bootstrap class for BotFend Anti-Bot Firewall
 *
 * @package BotFend\Core
 * @version 4.9.0 - Added license system and Cloudflare Pro integration
 */

namespace BotFend\Core;

use BotFend\Utilities\Utilities;
use BotFend\Database\Database;
use BotFend\Logging\Logger;
use BotFend\Security\WAF;
use BotFend\Security\WordPressProtection;
use BotFend\Security\BehavioralAnalyzer;
use BotFend\Security\ConnectionFingerprint;
use BotFend\Security\IntelligentSession;
use BotFend\Security\TorSystem;
use BotFend\Security\Advanced404;
use BotFend\Security\FileGuard;
use BotFend\Detection\ThreatIntel;
use BotFend\Detection\Signatures;
use BotFend\Adaptive\Adaptive;
use BotFend\Challenges\Challenges;
use BotFend\ThirdParty\IPHub;
use BotFend\ThirdParty\AbuseIPDB;
use BotFend\ThirdParty\Recaptcha;
use BotFend\Cloudflare\CloudflareIntegration;
use BotFend\Admin\AdminCoreManager;
use BotFend\License\LicenseKey;

defined('ABSPATH') || exit;

class Bootstrap {

    private static $instance = null;
    private $components = [];
    private $initialized = false;
    private $missing_components = [];
    private $benchmarks = [];
    private $license = null;

    private function __construct() {}

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

    public function init(): void {
        if ($this->initialized) {
            return;
        }
        $this->start_benchmark('total_init');
        try {
            $this->components['config'] = Config::get_instance();
            
            // Initialize license system FIRST before any Pro features
            $this->init_license_system();
            
            $this->init_core_infrastructure();
            $this->init_enabled_features();
            
            if (is_admin() && !wp_doing_cron()) {
                $this->init_admin();
            }
            
            $this->register_hooks();
            $GLOBALS['botfend_bootstrap'] = $this;
            $this->initialized = true;
            $this->stop_benchmark('total_init');
            
            do_action('botfend_defender_bootstrap_init', $this);
            
            if (defined('WP_DEBUG') && WP_DEBUG && $this->components['config']->get_bool('debug_mode', false)) {
                error_log('BotFend: Bootstrap initialized successfully');
                if ($this->license && $this->license->is_valid()) {
                    error_log('BotFend: Pro license active');
                }
            }
        } catch (\Throwable $e) {
            $this->handle_init_error($e);
        }
    }
    
    /**
     * Initialize license system
     *
     * @since 4.9.0
     */
    private function init_license_system(): void {
        try {
            $this->license = LicenseKey::get_instance();
            
            // Store license status for global access
            if (!defined('BOTFEND_IS_PRO')) {
                define('BOTFEND_IS_PRO', $this->license->is_valid());
            }
            
            // Log expiration warning if less than 7 days left
            if ($this->license->is_valid() && $this->license->days_remaining() <= 7 && $this->license->days_remaining() > 0) {
                add_action('admin_notices', [$this, 'show_license_expiry_notice']);
            }
        } catch (\Throwable $e) {
            error_log('BotFend: License system initialization failed - ' . $e->getMessage());
            define('BOTFEND_IS_PRO', false);
        }
    }
    
    /**
     * Show license expiry warning notice
     *
     * @since 4.9.0
     */
    public function show_license_expiry_notice(): void {
        if (!current_user_can('manage_options')) {
            return;
        }
        
        $days_left = $this->license->days_remaining();
        ?>
        <div class="notice notice-warning is-dismissible">
            <p>
                <strong><?php echo esc_html__('BotFend Pro License Notice:', 'botfend-anti-bot-firewall'); ?></strong>
                <?php echo sprintf(
                    esc_html__('Your license expires in %d days. Renew now to continue receiving updates and Pro features.', 'botfend-anti-bot-firewall'),
                    $days_left
                ); ?>
                <a href="<?php echo esc_url(admin_url('admin.php?page=botfend-license')); ?>">
                    <?php echo esc_html__('Manage License', 'botfend-anti-bot-firewall'); ?>
                </a>
            </p>
        </div>
        <?php
    }

    private function init_core_infrastructure(): void {
        $this->start_benchmark('core_infra');
        $this->components['utilities'] = new Utilities();
        $this->components['database'] = new Database();
        $this->upgrade_database_schema();
        $this->components['logger'] = new Logger($this->components['database']);
        $this->stop_benchmark('core_infra');
    }

    /**
     * Upgrade database schema to latest version
     *
     * @since 4.8.3
     * @return void
     */
    private function upgrade_database_schema(): void {
        try {
            $database = $this->components['database'];
            $database->create_tables();

            $upgraded = $database->maybe_upgrade_database();

            if ($upgraded && defined('WP_DEBUG') && WP_DEBUG) {
                if (isset($this->components['config']) && $this->components['config']->get_bool('debug_mode', false)) {
                    error_log('BotFend: Database schema upgraded to version ' . Database::DB_VERSION);
                }
            }

            $GLOBALS['botfend_database'] = $database;

        } catch (\Throwable $e) {
            error_log('BotFend: Database upgrade failed - ' . $e->getMessage());

            if (defined('WP_DEBUG') && WP_DEBUG) {
                add_action('admin_notices', function() use ($e) {
                    echo '<div class="notice notice-warning"><p>';
                    echo '<strong>' . esc_html__('BotFend Database Notice:', 'botfend-anti-bot-firewall') . '</strong> ';
                    echo esc_html($e->getMessage());
                    echo '</p></div>';
                });
            }
        }
    }

    private function init_enabled_features(): void {
        $config = $this->components['config'];
        $this->start_benchmark('enabled_features');

        // ============================================
        // CORE SECURITY FEATURES - Enabled by default
        // ============================================
        
        if ($config->get_bool('enable_waf', true)) {
            $this->create_component('BotFend\Security\WAF', [$this->components['utilities'], $this->components['database']], 'waf');
        }
        if ($config->get_bool('enable_wp_protection', true)) {
            $this->create_component('BotFend\Security\WordPressProtection', [$this->components['utilities'], $this->components['database']], 'wp_protection');
        }
        if ($config->get_bool('enable_behavioral_analysis', true)) {
            $this->create_component('BotFend\Security\BehavioralAnalyzer', [$this->components['utilities'], $this->components['database']], 'behavioral_analyzer');
        }
        if ($config->get_bool('enable_adaptive', true)) {
            $this->components['adaptive'] = new Adaptive();
        }
        if ($config->get_bool('enable_signatures', true)) {
            $this->create_component('BotFend\Detection\Signatures', [$this->components['database']], 'signatures');
        }
        if ($config->get_bool('enable_advanced_404', true)) {
            $this->create_component('BotFend\Security\Advanced404', [$this->components['utilities'], $this->components['database']], 'advanced_404');
        }
        if ($config->get_bool('enable_connection_fp', true)) {
            $this->create_component('BotFend\Security\ConnectionFingerprint', [$this->components['utilities'], $this->components['database']], 'connection_fp');
        }
        if ($config->get_bool('enable_intelligent_session', true)) {
            $this->create_component('BotFend\Security\IntelligentSession', [$this->components['utilities'], $this->components['database']], 'intelligent_session');
        }
        if ($config->get_bool('enable_js_challenge', true)) {
            $this->create_component('BotFend\Challenges\Challenges', [$this->components['utilities'], $this->components['database']], 'challenges');
        }

        // ============================================
        // EXTERNAL SERVICES - DISABLED BY DEFAULT (Opt-in)
        // ============================================

        // Threat intelligence - external feeds (disabled by default)
        if ($config->get_bool('enable_threat_intel', false)) {
            $this->components['threat_intel'] = ThreatIntel::get_instance();
        }

        // TOR detection - requires external list download (disabled by default)
        if ($config->get_bool('enable_tor_detection', false)) {
            $this->create_component('BotFend\Security\TorSystem', [$this->components['database']], 'tor_system');
        }

        // IPHub - external API (disabled by default, also requires Pro license)
        if ($config->get_bool('enable_iphub', false) && $this->is_pro_feature_allowed('geolocation')) {
            $this->create_component('BotFend\ThirdParty\IPHub', [$this->components['utilities']], 'iphub');
        }

        // AbuseIPDB - external API (disabled by default, also requires Pro license)
        if ($config->get_bool('enable_abuseipdb', false) && $this->is_pro_feature_allowed('threat_intel')) {
            $this->create_component('BotFend\ThirdParty\AbuseIPDB', [$this->components['database']], 'abuseipdb');
        }

        // reCAPTCHA - external Google service (disabled by default)
        if ($config->get_bool('enable_recaptcha', false)) {
            $this->create_component('BotFend\ThirdParty\Recaptcha', [], 'recaptcha');
        }

        // ============================================
        // CLOUDFLARE INTEGRATION - PRO FEATURE
        // Requires valid Pro license with cloudflare feature
        // ============================================
        
        if ($config->get_bool('cf_enabled', false) && $this->is_pro_feature_allowed('cloudflare')) {
            if (class_exists('BotFend\Cloudflare\CloudflareIntegration')) {
                $this->components['cloudflare'] = CloudflareIntegration::get_instance();
                if (defined('WP_DEBUG') && WP_DEBUG && $config->get_bool('debug_mode', false)) {
                    error_log('BotFend: Cloudflare Integration initialized (Pro feature)');
                }
            } else {
                $this->missing_components[] = 'BotFend\Cloudflare\CloudflareIntegration';
            }
        }

        // ============================================
        // FILE PROTECTION - Disabled by default (invasive)
        // ============================================
        
        $file_protection_enabled = (
            $config->get_bool('protect_uploads', false) ||
            $config->get_bool('scan_uploads', false) ||
            $config->get_bool('monitor_permissions', false)
        );
        if ($file_protection_enabled) {
            $this->create_component('BotFend\Security\FileGuard', [$this->components['logger'], $this->get_core()], 'file_guard');
        }

        // Detection component
        if (class_exists('BotFend\Detection\Detection')) {
            $this->components['detection'] = new \BotFend\Detection\Detection($this->components['utilities'], $this->components['database']);
        }

        // Firewall setup (admin only)
        if (is_admin() && class_exists('BotFend\Core\FirewallSetup')) {
            $firewall_setup = $this->create_component('BotFend\Core\FirewallSetup', [$this->components['config'], $this->components['utilities']], 'firewall_setup');
            if ($firewall_setup && isset($this->components['database'])) {
                $firewall_setup->set_database($this->components['database']);
            }
        }

        $this->stop_benchmark('enabled_features');
    }
    
    /**
     * Check if a Pro feature is allowed by license
     *
     * @since 4.9.0
     * @param string $feature Feature name
     * @return bool
     */
    private function is_pro_feature_allowed(string $feature): bool {
        if (!$this->license) {
            return false;
        }
        return $this->license->has_feature($feature);
    }

    private function create_component(string $class, array $args = [], string $key = ''): ?object {
        if (class_exists($class)) {
            try {
                $instance = new $class(...$args);
                $component_key = $key ?: $class;
                $this->components[$component_key] = $instance;
                return $instance;
            } catch (\Throwable $e) {
                $this->missing_components[] = $class;
                if (defined('WP_DEBUG') && WP_DEBUG && isset($this->components['config']) && $this->components['config']->get_bool('debug_mode', false)) {
                    error_log("BotFend: Failed to load {$class}: " . $e->getMessage());
                }
            }
        } else {
            $this->missing_components[] = $class;
        }
        return null;
    }

    private function init_admin(): void {
        $this->start_benchmark('admin_init');
        $this->components['admin_core'] = new AdminCoreManager($this->get_core());
        $this->stop_benchmark('admin_init');
    }

    private function get_core(): Core {
        if (!isset($this->components['core'])) {
            $this->components['core'] = new Core(
                $this->components['utilities'],
                $this->components['database'],
                $this->components['detection'] ?? null,
                $this->components['iphub'] ?? null,
                $this->components['abuseipdb'] ?? null
            );
            $this->components['core']->set_components(
                $this->components['challenges'] ?? null,
                $this->components['adaptive'] ?? null,
                $this->components['threat_intel'] ?? null,
                $this->components['signatures'] ?? null,
                $this->components['tor_system'] ?? null,
                $this->components['advanced_404'] ?? null,
                $this->components['connection_fp'] ?? null,
                $this->components['intelligent_session'] ?? null,
                $this->components['behavioral_analyzer'] ?? null,
                $this->components['waf'] ?? null,
                $this->components['wp_protection'] ?? null,
                $this->components['logger'] ?? null,
                $this->components['cloudflare'] ?? null
            );
        }
        return $this->components['core'];
    }

    private function register_hooks(): void {
        $config = $this->components['config'];
        add_filter('cron_schedules', [$this, 'add_cron_schedules']);
        add_action('init', [$this, 'schedule_core_cron_jobs']);
        
        if ($config->get_bool('enabled', true)) {
            add_action('init', [$this->get_core(), 'check_visitor'], 2);
        }
        
        add_action('admin_notices', [$this, 'show_admin_notices']);
        add_action('wp_ajax_botfend_dismiss_notice', [$this, 'handle_ajax_dismiss_notice']);
        add_action('wp_ajax_botfend_protect_uploads', [$this, 'handle_ajax_protect_uploads']);
        add_action('wp_ajax_botfend_check_permissions', [$this, 'handle_ajax_check_permissions']);
        add_action('shutdown', [$this, 'cleanup']);
    }

    public function add_cron_schedules(array $schedules): array {
        $schedules['five_minutes'] = [
            'interval' => 300,
            'display' => esc_html__('Every 5 minutes', 'botfend-anti-bot-firewall')
        ];
        $schedules['twicedaily'] = [
            'interval' => 12 * HOUR_IN_SECONDS,
            'display' => esc_html__('Twice Daily', 'botfend-anti-bot-firewall')
        ];
        $schedules['weekly'] = [
            'interval' => WEEK_IN_SECONDS,
            'display' => esc_html__('Once Weekly', 'botfend-anti-bot-firewall')
        ];
        return $schedules;
    }

    public function schedule_core_cron_jobs(): void {
        $config = $this->components['config'];

        $core_schedules = [
            'botfend_daily_maintenance' => 'daily',
            'botfend_auto_unblock' => 'hourly',
            'botfend_cleanup_transients' => 'hourly',
        ];
        foreach ($core_schedules as $hook => $interval) {
            if (!wp_next_scheduled($hook)) {
                wp_schedule_event(time(), $interval, $hook);
            }
        }

        if ($config->get_bool('enable_adaptive', true)) {
            if (!wp_next_scheduled('botfend_calculate_enhanced_attack_level')) {
                wp_schedule_event(time(), 'five_minutes', 'botfend_calculate_enhanced_attack_level');
            }
        }

        // ============================================
        // EXTERNAL SERVICE CRON JOBS - DISABLED BY DEFAULT
        // ============================================

        if ($config->get_bool('enable_threat_intel', false) && $this->is_pro_feature_allowed('threat_intel')) {
            if (!wp_next_scheduled('botfend_update_threat_intel')) {
                wp_schedule_event(time(), 'twicedaily', 'botfend_update_threat_intel');
            }
            if (!wp_next_scheduled('botfend_preload_threat_feeds')) {
                wp_schedule_single_event(time() + 60, 'botfend_preload_threat_feeds');
            }
        }

        if ($config->get_bool('enable_tor_detection', false) && $config->get_bool('enable_external_tor_check', false)) {
            if (!wp_next_scheduled('botfend_update_tor_nodes')) {
                wp_schedule_event(time(), 'daily', 'botfend_update_tor_nodes');
            }
            if (!wp_next_scheduled('botfend_import_tor_nodes')) {
                wp_schedule_single_event(time() + 30, 'botfend_import_tor_nodes');
            }
        }

        if ($config->get_bool('protect_uploads', false)) {
            if (!wp_next_scheduled('botfend_file_guard_weekly')) {
                wp_schedule_event(time(), 'weekly', 'botfend_file_guard_weekly');
            }
            if (!wp_next_scheduled('botfend_file_guard_daily')) {
                wp_schedule_event(time(), 'daily', 'botfend_file_guard_daily');
            }
        }

        // ============================================
        // CLOUDFLARE CRON JOBS - PRO FEATURE
        // ============================================

        if ($config->get_bool('cf_enabled', false) && $this->is_pro_feature_allowed('cloudflare') && $config->get_bool('cf_sync_blocks', true)) {
            if (!wp_next_scheduled('botfend_cf_sync_cron')) {
                wp_schedule_event(time() + 300, 'hourly', 'botfend_cf_sync_cron');
            }
        }

        if ($config->get_bool('cf_enabled', false) && $this->is_pro_feature_allowed('cloudflare') && $config->get_bool('cf_auto_cleanup', true)) {
            if (!wp_next_scheduled('botfend_cf_cleanup_cron')) {
                wp_schedule_event(time() + 600, 'daily', 'botfend_cf_cleanup_cron');
            }
        }
    }

    public function show_admin_notices(): void {
        if (!current_user_can('manage_options')) {
            return;
        }

        if (!empty($this->missing_components)) {
            echo '<div class="notice notice-warning is-dismissible">';
            echo '<p><strong>' . esc_html__('BotFend Anti-Bot Firewall:', 'botfend-anti-bot-firewall') . '</strong></p>';
            echo '<p>' . esc_html__('Optional components not loaded:', 'botfend-anti-bot-firewall') . '</p>';
            echo '<ul>';
            foreach ($this->missing_components as $component) {
                echo '<li><code>' . esc_html($component) . '</code></li>';
            }
            echo '</ul>';
            echo '<p>' . esc_html__('Some features may be unavailable. Check your installation.', 'botfend-anti-bot-firewall') . '</p>';
            echo '</div>';
        }
        
        // Show Pro feature upgrade notice if Cloudflare enabled but license missing
        if ($this->components['config']->get_bool('cf_enabled', false) && !$this->is_pro_feature_allowed('cloudflare')) {
            echo '<div class="notice notice-warning">';
            echo '<p>';
            echo '<strong>' . esc_html__('BotFend Pro Feature:', 'botfend-anti-bot-firewall') . '</strong> ';
            echo esc_html__('Cloudflare integration requires a Pro license.', 'botfend-anti-bot-firewall');
            echo ' <a href="' . esc_url(admin_url('admin.php?page=botfend-license')) . '">';
            echo esc_html__('Activate License →', 'botfend-anti-bot-firewall');
            echo '</a>';
            echo '</p>';
            echo '</div>';
        }
    }

    public function handle_ajax_dismiss_notice(): void {
        check_ajax_referer('botfend_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => esc_html__('Unauthorized', 'botfend-anti-bot-firewall')]);
        }
        $notice_id = isset($_POST['notice_id']) ? sanitize_key(wp_unslash($_POST['notice_id'])) : '';
        if ($notice_id) {
            $user_id = get_current_user_id();
            update_user_meta($user_id, 'botfend_dismissed_' . $notice_id, time());
            wp_send_json_success(['message' => esc_html__('Notice dismissed', 'botfend-anti-bot-firewall')]);
        }
        wp_send_json_error(['message' => esc_html__('Invalid notice ID', 'botfend-anti-bot-firewall')]);
    }

    public function handle_ajax_protect_uploads(): void {
        check_ajax_referer('botfend_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => esc_html__('Unauthorized', 'botfend-anti-bot-firewall')]);
        }
        if (isset($this->components['file_guard'])) {
            $result = $this->components['file_guard']->manually_protect_uploads();
            wp_send_json_success($result);
        } else {
            wp_send_json_error(['message' => esc_html__('File Guard not available', 'botfend-anti-bot-firewall')]);
        }
    }

    public function handle_ajax_check_permissions(): void {
        check_ajax_referer('botfend_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => esc_html__('Unauthorized', 'botfend-anti-bot-firewall')]);
        }
        if (isset($this->components['file_guard'])) {
            $issues = $this->components['file_guard']->manually_check_permissions();
            wp_send_json_success(['issues' => $issues, 'count' => count($issues)]);
        } else {
            wp_send_json_error(['message' => esc_html__('File Guard not available', 'botfend-anti-bot-firewall')]);
        }
    }

    public function cleanup(): void {
        if (isset($this->components['logger'])) {
            $this->components['logger']->process_log_queue();
        }
    }

    public function get_component(string $name): ?object {
        return $this->components[$name] ?? null;
    }

    public function get_components(): array {
        return $this->components;
    }

    public function has_component(string $name): bool {
        return isset($this->components[$name]);
    }
    
    /**
     * Get license instance
     *
     * @return LicenseKey|null
     */
    public function get_license(): ?LicenseKey {
        return $this->license;
    }
    
    /**
     * Check if Pro license is active
     *
     * @return bool
     */
    public function is_pro_active(): bool {
        return $this->license && $this->license->is_valid();
    }

    private function start_benchmark(string $key): void {
        $this->benchmarks[$key] = microtime(true);
    }

    private function stop_benchmark(string $key): void {
        if (isset($this->benchmarks[$key])) {
            $this->benchmarks[$key] = microtime(true) - $this->benchmarks[$key];
        }
    }

    public function get_benchmarks(): array {
        return $this->benchmarks;
    }

    private function handle_init_error(\Throwable $e): void {
        error_log('BotFend Critical Init Failure: ' . $e->getMessage());
        add_action('admin_notices', function() use ($e) {
            echo '<div class="notice notice-error">';
            echo '<p><strong>' . esc_html__('BotFend Error:', 'botfend-anti-bot-firewall') . '</strong> ';
            echo esc_html($e->getMessage()) . '</p>';
            echo '<p>' . esc_html__('The plugin may not function correctly. Please check your WordPress error log.', 'botfend-anti-bot-firewall') . '</p>';
            echo '</div>';
        });
    }

    public function is_initialized(): bool {
        return $this->initialized;
    }

    public function get_missing_components(): array {
        return $this->missing_components;
    }

    public static function reset(): void {
        self::$instance = null;
    }
}