<?php
/**
 * Plugin — Root Singleton
 *
 * Acts as the **parent** that wires every subsystem together.
 * Initialisation order is strictly enforced:
 *
 *  1. Core services (Database, CacheManager, Settings, Utils)
 *  2. Module registry + module bootstrap
 *  3. Admin interface (only on is_admin())
 *  4. WordPress hooks (action links, cron, cache-invalidation)
 *
 * Every child class (modules, db tables, controllers) receives $plugin
 * via constructor injection — zero static coupling to global state.
 *
 * @package UltraguardPro
 */

namespace UltraguardPro;

use UltraguardPro\core\CacheManager;
use UltraguardPro\core\DatabaseInstaller;
use UltraguardPro\core\Logger;
use UltraguardPro\contracts\ModuleInterface;
use UltraguardPro\modules\ModuleRegistry;
use UltraguardPro\support\LicenseInfo;
use UltraguardPro\support\ModuleIntegrationHub;
if ( ! defined( 'ABSPATH' ) ) { exit; }

final class Plugin {

    // ── Singleton ─────────────────────────────────────────────────────────────
    private static ?Plugin $instance = null;

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

    // ── Core service properties (populated by init()) ─────────────────────────

    /** @var core\CacheManager */
    public readonly core\CacheManager $cache;

    /** @var modules\settings\Settings */
    public readonly modules\settings\Settings $settings;

    /** @var core\Utils */
    public readonly core\Utils $utils;

    /** @var core\AjaxManager */
    public readonly core\AjaxManager $ajax;

    /** @var core\DatabaseInstaller */
    public readonly core\DatabaseInstaller $db_installer;

    /** @var modules\ModuleRegistry */
    public readonly modules\ModuleRegistry $modules;

    /** @var support\ModuleIntegrationHub */
    public readonly support\ModuleIntegrationHub $integration_hub;

    /** @var support\LicenseInfo|null (lazy) */
    public ?support\LicenseInfo $license = null;

    /** @var bool */
    private bool $booted = false;

    // ── Constructor ───────────────────────────────────────────────────────────
    private function __construct() {
        if ( ! $this->check_requirements() ) {
            return;
        }
        add_action( 'plugins_loaded', [ $this, 'init' ], 10 );
        add_action( 'init',           [ $this, 'load_textdomain' ], 1 );
        add_action( 'init',           [ $this, 'early_security_init' ], 2 );
    }

    // ── Requirements check ────────────────────────────────────────────────────
    private function check_requirements(): bool {
        if ( version_compare( PHP_VERSION, ULTRAGUARD_PRO_MIN_PHP, '<' ) ) {
            add_action( 'admin_notices', [ $this, 'notice_php_version' ] );
            return false;
        }
        global $wp_version;
        if ( version_compare( $wp_version, ULTRAGUARD_PRO_MIN_WP, '<' ) ) {
            add_action( 'admin_notices', [ $this, 'notice_wp_version' ] );
            return false;
        }
        $missing = array_filter( [ 'json', 'curl', 'openssl' ], fn( $e ) => ! extension_loaded( $e ) );
        if ( $missing ) {
            add_action( 'admin_notices', fn() => $this->notice_missing_extensions( $missing ) );
            return false;
        }
        return true;
    }

    public function load_textdomain(): void {
        // WordPress auto-loads language packs for modern plugins, so no explicit
        // textdomain bootstrapping is needed here.
    }

    // ── Main init (plugins_loaded) ────────────────────────────────────────────
    public function init(): void {
        // Guard: prevent double-initialisation if the action fires more than once.
        if ( $this->booted ) { return; }

        // 1. Core services — required by everything else
        $this->cache       = CacheManager::get_instance();
        $this->utils       = new core\Utils();
        $this->settings    = modules\settings\Settings::get_instance( $this );
        $this->ajax        = core\AjaxManager::get_instance();
        $this->db_installer = new core\DatabaseInstaller( $this );
        LicenseInfo::init();
        $this->license = LicenseInfo::instance();
        $this->integration_hub = new ModuleIntegrationHub( $this );
        $this->integration_hub->register();

        // 2. Module registry — discovers & boots all modules
        $this->modules = new modules\ModuleRegistry( $this );
        $this->modules->boot();

        // 3. Admin bootstrap (only on wp-admin requests)
        if ( is_admin() ) {
            $this->boot_admin();
        }

        // 4. Plugin-level WordPress hooks
        $this->register_hooks();

        // 5. SSE stream (replaces constant AJAX polling)
        ( new view\SseStream( $this ) )->register();

        $this->booted = true;

        do_action( 'ultraguard_pro_init', $this );
        do_action( 'ultraguard_pro/services_registered', $this );
    }

    // ── Early security (WordPress init hook) ─────────────────────────────────
    public function early_security_init(): void {
        if ( ! $this->booted ) { return; }

        do_action( 'ultraguard_pro/early_security_init/before', $this );

        $firewall = $this->modules->get( 'firewall' );
        if ( $firewall && method_exists( $firewall, 'start_protection' ) ) {
            $firewall->start_protection();
        }

        $login_limiter = $this->modules->get( 'login_limiter' );
        if ( $login_limiter ) {
            $uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
            if ( strpos( $uri, 'wp-login.php' ) !== false || strpos( $uri, 'wp-signup.php' ) !== false ) {
                if ( method_exists( $login_limiter, 'maybe_block_locked_out_ip' ) ) {
                    $login_limiter->maybe_block_locked_out_ip();
                }
            }
        }

        do_action( 'ultraguard_pro/early_security_init/after', $this );
    }

    // ── Admin bootstrap ───────────────────────────────────────────────────────
    private function boot_admin(): void {
        if ( class_exists( core\Admin::class ) ) {
            core\Admin::get_instance( $this );
        }
        add_action( 'admin_init', [ $this, 'on_admin_init' ] );
        do_action( 'ultraguard_pro/admin_initialized', $this );
    }

    public function on_admin_init(): void {
        if ( ! current_user_can( $this->get_capability() ) ) { return; }
        do_action( 'ultraguard_pro/admin_init', $this );
    }

    // ── WordPress hooks ───────────────────────────────────────────────────────
    private function register_hooks(): void {
        add_filter( 'plugin_action_links_' . ULTRAGUARD_PRO_BASENAME, [ $this, 'plugin_action_links' ] );
        add_filter( 'plugin_row_meta',                                  [ $this, 'plugin_row_meta' ], 10, 2 );
        add_action( 'ultraguard_pro_cleanup_logs',                      [ $this, 'run_cleanup_logs' ] );

        // Render/page cache hooks have been removed: only DB-query cache is active.
        add_action( 'ultraguard_pro_setting_updated',       fn() => $this->cache->invalidate_db() );
        add_action( 'ultraguard_pro_settings_bulk_updated', fn() => $this->cache->invalidate_db() );
        add_action( 'ultraguard_pro_settings_reset',        fn() => $this->cache->invalidate_db() );
        add_action( 'ultraguard_options_saved',             fn() => $this->cache->invalidate_db() );
        add_action( 'ultraguard_settings_imported',         fn() => $this->cache->invalidate_db() );
        add_action( 'ultraguard_firewall_rule_saved', fn() => $this->cache->invalidate_db( 'firewall_rules' ) );
        add_action( 'ultraguard_ip_list_updated',     fn() => $this->cache->invalidate_db( 'ip_blacklist' ) );
        add_action( 'ultraguard_ip_list_updated',     fn() => $this->cache->invalidate_db( 'ip_whitelist' ) );
        add_action( 'ultraguard_scan_complete',       fn() => $this->cache->invalidate_db( 'scan_results' ) );
    }

    // ── Cron: log cleanup ─────────────────────────────────────────────────────
    public function run_cleanup_logs(): void {
        try {
            if ( class_exists( core\Logger::class ) ) {
                core\Logger::cleanup_old_logs( [ 'days' => 30 ] );
                core\Logger::cleanup_database_logs( [ 'days' => 90 ] );
            }

            $db_tables = $this->modules->get_db_tables();
            if ( $db_tables ) {
                $prune = [
                    'security_logs' => 90, 'audit_logs' => 90, 'firewall_logs' => 60,
                    'login_attempts' => 30, 'user_activity' => 60,
                    'blocked_requests' => 30, 'security_events' => 90,
                ];
                foreach ( $prune as $table_key => $days ) {
                    $table = $db_tables->get_table( $table_key );
                    if ( $table && method_exists( $table, 'delete_old_records' ) ) {
                        $table->delete_old_records( $days );
                    }
                }

                // Clean expired cloud threat IPs
                $threat_t = $db_tables->get_table( 'threat_ips' );
                if ( $threat_t && method_exists( $threat_t, 'cleanup_expired' ) ) {
                    $threat_t->cleanup_expired();
                }
            }
            do_action( 'ultraguard_pro/cleanup_logs_completed' );
        } catch ( \Exception $e ) {
            Logger::error(
                'Ultraguard Pro cleanup failed',
                [
                    'message' => $e->getMessage(),
                ]
            );
        }
    }

    // ── Public API ────────────────────────────────────────────────────────────

    public function get_option( string $key, $default = false ) {
        return $this->settings->get_option( $key, $default );
    }

    public function update_option( string $key, $value ): bool {
        return $this->settings->update_option( $key, $value );
    }

    public function get_capability(): string {
        $default = is_multisite() ? 'manage_network_options' : 'manage_options';
        return apply_filters( 'ultraguard_pro/capability', $default );
    }

    public function is_booted(): bool {
        return $this->booted;
    }

    // ── Plugin meta links ─────────────────────────────────────────────────────
    public function plugin_action_links( array $links ): array {
        if ( ! current_user_can( $this->get_capability() ) ) { return $links; }
        $link = sprintf(
            '<a href="%s">%s</a>',
            esc_url( self_admin_url( 'admin.php?page=ultraguard-security-suite-dashboard' ) ),
            esc_html__( 'Settings', 'ultraguard-security-suite' )
        );
        array_unshift( $links, $link );
        return $links;
    }

    public function plugin_row_meta( array $links, string $file ): array {
        if ( ULTRAGUARD_PRO_BASENAME !== $file ) { return $links; }
        return array_merge( $links, [
            'docs'    => sprintf(
                '<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>',
                esc_url( 'https://ultraguard.net/docs/' ),
                esc_html__( 'Documentation', 'ultraguard-security-suite' )
            ),
            'support' => sprintf(
                '<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>',
                esc_url( 'https://ultraguard.net/contact' ),
                esc_html__( 'Support', 'ultraguard-security-suite' )
            ),
        ] );
    }

    // ── Admin notices ─────────────────────────────────────────────────────────
    public function notice_php_version(): void {
        if ( ! function_exists( __NAMESPACE__ . '\\ultraguard_current_user_can_manage' ) || ! ultraguard_current_user_can_manage() ) { return; }
        printf(
            '<div class="notice notice-error"><p>%s</p></div>',
            /* translators: Placeholder values are inserted into this string. */
            esc_html__( 'Ultraguard Pro requires PHP %1$s or higher. Current: %2$s.', 'ultraguard-security-suite' ),
            esc_html( ULTRAGUARD_PRO_MIN_PHP ),
            esc_html( PHP_VERSION )
        );
    }

    public function notice_wp_version(): void {
        if ( ! function_exists( __NAMESPACE__ . '\\ultraguard_current_user_can_manage' ) || ! ultraguard_current_user_can_manage() ) { return; }
        global $wp_version;
        printf(
            '<div class="notice notice-error"><p>%s</p></div>',
            /* translators: Placeholder values are inserted into this string. */
            esc_html__( 'Ultraguard Pro requires WordPress %1$s or higher. Current: %2$s.', 'ultraguard-security-suite' ),
            esc_html( ULTRAGUARD_PRO_MIN_WP ),
            esc_html( $wp_version )
        );
    }

    public function notice_missing_extensions( array $extensions ): void {
        if ( ! function_exists( __NAMESPACE__ . '\\ultraguard_current_user_can_manage' ) || ! ultraguard_current_user_can_manage() ) { return; }
        printf(
            '<div class="notice notice-error"><p>%s</p></div>',
            /* translators: Placeholder values are inserted into this string. */
            esc_html__( 'Ultraguard Pro requires PHP extensions: %s', 'ultraguard-security-suite' ),
            esc_html( implode( ', ', $extensions ) )
        );
    }
}
