<?php

if (!defined('ABSPATH')) {
    exit; // Pas d'accès direct !
}

// Hook pour bloquer une IP déjà blacklistée avant même la vérification du mot de passe
function hpixl_securicheck_authenticate($user, $username, $password)
{
    if (!(bool) get_option('hpixl_securicheck_toggle_brute_force', false)) {
        return $user;
    }

    $ip = hpixl_securicheck_get_ip();
    if (empty($ip)) return $user;

    $blocked_until = get_transient('blocked_ip_' . $ip);
    if ($blocked_until !== false) {
        $remaining = max(0, $blocked_until - time());

        $title = __('Accès refusé', 'securicheck');
        $message = sprintf(
            __('Votre adresse IP (%1$s) a été temporairement bloquée en raison de trop nombreuses tentatives de connexion. Réessayez dans %2$d secondes.', 'securicheck'),
            esc_html($ip),
            $remaining
        );

        wp_die(
            '<div style="text-align:center;padding:30px;">' .
                '<h1>' . esc_html($title) . '</h1>' .
                '<p style="font-size:16px;">' . wp_kses_post($message) . '</p>' .
                '<p><small>' . esc_html__('Si vous pensez qu\'il s\'agit d\'une erreur, contactez l\'administrateur.', 'securicheck') . '</small></p>' .
                '</div>',
            esc_html($title),
            array('response' => 403)
        );
    }

    return $user;
}
add_filter('authenticate', 'hpixl_securicheck_authenticate', 1, 3);

// Vérifie après un échec confirmé par WP si le seuil est atteint, et bloque si c'est le cas.
// Priorité 20 : s'exécute après le log de l'échec dans connexions-logs.php (priorité 10).
function hpixl_securicheck_check_block_after_failure($username)
{
    global $wpdb;

    if (!(bool) get_option('hpixl_securicheck_toggle_brute_force', false)) {
        return;
    }

    $ip = hpixl_securicheck_get_ip();
    if (empty($ip)) return;

    // L'IP est déjà bloquée par un processus concurrent : évite une requête DB inutile.
    if (get_transient('blocked_ip_' . $ip) !== false) return;

    // Blocage immédiat si tentative avec le nom "admin" et qu'aucun vrai compte admin n'existe.
    if (
        (bool) get_option('hpixl_securicheck_toggle_block_ip_connexion_admin', false)
        && $username === 'admin'
        && ! username_exists('admin')
    ) {
        $block_minutes = (int) get_option('hpixl_securicheck_text_duree_blocage_brute_force', 60);
        $block_seconds = $block_minutes * MINUTE_IN_SECONDS;
        set_transient('blocked_ip_' . $ip, time() + $block_seconds, $block_seconds);
        $raison = __('Tentative de connexion avec le compte "admin"', 'securicheck');
        hpixl_securicheck_log_blocage_ip($ip, $raison, $block_seconds);

        $destinataire        = get_option('admin_email');
        $option_ip_bloquee   = get_option('hpixl_securicheck_toggle_notifications_ip_bloquee');
        $option_destinataire = get_option('hpixl_securicheck_destinataire_email_notifications');
        if (!empty($option_ip_bloquee)) {
            if (!empty($option_destinataire) && hpixl_securicheck_is_valid_email($option_destinataire)) {
                $destinataire = $option_destinataire;
            }
            hpixl_securicheck_envoi_mail_blocage_ip($destinataire, $ip, $raison);
        }

        $title   = __('Accès refusé', 'securicheck');
        $message = sprintf(
            __('Votre adresse IP (%1$s) a été temporairement bloquée en raison de trop nombreuses tentatives de connexion. Réessayez dans %2$d secondes.', 'securicheck'),
            esc_html($ip),
            $block_seconds
        );
        wp_die(
            '<div style="text-align:center;padding:30px;">' .
                '<h1>' . esc_html($title) . '</h1>' .
                '<p style="font-size:16px;">' . wp_kses_post($message) . '</p>' .
                '<p><small>' . esc_html__('Si vous pensez qu\'il s\'agit d\'une erreur, contactez l\'administrateur.', 'securicheck') . '</small></p>' .
                '</div>',
            esc_html($title),
            array('response' => 403)
        );
    }

    $max_attempts     = (int) get_option('hpixl_securicheck_text_max_tentatives_brute_force', 5);
    $periode_attempts = (int) get_option('hpixl_securicheck_text_periode_tentatives_brute_force', 5);
    $block_minutes    = (int) get_option('hpixl_securicheck_text_duree_blocage_brute_force', 300);

    // Date de reset (si débloquée manuellement)
    // Stockée en datetime WP local depuis la v2.2.0 ; support du format hérité (timestamp Unix)
    $reset_val  = get_transient('hpixl_securicheck_reset_' . $ip);
    if (!empty($reset_val)) {
        $reset_date = is_numeric($reset_val)
            ? wp_date('Y-m-d H:i:s', (int) $reset_val) // ancien format : conversion UTC→WP local
            : (string) $reset_val;                      // nouveau format : datetime WP local direct
    } else {
        $reset_date = '1970-01-01 00:00:00';
    }

    $periode_attempts_seconds = $periode_attempts * MINUTE_IN_SECONDS;
    $tableLogConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;

    // Compter les échecs récents — la tentative courante est déjà loguée (priorité 10)
    $attempts = (int) $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM {$tableLogConnexions}
         WHERE ip = %s
           AND etat = %s
           AND date > %s
           AND date > DATE_SUB(NOW(), INTERVAL %d SECOND)",
        $ip,
        'failed',
        $reset_date,
        $periode_attempts_seconds
    ));

    if ($attempts < $max_attempts) {
        return;
    }

    // Seuil atteint : bloquer l'IP
    $block_seconds = $block_minutes * MINUTE_IN_SECONDS;
    set_transient('blocked_ip_' . $ip, time() + $block_seconds, $block_seconds);
    $raison = sprintf(_n('%d tentative de connexion échouée', '%d tentatives de connexion échouées', $attempts, 'securicheck'), $attempts);
    hpixl_securicheck_log_blocage_ip($ip, $raison, $block_seconds);

    // Envoi mail de blocage si configuré
    $destinataire        = get_option('admin_email');
    $option_ip_bloquee   = get_option('hpixl_securicheck_toggle_notifications_ip_bloquee');
    $option_destinataire = get_option('hpixl_securicheck_destinataire_email_notifications');
    if (!empty($option_ip_bloquee)) {
        if (!empty($option_destinataire) && hpixl_securicheck_is_valid_email($option_destinataire)) {
            $destinataire = $option_destinataire;
        }
        hpixl_securicheck_envoi_mail_blocage_ip($destinataire, $ip, $raison);
    }

    $title   = __('Accès refusé', 'securicheck');
    $message = sprintf(
        __('Votre adresse IP (%1$s) a été temporairement bloquée en raison de trop nombreuses tentatives de connexion. Réessayez dans %2$d secondes.', 'securicheck'),
        esc_html($ip),
        $block_seconds
    );

    wp_die(
        '<div style="text-align:center;padding:30px;">' .
            '<h1>' . esc_html($title) . '</h1>' .
            '<p style="font-size:16px;">' . wp_kses_post($message) . '</p>' .
            '<p><small>' . esc_html__('Si vous pensez qu\'il s\'agit d\'une erreur, contactez l\'administrateur.', 'securicheck') . '</small></p>' .
            '</div>',
        esc_html($title),
        array('response' => 403)
    );
}
add_action('wp_login_failed', 'hpixl_securicheck_check_block_after_failure', 20);

// Connexion réussie : remet le compteur à zéro pour éviter que d'anciennes tentatives
// échouées ne provoquent un blocage lors d'une prochaine session.
function hpixl_securicheck_reset_counter_on_login($username, $user)
{
    if (!(bool) get_option('hpixl_securicheck_toggle_brute_force', false)) {
        return;
    }

    $ip = hpixl_securicheck_get_ip();
    if (!empty($ip)) {
        hpixl_securicheck_reset_ip_counter($ip);
    }
}
add_action('wp_login', 'hpixl_securicheck_reset_counter_on_login', 10, 2);

//remplacer complètement la page de connexion par une page personnalisée when blocked
add_action('login_init', 'hpixl_securicheck_replace_login_if_blocked');
function hpixl_securicheck_replace_login_if_blocked()
{

    // Vérifier si la protection brute force est activée
    if (!(bool) get_option('hpixl_securicheck_toggle_brute_force', false)) {
        return; // Protection désactivée
    }

    $ip = hpixl_securicheck_get_ip();
    if (empty($ip)) return;

    $transient_key = 'blocked_ip_' . $ip;
    $blocked_until = get_transient($transient_key);
    if ($blocked_until === false) return;

    $remaining = max(0, $blocked_until - time());

    $title = __('Accès refusé', 'securicheck');
    $message = sprintf(
        __('Votre adresse IP (%1$s) a été temporairement bloquée en raison de trop nombreuses tentatives de connexion. Réessayez dans %2$d secondes.', 'securicheck'),
        esc_html($ip),
        $remaining
    );

    wp_die(
        '<div style="text-align:center;padding:30px;">' .
            '<h1>' . esc_html($title) . '</h1>' .
            '<p style="font-size:16px;">' . wp_kses_post($message) . '</p>' .
            '<p><small>' . esc_html__('Si vous pensez qu\'il s\'agit d\'une erreur, contactez l\'administrateur.', 'securicheck') . '</small></p>' .
            '</div>',
        esc_html($title),
        array('response' => 403)
    );
}



/**
 * Remet à zéro le compteur d'échecs pour une IP (connexion réussie ou déblocage manuel).
 * Stocké en datetime WP local pour être cohérent avec les dates en base de données.
 */
function hpixl_securicheck_reset_ip_counter($ip)
{
    set_transient('hpixl_securicheck_reset_' . $ip, current_time('mysql'), DAY_IN_SECONDS);
}

/**
 * Débloque une IP manuellement : supprime le transient de blocage, remet le compteur
 * à zéro et envoie une notification email si configurée.
 */
function hpixl_securicheck_debloquer_ip($ip)
{
    delete_transient('blocked_ip_' . $ip);
    hpixl_securicheck_reset_ip_counter($ip);
    $current_user = wp_get_current_user();
    $auteur = ($current_user && $current_user->ID) ? $current_user->user_login : 'Securicheck';
    hpixl_securicheck_log_deblocage_ip($ip, $auteur, "Manuel");

    $destinataire        = get_option('admin_email');
    $option_ip_debloquee = get_option('hpixl_securicheck_toggle_notifications_ip_debloquee');
    $option_destinataire = get_option('hpixl_securicheck_destinataire_email_notifications');
    if (!empty($option_ip_debloquee)) {
        if (!empty($option_destinataire) && hpixl_securicheck_is_valid_email($option_destinataire)) {
            $destinataire = $option_destinataire;
        }
        hpixl_securicheck_envoi_mail_deblocage_ip($destinataire, $ip, $auteur);
    }
}

/**
 * on envoie un e-mail au destinataire en paramètre
 */
function hpixl_securicheck_envoi_mail_blocage_ip($destinataire, $ip, $raison)
{
    $site_name = get_bloginfo('name');
    $admin_email = get_option('admin_email');
    $user_email = $destinataire;
    //si email non valide on défini le destinataire comme l'administrateur
    if (!hpixl_securicheck_is_valid_email($user_email)) {
        $user_email = $admin_email;
    }

    $headers = array(
        'Content-Type: text/html; charset=UTF-8',
        __('From: WP Securicheck : nouveau blocage IP <', 'securicheck') . $admin_email . '>'
    );

    $subject = __('Blocage d\'une nouvelle IP pour le site ', 'securicheck') . $site_name . ' !';
    $body = hpixl_securicheck_create_email_body_blocage_ip($ip, $raison);

    wp_mail($user_email, $subject, $body, $headers);
}

function hpixl_securicheck_create_email_body_blocage_ip($ip, $raison)
{
    $recipient_user = get_user_by('email', get_option('admin_email'));
    $recipient_firstname = $recipient_user ? $recipient_user->user_firstname : '';

    ob_start();

    include(plugin_dir_path(dirname(__FILE__)) . 'utils/mail_ip_bloquee.php');

    $body = ob_get_contents();

    ob_end_clean();
    return $body;
}


/**
 * on envoie un e-mail au destinataire en paramètre
 */
function hpixl_securicheck_envoi_mail_deblocage_ip($destinataire, $ip, $userAction)
{
    $site_name = get_bloginfo('name');
    $admin_email = get_option('admin_email');
    $user_email = $destinataire;
    /*$userAction = "";

    $current_user = wp_get_current_user();

    if ($current_user && $current_user->ID) {
        $userAction = $current_user->user_login;
    }*/

    //si email non valide on défini le destinataire comme l'administrateur
    if (!hpixl_securicheck_is_valid_email($user_email)) {
        $user_email = $admin_email;
    }

    $headers = array(
        'Content-Type: text/html; charset=UTF-8',
        __('From: WP Securicheck : déblocage IP <', 'securicheck') . $admin_email . '>'
    );

    $subject = __('Déblocage d\'une nouvelle IP pour le site ', 'securicheck') . $site_name . ' !';
    $body = hpixl_securicheck_create_email_body_deblocage_ip($ip, $userAction);

    wp_mail($user_email, $subject, $body, $headers);
}

function hpixl_securicheck_create_email_body_deblocage_ip($ip, $userAction)
{
    $recipient_user = get_user_by('email', get_option('admin_email'));
    $recipient_firstname = $recipient_user ? $recipient_user->user_firstname : '';

    ob_start();

    include(plugin_dir_path(dirname(__FILE__)) . 'utils/mail_ip_debloquee.php');

    $body = ob_get_contents();

    ob_end_clean();
    return $body;
}

/**
 * Logue un blocage d'IP dans la table securicheck_brute_force_logs
 */
function hpixl_securicheck_log_blocage_ip($ip, $raison, $duree_blocage)
{
    global $wpdb;
    $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_BRUTE_FORCE_LOGS;
    $wpdb->insert($table, [
        'ip'            => $ip,
        'action'        => 'blocage',
        'date_action'   => current_time('mysql'),
        'auteur_action' => 'Securicheck',
        'raison'        => $raison,
        'duree_blocage' => $duree_blocage,
    ]);
}

/**
 * Logue un déblocage d'IP dans la table securicheck_brute_force_logs
 */
function hpixl_securicheck_log_deblocage_ip($ip, $auteur, $raison)
{
    global $wpdb;
    $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_BRUTE_FORCE_LOGS;
    $wpdb->insert($table, [
        'ip'            => $ip,
        'action'        => 'deblocage',
        'date_action'   => current_time('mysql'),
        'auteur_action' => $auteur,
        'raison'        => $raison,
        'duree_blocage' => null,
    ]);
}
