<?php
/**
 * WP Multi – Modul: Brute-Force-Schutz
 *
 * Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
 * wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
 */

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

/*
 * Schutz vor Brute-Force-Angriffen mit wöchentlicher Zusammenfassung
 * Sperr-E-Mails entfernt, Zusammenfassung deaktivierbar unter Benutzer mit verbessertem Design
 */

// Funktion zur Erfassung der echten IP-Adresse des Benutzers
function get_user_ip() {
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) {
        return $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $ip = trim($ips[0]);
        return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : $_SERVER['REMOTE_ADDR'];
    }
    return filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
}

// Funktion zur Verfolgung von fehlgeschlagenen Anmeldeversuchen
function wp_multi_log_failed_login($username) {
    global $wpdb;

    $ip = get_user_ip();
    if ($ip === '0.0.0.0') {
        return;
    }

    $blocked_table = $wpdb->prefix . 'blocked_ips';
    $attempts_table = $wpdb->prefix . 'login_attempts';
    $block_threshold = 5;

    // Anmeldeversuch in attempts-Tabelle speichern
    $wpdb->insert(
        $attempts_table,
        array(
            'ip' => $ip,
            'username' => $username,
            'attempt_time' => current_time('mysql'),
        ),
        array('%s', '%s', '%s')
    );

    // Prüfen, ob IP bereits in blocked_ips existiert
    $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM $blocked_table WHERE ip = %s", $ip));

    if ($row) {
        $wpdb->update(
            $blocked_table,
            array(
                'attempts' => $row->attempts + 1,
                'last_attempt' => current_time('mysql'),
            ),
            array('ip' => $ip),
            array('%d', '%s'),
            array('%s')
        );
        $attempts = $row->attempts + 1;
    } else {
        $wpdb->insert(
            $blocked_table,
            array(
                'ip' => $ip,
                'attempts' => 1,
                'last_attempt' => current_time('mysql'),
            ),
            array('%s', '%d', '%s')
        );
        $attempts = 1;
    }

    // IP sperren, wenn Schwellenwert erreicht
    if ($attempts >= $block_threshold) {
        wp_die(
            __('Deine IP-Adresse wurde aufgrund zu vieler Fehlversuche gesperrt. Bitte versuche es später noch einmal.', 'wp-multi'),
            __('Zugriff gesperrt', 'wp-multi'),
            array('response' => 403)
        );
    }
}

// Hook für fehlgeschlagene Anmeldungen
add_action('wp_login_failed', 'wp_multi_log_failed_login', 10, 1);

// Funktion zur Erstellung der Tabellen
function wp_multi_create_blocked_ips_table() {
    global $wpdb;

    $blocked_table = $wpdb->prefix . 'blocked_ips';
    $attempts_table = $wpdb->prefix . 'login_attempts';
    $charset_collate = $wpdb->get_charset_collate();
    $version = get_option('wp_multi_blocked_ips_version', '1.0');

    if (version_compare($version, '1.1', '<')) {
        $sql_blocked = "CREATE TABLE $blocked_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            ip varchar(45) NOT NULL,
            attempts int NOT NULL DEFAULT 0,
            last_attempt datetime NOT NULL,
            PRIMARY KEY (id),
            KEY ip (ip)
        ) $charset_collate;";

        $sql_attempts = "CREATE TABLE $attempts_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            ip varchar(45) NOT NULL,
            username varchar(255) NOT NULL,
            attempt_time datetime NOT NULL,
            PRIMARY KEY (id),
            KEY ip (ip),
            KEY attempt_time (attempt_time)
        ) $charset_collate;";

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        dbDelta($sql_blocked);
        dbDelta($sql_attempts);
        update_option('wp_multi_blocked_ips_version', '1.1');
    }
}
register_activation_hook(WP_MULTI_FILE, 'wp_multi_create_blocked_ips_table');

// Wöchentliche Zusammenfassung
function wp_multi_send_weekly_summary() {
    global $wpdb;

    // Prüfen, ob Zusammenfassung aktiviert ist
    $summary_enabled = get_option('wp_multi_summary_enabled', 1);
    if (!$summary_enabled) {
        return;
    }

    $attempts_table = $wpdb->prefix . 'login_attempts';
    $last_email_time = get_option('wp_multi_last_summary_email', 0);
    $current_time = time();

    // Prüfen, ob eine Woche vergangen ist (7 Tage = 604800 Sekunden)
    if (($current_time - $last_email_time) < 604800) {
        return;
    }

    // Zeitraum für die Zusammenfassung (letzte Woche)
    $week_ago = date('Y-m-d H:i:s', strtotime('-7 days'));
    $now = date('Y-m-d H:i:s');

    // Gesamtzahl der Anmeldeversuche
    $total_attempts = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM $attempts_table WHERE attempt_time >= %s",
            $week_ago
        )
    );
    $total_attempts = $total_attempts ? $total_attempts : 0;

    // Top 10 IPs mit den meisten Anmeldeversuchen
    $top_attempts = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT ip, username, COUNT(*) as attempt_count, MAX(attempt_time) as last_attempt
             FROM $attempts_table 
             WHERE attempt_time >= %s 
             GROUP BY ip, username 
             ORDER BY attempt_count DESC 
             LIMIT 10",
            $week_ago
        )
    );

    // E-Mail-Inhalt
    $message = __("Wöchentliche Anmeldeversuche-Zusammenfassung\n\n", 'wp-multi');
    $message .= sprintf(__("Zeitraum: %s bis %s\n\n", 'wp-multi'), $week_ago, $now);
    $message .= sprintf(__("Gesamtzahl der Anmeldeversuche: %d\n\n", 'wp-multi'), $total_attempts);
    $message .= __("Top 10 Anmeldeversuche (nach IP und Benutzername):\n", 'wp-multi');

    if ($top_attempts) {
        foreach ($top_attempts as $index => $attempt) {
            $message .= sprintf(
                __("%d. IP: %s, Benutzername: %s, Versuche: %d, Letzter Versuch: %s\n", 'wp-multi'),
                $index + 1,
                $attempt->ip,
                $attempt->username,
                $attempt->attempt_count,
                $attempt->last_attempt
            );
        }
    } else {
        $message .= __("Keine Anmeldeversuche in diesem Zeitraum.\n", 'wp-multi');
    }

    // E-Mail an Admin senden
    $admin_email = get_option('admin_email');
    wp_mail(
        $admin_email,
        __('Wöchentliche Anmeldeversuche-Zusammenfassung', 'wp-multi'),
        $message,
        array('Content-Type: text/plain; charset=UTF-8')
    );

    // Aktualisiere den Zeitstempel der letzten E-Mail
    update_option('wp_multi_last_summary_email', $current_time);
}

// Planen der wöchentlichen Zusammenfassung (jeden Montag um 8:00 Uhr)
function wp_multi_schedule_weekly_summary() {
    if (!wp_next_scheduled('wp_multi_weekly_summary_event')) {
        wp_schedule_event(strtotime('next Monday 08:00'), 'weekly', 'wp_multi_weekly_summary_event');
    }
}
add_action('wp', 'wp_multi_schedule_weekly_summary');

// Hook für die Ausführung der Zusammenfassung
add_action('wp_multi_weekly_summary_event', 'wp_multi_send_weekly_summary');

// Einstellungsoption für die Zusammenfassung
function wp_multi_users_register_settings() {
    add_option('wp_multi_summary_enabled', 1);
    register_setting('wp_multi_users_settings_group', 'wp_multi_summary_enabled', array(
        'type' => 'integer',
        'sanitize_callback' => 'absint',
        'default' => 1,
    ));

    // Settings Section hinzufügen
    add_settings_section(
        'wp_multi_security_section',
        __('Brute-Force-Schutz Einstellungen', 'wp-multi'),
        'wp_multi_security_section_callback',
        'wp_multi_users_security_settings'
    );

    // Settings Field hinzufügen
    add_settings_field(
        'wp_multi_summary_enabled',
        __('Wöchentliche Zusammenfassung', 'wp-multi'),
        'wp_multi_summary_enabled_callback',
        'wp_multi_users_security_settings',
        'wp_multi_security_section'
    );
}
add_action('admin_init', 'wp_multi_users_register_settings');

// Callback für die Settings Section
function wp_multi_security_section_callback() {
    echo '<p>' . __('Konfiguriere die Sicherheitseinstellungen für den Brute-Force-Schutz deiner Website. Aktiviere oder deaktiviere die wöchentliche Zusammenfassung der fehlgeschlagenen Anmeldeversuche.', 'wp-multi') . '</p>';
}

// Callback für das Settings Field
function wp_multi_summary_enabled_callback() {
    $summary_enabled = get_option('wp_multi_summary_enabled', 1);
    ?>
    <input type="checkbox" name="wp_multi_summary_enabled" id="wp_multi_summary_enabled" value="1" <?php checked(1, $summary_enabled); ?> />
    <label for="wp_multi_summary_enabled"><?php _e('Wöchentliche E-Mail-Zusammenfassung für fehlgeschlagene Anmeldeversuche aktivieren', 'wp-multi'); ?></label>
    <p class="description"><?php _e('Wenn aktiviert, erhält der Administrator jeden Montag um 8:00 Uhr eine E-Mail mit einer Zusammenfassung der fehlgeschlagenen Anmeldeversuche der letzten Woche.', 'wp-multi'); ?></p>
    <?php
}

// Blockierte IPs & Sicherheitseinstellungen werden zentral in wp_multi_register_admin_menus() registriert.

// Einstellungsseite unter Benutzer
function wp_multi_users_security_settings_page() {
    wpmt_admin_page_open(
        __('Benutzer-Sicherheit', 'wp-multi'),
        __('Brute-Force-Schutz und Benachrichtigungen für fehlgeschlagene Logins', 'wp-multi')
    );

    wpmt_admin_card_open(__('Brute-Force-Schutz', 'wp-multi'));
    ?>
    <p><?php _e('Verwalte die Einstellungen für den Schutz vor Brute-Force-Angriffen. Passe die Benachrichtigungen für fehlgeschlagene Anmeldeversuche an.', 'wp-multi'); ?></p>
    <form method="post" action="options.php">
        <?php
        settings_fields('wp_multi_users_settings_group');
        do_settings_sections('wp_multi_users_security_settings');
        submit_button(__('Einstellungen speichern', 'wp-multi'));
        ?>
    </form>
    <?php
    wpmt_admin_card_close();

    wpmt_admin_page_close();
}

// Anzeige der blockierten IPs im Admin-Bereich
function wp_multi_display_blocked_ips() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'blocked_ips';

    $five_days_ago = date('Y-m-d H:i:s', strtotime('-5 days'));
    $per_page = 50;
    $page = max(1, isset($_GET['paged']) ? intval($_GET['paged']) : 1);
    $offset = ($page - 1) * $per_page;

    $blocked_ips = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT * FROM $table_name WHERE last_attempt >= %s ORDER BY last_attempt DESC LIMIT %d OFFSET %d",
            $five_days_ago,
            $per_page,
            $offset
        )
    );

    $total_ips = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE last_attempt >= %s", $five_days_ago));
    $total_pages = ceil($total_ips / $per_page);

    wpmt_admin_page_open(
        __('Blockierte IPs', 'wp-multi'),
        __('Vom Brute-Force-Schutz erfasste IP-Adressen der letzten 5 Tage', 'wp-multi')
    );

    wpmt_admin_card_open();
    if (empty($blocked_ips)) {
        wpmt_admin_notice('info', __('Keine blockierten IPs gefunden.', 'wp-multi'));
    } else {
        ?>
        <div class="wpm-table-wrap">
            <table class="wpm-table">
                <thead>
                    <tr>
                        <th><?php _e('ID', 'wp-multi'); ?></th>
                        <th><?php _e('IP-Adresse', 'wp-multi'); ?></th>
                        <th><?php _e('Versuche', 'wp-multi'); ?></th>
                        <th><?php _e('Letzter Versuch', 'wp-multi'); ?></th>
                        <th><?php _e('Aktionen', 'wp-multi'); ?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($blocked_ips as $ip) : ?>
                        <tr>
                            <td><?php echo esc_html($ip->id); ?></td>
                            <td><?php echo esc_html($ip->ip); ?></td>
                            <td><span class="wpm-badge <?php echo $ip->attempts >= 5 ? 'wpm-badge--danger' : 'wpm-badge--warning'; ?>"><?php echo esc_html($ip->attempts); ?></span></td>
                            <td><?php echo esc_html($ip->last_attempt); ?></td>
                            <td>
                                <a class="wpm-btn wpm-btn--danger" href="<?php echo esc_url(wp_nonce_url(admin_url('admin-post.php?action=remove_blocked_ip&id=' . $ip->id), 'wp_multi_remove_blocked_ip_' . $ip->id)); ?>">
                                    <?php _e('Entfernen', 'wp-multi'); ?>
                                </a>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>

        <?php if ($total_pages > 1) : ?>
            <div class="tablenav">
                <div class="tablenav-pages">
                    <?php
                    echo paginate_links(array(
                        'base' => add_query_arg('paged', '%#%'),
                        'format' => '',
                        'prev_text' => __('«'),
                        'next_text' => __('»'),
                        'total' => $total_pages,
                        'current' => $page,
                    ));
                    ?>
                </div>
            </div>
        <?php endif; ?>
        <?php
    }
    wpmt_admin_card_close();

    // Aufräumen: alte Einträge mit wenigen Versuchen entfernen
    $three_days_ago = date('Y-m-d H:i:s', strtotime('-3 days'));
    $wpdb->query(
        $wpdb->prepare(
            "DELETE FROM $table_name WHERE attempts < 10 AND last_attempt < %s",
            $three_days_ago
        )
    );

    wpmt_admin_page_close();
}

// Funktion zum Entfernen einer blockierten IP
function wp_multi_remove_blocked_ip() {
    if (!current_user_can('manage_options')) {
        wp_die(__('Du hast nicht die erforderlichen Berechtigungen.', 'wp-multi'), '', array('response' => 403));
    }

    $id = isset($_GET['id']) ? intval($_GET['id']) : 0;

    if (!$id || !isset($_GET['_wpnonce']) || !wp_verify_nonce(wp_unslash($_GET['_wpnonce']), 'wp_multi_remove_blocked_ip_' . $id)) {
        wp_die(__('Ungültige oder abgelaufene Anfrage.', 'wp-multi'), '', array('response' => 403));
    }

    global $wpdb;

    if ($id > 0) {
        $table_name = $wpdb->prefix . 'blocked_ips';
        $wpdb->delete($table_name, array('id' => $id), array('%d'));
    }

    wp_safe_redirect(admin_url('admin.php?page=wp_multi_blocked_ips'));
    exit;
}
add_action('admin_post_remove_blocked_ip', 'wp_multi_remove_blocked_ip');


