<?php

namespace UltraguardPro\support;

use UltraguardPro\Plugin;

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

class ModuleIntegrationHub {

    private Plugin $plugin;

    public function __construct( Plugin $plugin ) {
        $this->plugin = $plugin;
    }

    public function register(): void {
        add_action( 'ultraguard_request_blocked', [ $this, 'on_firewall_request_blocked' ], 10, 3 );
        add_action( 'ultraguard_antivirus_scan_completed', [ $this, 'on_antivirus_scan_completed' ], 10, 2 );
        add_action( 'ultraguard_filechecker_scan_complete', [ $this, 'on_filechecker_scan_complete' ], 10, 1 );
        add_action( 'ultraguard_db_scan_complete', [ $this, 'on_database_scan_complete' ], 10, 2 );
        add_action( 'ultraguard_vulnerability_scan_complete', [ $this, 'on_vulnerability_scan_complete' ], 10, 1 );
        add_action( 'ultraguard_vulnerability_threats_found', [ $this, 'on_vulnerability_threats_found' ], 10, 1 );
        add_action( 'ultraguard_virtual_patch_applied', [ $this, 'on_virtual_patch_applied' ], 10, 3 );
        add_action( 'ultraguard_virtual_patch_removed', [ $this, 'on_virtual_patch_removed' ], 10, 2 );
        add_action( 'ultraguard_pro/two_factor/enabled', [ $this, 'on_two_factor_enabled' ], 10, 2 );
        add_action( 'ultraguard_pro/two_factor/disabled', [ $this, 'on_two_factor_disabled' ], 10, 2 );
        add_action( 'ultraguard_pro/two_factor/backup_regenerated', [ $this, 'on_two_factor_backup_regenerated' ], 10, 2 );
        add_action( 'ultraguard_pro/two_factor/account_locked', [ $this, 'on_two_factor_account_locked' ], 10, 2 );
        add_action( 'ultraguard_pro/login_protect/old_url_hit', [ $this, 'on_hidden_login_hit' ], 10, 1 );
        add_action( 'ultraguard_pro/reputation_monitor/check_complete', [ $this, 'on_reputation_check_complete' ], 10, 1 );
        add_action( 'ultraguard_pro/uptime_monitor/status_changed', [ $this, 'on_uptime_status_changed' ], 10, 2 );
        add_action( 'ultraguard_pro/woo_security/skimmer_scan_complete', [ $this, 'on_woo_skimmer_scan_complete' ], 10, 1 );
        add_action( 'ultraguard_pro/woo_security/honeypot_triggered', [ $this, 'on_woo_honeypot_triggered' ], 10, 1 );
        add_action( 'ultraguard_hardening_applied', [ $this, 'on_hardening_applied' ], 10, 1 );
        add_action( 'ultraguard_pro/module_activated', [ $this, 'on_module_activated' ], 10, 1 );
        add_action( 'ultraguard_pro/module_deactivated', [ $this, 'on_module_deactivated' ], 10, 1 );
        add_action( 'ultraguard_pro/firewall/ip_blocked', [ $this, 'on_firewall_ip_blocked' ], 10, 3 );
        add_action( 'ultraguard_pro/firewall/ip_whitelisted', [ $this, 'on_firewall_ip_whitelisted' ], 10, 3 );

        // Bridge module-specific interop requests into the shared firewall hook surface.
        add_action( 'ultraguard_pro/traffic_monitor/block_ip', [ $this, 'bridge_traffic_monitor_block' ], 10, 3 );
        add_action( 'ultraguard_pro/traffic_monitor/whitelist_ip', [ $this, 'bridge_traffic_monitor_whitelist' ], 10, 2 );
    }

    public function bridge_traffic_monitor_block( string $ip, string $reason = '', string $severity = 'medium' ): void {
        do_action( 'ultraguard_pro/firewall/block_ip', $ip, 'traffic_monitor', $reason ?: $severity );
    }

    public function bridge_traffic_monitor_whitelist( string $ip, string $reason = '' ): void {
        do_action( 'ultraguard_pro/firewall/whitelist_ip', $ip, 'traffic_monitor', $reason );
    }

    public function on_firewall_request_blocked( string $ip, string $reason, string $threat ): void {
        $this->dispatch_event( [
            'source'   => 'firewall',
            'event'    => 'request_blocked',
            'category' => 'protection',
            'severity' => $threat ?: 'medium',
            'message'  => 'A request was blocked by the firewall.',
            'context'  => [
                'ip_address' => $ip,
                'reason'     => $reason,
                'threat'     => $threat,
            ],
        ] );
    }

    public function on_firewall_ip_blocked( string $ip, string $source = 'integration', string $reason = '' ): void {
        $this->dispatch_event( [
            'source'   => 'firewall',
            'event'    => 'ip_blocked',
            'category' => 'protection',
            'severity' => 'high',
            'message'  => 'An IP address was added to the firewall blocklist.',
            'context'  => [
                'ip_address'    => $ip,
                'blocked_by'    => $source,
                'block_reason'  => $reason,
            ],
        ] );
    }

    public function on_firewall_ip_whitelisted( string $ip, string $source = 'integration', string $reason = '' ): void {
        $this->dispatch_event( [
            'source'   => 'firewall',
            'event'    => 'ip_whitelisted',
            'category' => 'management',
            'severity' => 'low',
            'message'  => 'An IP address was added to the firewall allowlist.',
            'context'  => [
                'ip_address'       => $ip,
                'whitelisted_by'   => $source,
                'whitelist_reason' => $reason,
            ],
        ] );
    }

    public function on_antivirus_scan_completed( string $scan_id, array $summary ): void {
        $severity = ! empty( $summary['critical'] ) || ! empty( $summary['infected'] ) ? 'high' : 'low';

        $this->dispatch_event( [
            'source'   => 'antivirus',
            'event'    => 'scan_completed',
            'category' => 'monitoring',
            'severity' => $severity,
            'message'  => 'An antivirus scan completed.',
            'context'  => [
                'scan_id' => $scan_id,
                'summary' => $summary,
            ],
        ] );
    }

    public function on_filechecker_scan_complete( array $result ): void {
        $this->dispatch_event( [
            'source'   => 'filechecker',
            'event'    => 'scan_completed',
            'category' => 'monitoring',
            'severity' => ! empty( $result['threats_found'] ) ? 'medium' : 'low',
            'message'  => 'A file integrity scan completed.',
            'context'  => $result,
        ] );
    }

    public function on_database_scan_complete( string $scan_id, array $result ): void {
        $this->dispatch_event( [
            'source'   => 'database_scanner',
            'event'    => 'scan_completed',
            'category' => 'monitoring',
            'severity' => ! empty( $result['threats_found'] ) ? 'high' : 'low',
            'message'  => 'A database security scan completed.',
            'context'  => [
                'scan_id' => $scan_id,
                'result'  => $result,
            ],
        ] );
    }

    public function on_vulnerability_scan_complete( array $counts ): void {
        $this->dispatch_event( [
            'source'   => 'vulnerability',
            'event'    => 'scan_completed',
            'category' => 'monitoring',
            'severity' => ! empty( $counts['total'] ) ? 'medium' : 'low',
            'message'  => 'A vulnerability scan completed.',
            'context'  => $counts,
        ] );
    }

    public function on_vulnerability_threats_found( array $counts ): void {
        $this->dispatch_event( [
            'source'   => 'vulnerability',
            'event'    => 'threats_found',
            'category' => 'protection',
            'severity' => ! empty( $counts['critical'] ) ? 'critical' : 'high',
            'message'  => 'Vulnerabilities were found during scanning.',
            'context'  => $counts,
        ] );
    }

    public function on_virtual_patch_applied( string $cve_id, string $slug, $waf_id ): void {
        $this->dispatch_event( [
            'source'   => 'vulnerability',
            'event'    => 'virtual_patch_applied',
            'category' => 'protection',
            'severity' => 'medium',
            'message'  => 'A virtual patch was applied.',
            'context'  => [
                'cve_id'         => $cve_id,
                'component_slug' => $slug,
                'waf_rule_id'    => $waf_id,
            ],
        ] );
    }

    public function on_virtual_patch_removed( string $cve_id, string $new_version ): void {
        $this->dispatch_event( [
            'source'   => 'vulnerability',
            'event'    => 'virtual_patch_removed',
            'category' => 'management',
            'severity' => 'low',
            'message'  => 'A virtual patch was removed.',
            'context'  => [
                'cve_id'      => $cve_id,
                'new_version' => $new_version,
            ],
        ] );
    }

    public function on_two_factor_enabled( int $user_id, array $context = [] ): void {
        $this->dispatch_authenticator_event( 'two_factor_enabled', 'Two-factor authentication was enabled.', $user_id, 'medium', $context );
    }

    public function on_two_factor_disabled( int $user_id, array $context = [] ): void {
        $this->dispatch_authenticator_event( 'two_factor_disabled', 'Two-factor authentication was disabled.', $user_id, 'high', $context );
    }

    public function on_two_factor_backup_regenerated( int $user_id, array $context = [] ): void {
        $this->dispatch_authenticator_event( 'backup_codes_regenerated', 'Two-factor backup codes were regenerated.', $user_id, 'medium', $context );
    }

    public function on_two_factor_account_locked( int $user_id, array $context = [] ): void {
        $this->dispatch_authenticator_event( 'two_factor_account_locked', 'A user account was locked after failed two-factor verification.', $user_id, 'high', $context );
    }

    public function on_hidden_login_hit( array $payload ): void {
        $this->dispatch_event( [
            'source'   => 'login_protect',
            'event'    => 'old_login_url_hit',
            'category' => 'authentication',
            'severity' => 'medium',
            'message'  => 'The old login URL was accessed.',
            'context'  => $payload,
        ] );
    }

    public function on_reputation_check_complete( array $summary ): void {
        $severity = ! empty( $summary['blacklisted'] ) ? 'high' : 'low';

        $this->dispatch_event( [
            'source'   => 'reputation_monitor',
            'event'    => 'check_completed',
            'category' => 'monitoring',
            'severity' => $severity,
            'message'  => 'A reputation monitor check completed.',
            'context'  => $summary,
        ] );
    }

    public function on_uptime_status_changed( array $previous, array $result ): void {
        $severity = ( $result['status'] ?? 'up' ) === 'down' ? 'critical' : 'medium';

        $this->dispatch_event( [
            'source'   => 'uptime_monitor',
            'event'    => 'status_changed',
            'category' => 'monitoring',
            'severity' => $severity,
            'message'  => 'The monitored uptime status changed.',
            'context'  => [
                'previous' => $previous,
                'current'  => $result,
            ],
        ] );
    }

    public function on_woo_skimmer_scan_complete( array $results ): void {
        $threats = isset( $results['threats_found'] ) ? (int) $results['threats_found'] : count( $results );
        $severity = $threats > 0 ? 'critical' : 'low';

        $this->dispatch_event( [
            'source'   => 'woo_security',
            'event'    => 'skimmer_scan_completed',
            'category' => 'protection',
            'severity' => $severity,
            'message'  => 'A WooCommerce skimmer scan completed.',
            'context'  => $results,
        ] );
    }

    public function on_woo_honeypot_triggered( array $payload ): void {
        $this->dispatch_event( [
            'source'   => 'woo_security',
            'event'    => 'honeypot_triggered',
            'category' => 'protection',
            'severity' => 'high',
            'message'  => 'A WooCommerce checkout honeypot was triggered.',
            'context'  => $payload,
        ] );
    }

    public function on_hardening_applied( $settings = null ): void {
        $this->dispatch_event( [
            'source'   => 'hardening',
            'event'    => 'settings_applied',
            'category' => 'management',
            'severity' => 'low',
            'message'  => 'Hardening settings were applied.',
            'context'  => [],
        ] );
    }

    public function on_module_activated( string $module_id ): void {
        $this->dispatch_event( [
            'source'   => 'module_registry',
            'event'    => 'module_activated',
            'category' => 'management',
            'severity' => 'low',
            'message'  => 'A module was activated.',
            'context'  => [ 'module_id' => $module_id ],
        ], false );
    }

    public function on_module_deactivated( string $module_id ): void {
        $this->dispatch_event( [
            'source'   => 'module_registry',
            'event'    => 'module_deactivated',
            'category' => 'management',
            'severity' => 'medium',
            'message'  => 'A module was deactivated.',
            'context'  => [ 'module_id' => $module_id ],
        ], false );
    }

    private function dispatch_authenticator_event( string $event, string $message, int $user_id, string $severity, array $context = [] ): void {
        $context['user_id'] = $user_id;

        $this->dispatch_event( [
            'source'   => 'authenticator',
            'event'    => $event,
            'category' => 'authentication',
            'severity' => $severity,
            'message'  => $message,
            'context'  => $context,
        ] );
    }

    private function dispatch_event( array $event, bool $security_event = true ): void {
        $normalized = [
            'source'    => sanitize_key( (string) ( $event['source'] ?? 'system' ) ),
            'event'     => sanitize_key( (string) ( $event['event'] ?? 'event' ) ),
            'category'  => sanitize_key( (string) ( $event['category'] ?? 'general' ) ),
            'severity'  => sanitize_key( (string) ( $event['severity'] ?? 'low' ) ),
            'message'   => sanitize_text_field( (string) ( $event['message'] ?? '' ) ),
            'context'   => $this->normalize_context( $event['context'] ?? [] ),
            'timestamp' => current_time( 'mysql', true ),
        ];

        $normalized = (array) apply_filters( 'ultraguard_pro/integration/normalize_event', $normalized, $event, $this->plugin );

        do_action( 'ultraguard_pro/integration/event', $normalized );
        do_action( 'ultraguard_pro/integration/event/' . $normalized['source'], $normalized );
        do_action( 'ultraguard_pro/integration/event/' . $normalized['source'] . '/' . $normalized['event'], $normalized );
        do_action( 'ultraguard_pro/integration/audit_event', $normalized );

        if ( $security_event ) {
            do_action( 'ultraguard_pro/integration/security_event', $normalized );
        }
    }

    private function normalize_context( $context ): array {
        if ( ! is_array( $context ) ) {
            return [];
        }

        return $context;
    }
}
