<?php

namespace UltraguardPro\modules\uptime_monitor;

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

use UltraguardPro\Plugin;
use UltraguardPro\core\MailManager;
use UltraguardPro\modules\core\AbstractModule;

class UptimeMonitorModule extends AbstractModule {

    public function __construct( Plugin $plugin ) {
        parent::__construct( $plugin );
        $this->plugin->settings->register_module_prefix( 'uptime_monitor_', 'uptime_monitor' );
    }

    public function get_id(): string {
        return 'uptime_monitor';
    }

    protected function requires_pro(): bool {
        return true;
    }

    protected function allow_preview_mode(): bool {
        return true;
    }

    public function boot(): void {
        $_db_tables = $this->plugin->modules->get_db_tables();
        if ( $_db_tables ) {
            $_db_tables->register_schema( new schema\UptimeMonitorSchema() );
        }

        if ( method_exists( $this->plugin->settings, 'register_settings_schema' ) ) {
            $this->plugin->settings->register_settings_schema( 'uptime_monitor', 'uptime_monitor_', [
                'uptime_monitor_enabled'             => [ 'type' => 'bool', 'default' => true ],
                'uptime_monitor_check_url'           => [ 'type' => 'text', 'default' => home_url() ],
                'uptime_monitor_additional_urls'     => [ 'type' => 'textarea', 'default' => '' ],
                'uptime_monitor_interval'            => [ 'type' => 'select', 'default' => '5_minutes', 'options' => [ '1_minute', '5_minutes', '15_minutes', '30_minutes' ] ],
                'uptime_monitor_enable_ssl'          => [ 'type' => 'bool', 'default' => true ],
                'uptime_monitor_ssl_alert_30'        => [ 'type' => 'bool', 'default' => true ],
                'uptime_monitor_ssl_alert_7'         => [ 'type' => 'bool', 'default' => true ],
                'uptime_monitor_downtime_email'      => [ 'type' => 'bool', 'default' => true ],
                'uptime_monitor_failure_threshold'   => [ 'type' => 'int', 'default' => 2 ],
                'uptime_monitor_recovery_email'      => [ 'type' => 'bool', 'default' => true ],
                'uptime_monitor_weekly_report'       => [ 'type' => 'bool', 'default' => false ],
            ] );
        }

        ( new ajax\UptimeMonitorAjax( $this->plugin ) )->register();
        add_action( 'ultraguard_register_admin_pages', [ $this, 'register_pages' ], 120, 1 );
        ( new UptimeMonitorDashboardContributor( $this->plugin ) )->register();
        add_action( 'ultraguard_after_enqueue_assets', [ $this, 'enqueue_assets' ] );

        if ( ! $this->is_preview_mode() ) {
            add_filter( 'cron_schedules', [ $this, 'register_cron_schedules' ] );
            add_action( 'wp_loaded', [ $this, 'maybe_setup_schedule' ] );
            add_action( 'ultraguard_uptime_check', [ $this, 'run_uptime_check' ] );
            add_action( 'ultraguard_ssl_check', [ $this, 'run_ssl_check' ] );
            add_action( 'ultraguard_uptime_weekly_report', [ $this, 'run_weekly_report' ] );
            ( new UptimeMonitorNotifications( $this->plugin ) )->register();
        }

        do_action( 'ultraguard_pro/uptime_monitor/booted', $this );
    }

    public function register_pages( $admin ): void {
        $admin->register_page( [
            'id'              => 'uptime-monitor',
            'page_title'      => __( 'Uptime & SSL Monitor', 'ultraguard-security-suite' ),
            'menu_title'      => __( 'Uptime Monitor', 'ultraguard-security-suite' ),
            'capability'      => 'manage_options',
            'scheme_callback' => [ new pages\UptimeMonitorDashboard( $this->plugin ), 'get_scheme' ],
            'parent_id'       => '',
            'priority'        => 120,
            'group'           => 'Monitoring',
            'icon'            => 'dashicons-clock',
        ] );

        $admin->register_page( [
            'id'              => 'uptime-monitor-settings',
            'page_title'      => __( 'Uptime Monitor Settings', 'ultraguard-security-suite' ),
            'menu_title'      => __( 'Settings', 'ultraguard-security-suite' ),
            'capability'      => 'manage_options',
            'scheme_callback' => [ new pages\UptimeMonitorSettings( $this->plugin ), 'get_scheme' ],
            'parent_id'       => 'uptime-monitor',
            'priority'        => 121,
            'group'           => 'Monitoring',
            'icon'            => 'dashicons-admin-settings',
        ] );
    }

    public function register_cron_schedules( array $schedules ): array {
        $schedules['every_minute'] = [
            'interval' => MINUTE_IN_SECONDS,
            'display'  => __( 'Every Minute', 'ultraguard-security-suite' ),
        ];
        $schedules['every_5_minutes'] = [
            'interval' => 5 * MINUTE_IN_SECONDS,
            'display'  => __( 'Every 5 Minutes', 'ultraguard-security-suite' ),
        ];
        $schedules['every_15_minutes'] = [
            'interval' => 15 * MINUTE_IN_SECONDS,
            'display'  => __( 'Every 15 Minutes', 'ultraguard-security-suite' ),
        ];
        $schedules['every_30_minutes'] = [
            'interval' => 30 * MINUTE_IN_SECONDS,
            'display'  => __( 'Every 30 Minutes', 'ultraguard-security-suite' ),
        ];
        if ( ! isset( $schedules['weekly'] ) ) {
            $schedules['weekly'] = [
                'interval' => WEEK_IN_SECONDS,
                'display'  => __( 'Once Weekly', 'ultraguard-security-suite' ),
            ];
        }

        return $schedules;
    }

    public function maybe_setup_schedule(): void {
        $enabled      = $this->option_enabled( 'uptime_monitor_enabled' );
        $enable_ssl   = $this->option_enabled( 'uptime_monitor_enable_ssl' );
        $uptime_hook  = 'ultraguard_uptime_check';
        $ssl_hook     = 'ultraguard_ssl_check';
        $report_hook  = 'ultraguard_uptime_weekly_report';
        $interval_map = [
            '1_minute'   => 'every_minute',
            '5_minutes'  => 'every_5_minutes',
            '15_minutes' => 'every_15_minutes',
            '30_minutes' => 'every_30_minutes',
        ];
        $interval     = (string) $this->option( 'uptime_monitor_interval', '5_minutes' );
        $schedule     = $interval_map[ $interval ] ?? 'every_5_minutes';
        $current      = wp_get_schedule( $uptime_hook );

        if ( ! $enabled ) {
            wp_clear_scheduled_hook( $uptime_hook );
            wp_clear_scheduled_hook( $ssl_hook );
            wp_clear_scheduled_hook( $report_hook );
            return;
        }

        if ( $current !== $schedule ) {
            wp_clear_scheduled_hook( $uptime_hook );
            wp_schedule_event( time() + MINUTE_IN_SECONDS, $schedule, $uptime_hook );
        } elseif ( ! wp_next_scheduled( $uptime_hook ) ) {
            wp_schedule_event( time() + MINUTE_IN_SECONDS, $schedule, $uptime_hook );
        }

        if ( $enable_ssl ) {
            if ( ! wp_next_scheduled( $ssl_hook ) ) {
                wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', $ssl_hook );
            }
        } else {
            wp_clear_scheduled_hook( $ssl_hook );
        }

        if ( $this->option_enabled( 'uptime_monitor_weekly_report' ) ) {
            if ( ! wp_next_scheduled( $report_hook ) ) {
                wp_schedule_event( time() + DAY_IN_SECONDS, 'weekly', $report_hook );
            }
        } else {
            wp_clear_scheduled_hook( $report_hook );
        }
    }

    public function run_uptime_check(): void {
        if ( ! $this->option_enabled( 'uptime_monitor_enabled' ) ) {
            return;
        }

        $engine = new UptimeCheckEngine( $this->plugin );
        foreach ( $this->get_urls_to_monitor() as $url ) {
            $engine->check_uptime( $url );
        }
    }

    public function run_ssl_check(): void {
        if ( ! $this->option_enabled( 'uptime_monitor_enabled' ) || ! $this->option_enabled( 'uptime_monitor_enable_ssl' ) ) {
            return;
        }

        $domain = wp_parse_url( home_url(), PHP_URL_HOST );
        if ( ! empty( $domain ) ) {
            ( new UptimeCheckEngine( $this->plugin ) )->check_ssl( (string) $domain );
        }
    }

    public function run_weekly_report(): void {
        if ( ! $this->option_enabled( 'uptime_monitor_enabled' ) || ! $this->option_enabled( 'uptime_monitor_weekly_report' ) ) {
            return;
        }

        $email = sanitize_email( (string) get_option( 'admin_email', '' ) );
        if ( ! is_email( $email ) ) {
            return;
        }

        $engine = new UptimeCheckEngine( $this->plugin );
        $ssl    = $engine->get_ssl_status();

        MailManager::notification( [
            'to'        => $email,
            'subject'   => __( 'UltraGuard Weekly Uptime Report', 'ultraguard-security-suite' ),
            'title'     => __( 'Weekly Uptime Summary', 'ultraguard-security-suite' ),
            'message'   => __( 'Here is your weekly uptime and SSL health summary from UltraGuard.', 'ultraguard-security-suite' ),
            'tone'      => 'info',
            'details'   => [
                __( 'Current status', 'ultraguard-security-suite' )        => strtoupper( $engine->get_current_status() ),
                __( 'Uptime 24h', 'ultraguard-security-suite' )            => round( $engine->get_uptime_percentage( 24 ), 2 ) . '%',
                __( 'Uptime 7d', 'ultraguard-security-suite' )             => round( $engine->get_uptime_percentage( 24 * 7 ), 2 ) . '%',
                __( 'Uptime 30d', 'ultraguard-security-suite' )            => round( $engine->get_uptime_percentage( 24 * 30 ), 2 ) . '%',
                __( 'Average response', 'ultraguard-security-suite' )      => round( $engine->get_average_response_time( 24 * 7 ), 2 ) . ' ms',
                __( 'SSL expires in', 'ultraguard-security-suite' )        => isset( $ssl['days_remaining'] ) ? ( (int) $ssl['days_remaining'] . ' days' ) : __( 'Unknown', 'ultraguard-security-suite' ),
                __( 'Monitored URL', 'ultraguard-security-suite' )         => (string) $this->option( 'uptime_monitor_check_url', home_url() ),
            ],
            'cta_url'   => admin_url( 'admin.php?page=ultraguard-security-suite-dashboard&ug_page=uptime-monitor' ),
            'cta_label' => __( 'Open Uptime Monitor', 'ultraguard-security-suite' ),
        ] );
    }

    public function enqueue_assets(): void {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen detection.
        $ug_page = sanitize_key( wp_unslash( $_GET['ug_page'] ?? ''  ) );
        if ( ! in_array( $ug_page, [ 'uptime-monitor', 'uptime-monitor-settings' ], true ) ) {
            return;
        }

        $module_url = plugin_dir_url( __FILE__ );
        $version    = defined( 'ULTRAGUARD_PRO_VERSION' ) ? ULTRAGUARD_PRO_VERSION : '1.0.0';

        wp_enqueue_style(
            'ultraguard-uptime-monitor-page',
            $module_url . 'assets/css/uptime-monitor-page.css',
            [ 'admin-base', 'admin-components' ],
            $version
        );

        wp_enqueue_script(
            'ultraguard-uptime-monitor-page',
            $module_url . 'assets/js/uptime-monitor-page.js',
            [ 'jquery', 'ultraguard-core', 'ultraguard-managers' ],
            $version,
            true
        );

        wp_localize_script( 'ultraguard-uptime-monitor-page', 'ultraguardUptimeMonitor', [
            'nonce'   => wp_create_nonce( 'ultraguard_admin_nonce' ),
            'ajaxUrl' => self_admin_url( 'admin-ajax.php' ),
            'i18n'    => [
                'checking' => __( 'Running uptime and SSL checks...', 'ultraguard-security-suite' ),
                'failed'   => __( 'Unable to complete the uptime monitor request.', 'ultraguard-security-suite' ),
            ],
        ] );
    }

    private function get_urls_to_monitor(): array {
        $urls   = [ (string) $this->option( 'uptime_monitor_check_url', home_url() ) ];
        $extra  = preg_split( '/\r\n|\r|\n/', (string) $this->option( 'uptime_monitor_additional_urls', '' ) );

        foreach ( (array) $extra as $line ) {
            $line = trim( (string) $line );
            if ( '' !== $line ) {
                $urls[] = $line;
            }
        }

        $urls = array_values( array_unique( array_filter( array_map( 'esc_url_raw', $urls ) ) ) );

        return $urls;
    }
}
