<?php

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

//change le format de date
function hpixl_securicheck_format_date($date)
{
    /*  // Convertit la date au format timestamp Unix
    $timestamp = strtotime($date);

    // Formatte la date au format d-m-Y H:i:s
    $formatter = new IntlDateFormatter('fr_FR', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
    datefmt_set_pattern($formatter, 'dd MMMM yyyy kk:mm:ss');
    $formatted_date = $formatter->format($timestamp);

    return $formatted_date;*/
    $timestamp = strtotime($date);

    if (class_exists('IntlDateFormatter')) {
        // Utilisation de IntlDateFormatter si disponible
        $formatter = new IntlDateFormatter('fr_FR', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
        datefmt_set_pattern($formatter, 'dd MMMM yyyy kk:mm:ss');
        return $formatter->format($timestamp);
    } else {
        // Alternative sans strftime()
        $dt = new DateTime($date);

        $mois_fr = [
            'January' => 'janvier',
            'February' => 'février',
            'March' => 'mars',
            'April' => 'avril',
            'May' => 'mai',
            'June' => 'juin',
            'July' => 'juillet',
            'August' => 'août',
            'September' => 'septembre',
            'October' => 'octobre',
            'November' => 'novembre',
            'December' => 'décembre'
        ];
        $mois = $mois_fr[date('F', $dt->getTimestamp())] ?? date('F', $dt->getTimestamp());

        return $dt->format('d') . ' ' . $mois . ' ' . $dt->format('Y H:i:s');
    }
}

// Fonction pour vérifier si le répertoire de téléchargement des plugins est protégé
function hpixl_securicheck_checkPluginDir()
{
    $plugins_dir = plugins_url('/');

    /*  $dir_exists = wp_remote_get($plugins_dir);
    return (!(wp_remote_retrieve_response_code($dir_exists) === 200));*/
    $response = wp_remote_get($plugins_dir, [
        'timeout'     => 5,
        'redirection' => 0,
    ]);

    if (is_wp_error($response)) {
        return true; // Inaccessible = protégé
    }

    return wp_remote_retrieve_response_code($response) !== 200;
}

// Fonction pour vérifier si le répertoire uploads est protégé
function hpixl_securicheck_isUploadsDirProtected()
{
    // Chemin vers le répertoire des uploads
    $uploads_dir = wp_upload_dir()['basedir'];
    $uploads_url = wp_upload_dir()['baseurl'];

    // Nom du fichier de test
    $test_file_name = 'test_php_execution.php';
    $test_file_path = $uploads_dir . '/' . $test_file_name;
    $test_file_url = $uploads_url . '/' . $test_file_name;

    // Contenu PHP à insérer dans le fichier de test
    $test_file_content = "<?php echo 'PHP execution allowed'; ?>";

    // Crée le fichier PHP de test
    file_put_contents($test_file_path, $test_file_content);

    // Effectue une requête HTTP pour tenter d'exécuter le fichier PHP
    $response = wp_remote_get($test_file_url);

    // Supprime le fichier de test
    unlink($test_file_path);

    // Vérifie si l'exécution PHP a été autorisée ou non
    if (is_wp_error($response)) {
        return false; // Erreur lors de la requête
    }

    /* $body = wp_remote_retrieve_body($response);
    // Si la réponse contient "PHP execution allowed", alors PHP est exécuté
    if (strpos($body, 'PHP execution allowed') !== false) {
        return false; // PHP s'exécute dans le répertoire uploads
    }

    return true; // PHP est bloqué dans le répertoire uploads*/

    $http_code = wp_remote_retrieve_response_code($response);
    $body      = wp_remote_retrieve_body($response);

    // PHP bloqué = 403 (deny all) ou 404
    if (in_array($http_code, [403, 404], true)) {
        return true;
    }

    // PHP exécuté = 200 + contenu dans le body
    if ($http_code === 200 && strpos($body, 'PHP execution allowed') !== false) {
        return false;
    }

    return true; // cas inattendu


}

// Fonction pour vérifier si XML-RPC est désactivé
function hpixl_securicheck_checkXmlRpcDisabled()
{
    $xmlrpc_url = home_url() . '/xmlrpc.php';

    $response = wp_remote_head($xmlrpc_url, [
        'timeout'     => 10,
        'redirection' => 0,
    ]);

    if (is_wp_error($response)) {
        return true; // inaccessible = désactivé
    }

    $http_code = wp_remote_retrieve_response_code($response);
    //error_log("httpcode: " . $http_code);
    return in_array($http_code, [301, 308, 403, 404, 503, 502], true);
}

// Fonction pour vérifier que la navigation dans les dossiers est impossible
function hpixl_securicheck_checkDirectoryListing()
{
    $wp_includes_dir = includes_url();

    $response = wp_remote_get($wp_includes_dir, [
        'timeout'     => 5,
        'redirection' => 0,
    ]);

    if (is_wp_error($response)) {
        return true; // inaccessible = protégé
    }

    $http_code = wp_remote_retrieve_response_code($response);

    // 403 explicite = protégé
    if ($http_code === 403) {
        return true;
    }

    // Vérifier si le body contient un vrai listing Nginx/Apache
    $body = wp_remote_retrieve_body($response);
    if (stripos($body, 'Index of /') !== false) {
        return false; // listing visible = non protégé
    }

    // 200 sans listing = WordPress a intercepté = listing impossible = protégé
    return true;
}

// Fonction pour vérifier si wp-config.php est protégé
function hpixl_securicheck_checkWpConfigProtection()
{
    $wp_config_path = home_url('/wp-config.php');

    $wp_config_exists = wp_remote_get($wp_config_path, [
        'timeout'     => 5,
        'redirection' => 0,
    ]);

    if (is_wp_error($wp_config_exists)) {
        return true; // inaccessible = protégé
    }

    $http_code = wp_remote_retrieve_response_code($wp_config_exists);

    // Si HTTP 200 → exposé
    return $http_code !== 200;
}

// Fonction pour vérifier si .htaccess est protégé
function hpixl_securicheck_checkHtaccessProtection()
{

    $htaccess_path = home_url('/.htaccess');

    $htaccess_exists = wp_remote_get($htaccess_path, [
        'timeout'     => 5,
        'redirection' => 0,
    ]);

    if (is_wp_error($htaccess_exists)) {
        return true; // inaccessible = protégé
    }

    $http_code = wp_remote_retrieve_response_code($htaccess_exists);

    // 200 = exposé, autre code = protégé
    return $http_code !== 200;
}

//Fonction pour vérifier si la version de PHP est cachée
function hpixl_securicheck_versionPhpHidden()
{
    $server_info = get_headers(home_url(), 1);

    return !isset($server_info['X-Powered-By']);
}


//Fonction pour vérifier si la version de apache est cachée
/*function hpixl_securicheck_versionApacheHidden()
{
    // Récupérer les en-têtes HTTP du site
    $server_info = get_headers(home_url(), 1);

    // Vérifier si l'en-tête 'Server' est présent
    if (isset($server_info['Server'])) {
        // Vérifier si l'en-tête contient "Apache" suivi d'une version
        if (preg_match('/Apache\/[0-9\.]+/', $server_info['Server'])) {
            return false; // La version d'Apache est visible dans l'en-tête 'Server'
        }
    }

    return true; // Soit l'en-tête ne contient pas "Apache", soit il n'a pas de version

}*/

// Fonction pour vérifier si les informations relatives au serveur sont cachées
function hpixl_securicheck_checkServerSignatureHidden()
{
    /*   // Chemin vers le fichier .htaccess à la racine de votre site WordPress
    $htaccess_file = ABSPATH . '.htaccess';

    // Vérifier si le fichier .htaccess existe
    if (!file_exists($htaccess_file)) {
        return false;
    }

    // Lire le contenu du fichier .htaccess
    $htaccess_content = file_get_contents($htaccess_file);

    // Vérifier si "ServerSignature Off" est présent
    if (strpos($htaccess_content, 'ServerSignature Off') !== false) {
        return true;
    } else {
        return false;
    }*/


    $response = wp_remote_get(home_url('/'), [
        'timeout'     => 5,
        'redirection' => 0,
    ]);

    if (is_wp_error($response)) {
        return false;
    }

    $server_header = wp_remote_retrieve_header($response, 'server');

    if (empty($server_header)) {
        return true;
    }

    // Détecter si un serveur web connu expose sa version : Apache/2.4.51, nginx/1.18.0, etc.
    if (preg_match('/\b(Apache|nginx|LiteSpeed|Microsoft-IIS|OpenResty|lighttpd)\/[\d\.]+/i', $server_header)) {
        return false;
    }

    return true;
}



// Fonction pour vérifier si l'api rest est bien désactivée
function hpixl_securicheck_checkRestApiDisabled()
{
    $rest_url = trailingslashit(home_url('wp-json'));

    // Tente d'accéder à une URL de l'API REST
    $response = wp_remote_get($rest_url, [
        'timeout'     => 5,
        'redirection' => 0,
    ]);
    $apidesactiveeTotale = (wp_remote_retrieve_response_code($response) !== 200);

    // Vérifie si l'API REST est partiellement désactivée en vérifiant si le endpoint "user" est accessible
    $response_user = wp_remote_get($rest_url . 'wp/v2/posts', [
        'timeout'     => 5,
        'redirection' => 0,
    ]);
    $apidesactiveePartielle = (wp_remote_retrieve_response_code($response_user) !== 200);

    // Retourne le code :
    // 1 = totalement désactivée
    // 2 = partiellement désactivée
    // 0 = activée
    return $apidesactiveeTotale ? 1 : ($apidesactiveePartielle ? 2 : 0);
}

//vérifie si l'editeur de fichier est bien désactivé
function hpixl_securicheck_isEditeurFichierDisabled()
{
    // Vérifie si la constante DISALLOW_FILE_EDIT est définie à true
    if (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT === true) {
        return true;
    } else {
        return false;
    }
}

//fonction qui vérifie si chatgpt a accés au site
function hpixl_securicheck_is_accessible_by_chatgpt()
{
    $site_url = home_url();

    $response = wp_remote_get($site_url, [
        'timeout' => 15,
        'redirection' => 0,
        'headers' => [
            'User-Agent' => 'ChatGPT-User', // Définir le User-Agent comme ChatGPT
            // 'User-Agent' => 'OpenAI ChatGPT', // Définir le User-Agent comme ChatGPT
        ],
    ]);

    if (is_wp_error($response)) {
        return false; // inaccessible
    }

    // Vérification de la réponse
    $http_code = wp_remote_retrieve_response_code($response);

    return $http_code === 200;
}


// Fonction pour vérifier si le hotlinking est désactivé
function hpixl_securicheck_checkHotlinkingDisabled()
{

    // URL de l'image
    $image_url = "";
    $urlHotlinking = get_option('hpixl_securicheck_hotlinking_image_url') ?? '';
    if ($urlHotlinking != "") {
        $image_url = $urlHotlinking;
    } else {
        return HPIXL_SECURICHECK_HOTLINKING_PARAMETRE_NON_DEFINI;
    }

    //check existence de l'image
    $relative_path = wp_parse_url($image_url, PHP_URL_PATH);
    // Convertir le chemin relatif en chemin de fichier local
    $image_path = ABSPATH . ltrim($relative_path, '/');

    // si l'image n'existe pas
    if (!file_exists($image_path)) {
        return HPIXL_SECURICHECK_HOTLINKING_IMAGE_NON_PRESENTE;
    }

    // URL du site tiers qui tente de hotlinker
    $referer_url = "toto";

    // Exécution de la requête avec wp_remote_get
    $response = wp_remote_get($image_url, array(
        'timeout' => 15, // Temps d'attente en secondes
        'headers' => array(
            'Referer' => $referer_url,
        ),
    ));


    // Vérification de la réponse
    if (wp_remote_retrieve_response_code($response) === 200) {
        return "non"; // Hotlinking n'est pas bloqué
    } else {
        return "oui"; // Hotlinking est bloqué
    }
}

//fonction qui renvoie la version de php
function hpixl_securicheck_get_php_version()
{
    $php_version = phpversion();
    if ($php_version) {
        return $php_version;
    } else {
        return __('Version de PHP non trouvée', 'securicheck');
    }
}

//fonction qui renvoie le serveur web utilisé
function hpixl_securicheck_get_web_server()
{
    /*  if (! empty($_SERVER['SERVER_SOFTWARE'])) {
        $server = explode('/', $_SERVER['SERVER_SOFTWARE']);
        return sanitize_text_field($server[0]);
    }

    return 'Inconnu';*/
    // 1️⃣ SERVER_SOFTWARE
    if (! empty($_SERVER['SERVER_SOFTWARE'])) {

        $software = strtolower($_SERVER['SERVER_SOFTWARE']);

        if (strpos($software, 'litespeed') !== false) {
            return 'LiteSpeed';
        }

        if (strpos($software, 'nginx') !== false) {
            return 'Nginx';
        }

        if (strpos($software, 'apache') !== false) {
            return 'Apache';
        }

        if (strpos($software, 'iis') !== false) {
            return 'IIS';
        }
    }

    // 2️⃣ Variable spécifique LiteSpeed
    if (isset($_SERVER['LSWS_EDITION'])) {
        return 'LiteSpeed';
    }

    // 3️⃣ Fonction Apache disponible
    if (function_exists('apache_get_version')) {
        return 'Apache';
    }

    // 4️⃣ Modules Apache
    if (function_exists('apache_get_modules')) {
        return 'Apache';
    }

    // 5️⃣ Variables Nginx spécifiques
    if (isset($_SERVER['NGINX_VERSION'])) {
        return 'Nginx';
    }

    // 6️⃣ Windows IIS
    if (isset($_SERVER['SERVER_SOFTWARE']) && stripos($_SERVER['SERVER_SOFTWARE'], 'microsoft-iis') !== false) {
        return 'IIS';
    }

    return 'Inconnu';
}

function hpixl_securicheck_get_php_sapi()
{
    return PHP_SAPI;
}

// Fonction qui renvoie la version TLS utilisée par le serveur pour HTTPS
function hpixl_securicheck_get_tls_version()
{
    if (!function_exists('curl_version')) {
        return 'cURL non disponible';
    }

    $url = home_url();
    $versions = [
        130 => '1.3', // CURL_SSLVERSION_TLSv1_3
        120 => '1.2', // CURL_SSLVERSION_TLSv1_2
        110 => '1.1', // CURL_SSLVERSION_TLSv1_1
        100 => '1.0', // CURL_SSLVERSION_TLSv1_0
    ];

    foreach ($versions as $curl_const => $version) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_SSLVERSION => $curl_const,
        ]);
        curl_exec($ch);
        $errno = curl_errno($ch);
        curl_close($ch);

        if ($errno === 0) {
            return $version; // La version TLS qui a réussi
        }
    }

    return __('Version TLS non trouvée', 'securicheck');
}

//fonction qui renvoie la version de la bdd
function hpixl_securicheck_get_bdd_version()
{
    global $wpdb;
    $info = $wpdb->db_server_info();
    preg_match('/^[\d.]+/', $info, $matches);
    return $matches[0] ?? 'N/A';
}

//fonction qui renvoie si la bdd est MariaDB ou Mysql
function hpixl_securicheck_get_bdd_type()
{
    global $wpdb;
    $info = $wpdb->db_server_info();

    if (stripos($info, 'mariadb') !== false) {
        return 'MariaDB';
    }

    if (! empty($info)) {
        return 'MySQL';
    }

    return 'N/A';

    /*   $infos = explode("-", $info);

    if ($infos && $infos[1])
        return $infos[1];
    else
        return "N/A";*/
}

//fonction qui renvoie l'espace disque utilé par le site
function hpixl_securicheck_get_space_usage()
{
    $wordpress_root = ABSPATH; // Chemin vers le répertoire racine de WordPress
    $total_space = 0;

    // Fonction récursive pour parcourir les fichiers et répertoires
    $calculate_space = function ($path) use (&$calculate_space, &$total_space) {
        foreach (scandir($path) as $file) {
            if ($file === '.' || $file === '..') {
                continue;
            }
            $full_path = $path . '/' . $file;
            if (is_dir($full_path)) {
                $calculate_space($full_path);
            } else {
                $total_space += filesize($full_path);
            }
        }
    };

    // Calcul de l'espace utilisé
    $calculate_space($wordpress_root);

    // Conversion de l'espace utilisé en une chaîne lisible par l'homme (par exemple, en mégaoctets ou en gigaoctets)
    $used_space_human_readable = hpixl_securicheck_format_bytes($total_space);

    return $used_space_human_readable;
}

// Fonction pour formater les octets en une chaîne lisible par l'homme (Mo, Go, etc.)
function hpixl_securicheck_format_bytes($bytes, $precision = 2)
{
    $units = array('B', 'KB', 'MB', 'GB', 'TB');

    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);

    $bytes /= (1 << (10 * $pow));

    return round($bytes, $precision) . ' ' . $units[$pow];
}

//fonction qui renvoie l'espace disque utilé par la bdd du site
function hpixl_securicheck_get_database_disk_usage()
{
    global $wpdb;

    // Récupération de toutes les tables WordPress
    // Définir une clé de cache unique pour cette requête
    $cache_key = 'securicheck_all_wp_tables_status';
    // Tenter de récupérer les résultats du cache
    $tables = wp_cache_get($cache_key);
    if ($tables === false) {
        // Si les résultats ne sont pas en cache, effectuer la requête
        $tables = $wpdb->get_results("SHOW TABLE STATUS");
        // Mettre en cache les résultats pour une utilisation future
        wp_cache_set($cache_key, $tables, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
    }

    $total_size = 0;

    // Calcul de la taille totale de toutes les tables
    foreach ($tables as $table) {
        $total_size += $table->Data_length + $table->Index_length;
    }

    // Conversion de la taille en une chaîne lisible par l'homme (Mo, Go, etc.)
    $disk_usage_human_readable = hpixl_securicheck_format_bytes($total_size);

    return $disk_usage_human_readable;
}

//fonction qui compte le nombre de plugins à mettre à jour
function hpixl_securicheck_get_nb_maj_plugins()
{
    $plugins_with_updates = get_plugin_updates();
    $update_count = count($plugins_with_updates);
    return $update_count;
    return 0;
}

//fonction qui compte le nombre de plugins à mettre à jour
function hpixl_securicheck_get_nb_maj_themes()
{
    $plugins_with_updates = get_theme_updates();
    $update_count = count($plugins_with_updates);
    return $update_count;
    return 0;
}
//fonction qui récupère si le wordpress est à mettre à jour
function hpixl_securicheck_get_nb_maj_wordpress()
{
    // Récupération de la version actuelle de WordPress
    $current_version = get_bloginfo('version');

    // Récupération de la dernière version stable de WordPress
    $latest_version = get_core_updates();
    $latest_version = !empty($latest_version) ? $latest_version[0]->current : '';

    // Vérification si une mise à jour est disponible
    if (version_compare($current_version, $latest_version, '<')) {
        return 1;
    } else {
        return 0;
    }
}

//fonction qui récupère les informations du thème actif
function hpixl_securicheck_get_theme_info()
{
    $theme_info = wp_get_theme();
    $nom_theme = $theme_info->name;
    $titre_theme = $theme_info->title;
    $version_theme = $theme_info->version;
    $theme_enfant = hpixl_securicheck_is_child_theme_installed();
    $theme_parent = $theme_info->get_template();
    return $nom_theme . "-" . $titre_theme . "-" . $version_theme . " - theme enfant : " . $theme_enfant . " - theme parent : " . $theme_parent;
}

//fonction qui récupére le nom du theme actuel
function hpixl_securicheck_get_theme_name()
{
    $theme_info = wp_get_theme();
    return $theme_info->name;
}

//fonction qui récupére le nom du theme parent
function hpixl_securicheck_get_theme_parent()
{
    $theme_info = wp_get_theme();
    return $theme_info->get_template();
}

//fonction qui vérifie si un thèe enfant est installé
function hpixl_securicheck_is_child_theme_installed()
{
    // Récupération du nom du thème actuellement activé
    $active_theme = get_stylesheet();

    // Vérification si le thème actif est un thème enfant
    $parent_theme = wp_get_theme($active_theme)->get('Template');
    if ($parent_theme) {
        return "oui"; // Le thème actif est un thème enfant
    } else {
        return "non"; // Le thème actif n'est pas un thème enfant
    }
}

//fonction permettant de récupérer le nombre de plugins inactifs
function hpixl_securicheck_get_disabled_plugins_count()
{
    // Récupération de la liste des plugins
    $plugins = get_plugins();

    $disabled_count = 0;

    // Parcours des plugins pour vérifier s'ils sont désactivés
    foreach ($plugins as $plugin_file => $plugin_info) {
        if (!is_plugin_active($plugin_file)) {
            $disabled_count++;
        }
    }

    return $disabled_count;
}

//fonction permettant de récupérer le nombre de themes inactifs
function hpixl_securicheck_get_disabled_themes_count()
{
    //le theme actif
    $theme_info = wp_get_theme();
    $nom_theme = $theme_info->name;
    // Récupération de la liste de tous les thèmes installés
    $themes = wp_get_themes();

    $disabled_count = 0;

    foreach ($themes as $theme) {
        if (!$theme->is_active && $nom_theme != $theme->get('Name')) {
            $disabled_count++;
        }
    }

    return $disabled_count;
}

//le site est il en https ?
function hpixl_securicheck_isHTTPSUrl()
{
    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
        return true;
    } elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        return true;
    } elseif (isset($_SERVER['HTTP_FRONT_END_HTTPS']) && $_SERVER['HTTP_FRONT_END_HTTPS'] === 'on') {
        return true;
    }

    return false;
}

// récupère le prefixe des tables en bdd
function hpixl_securicheck_getBddPrefix()
{
    global $wpdb;
    return $wpdb->prefix;
}

// teste si un compte "admin" existe
function hpixl_securicheck_compteAdminExiste()
{
    $users = get_users([
        'search'         => 'admin',
        'search_columns' => ['user_login'],
        'number'         => 1, // On ne récupère qu'un seul utilisateur
    ]);

    return !empty($users);
}

//retourne le nombre d'administrateurs du site
function hpixl_securicheck_nombreAdministrateurs()
{

    $administrateurs = get_users([
        'role'   => 'administrator',
        'fields' => 'ID',  // on ne récupère que l'ID, plus léger
    ]);

    return count($administrateurs);
}

//vérifie si on est en mode debug ou non
function hpixl_securicheck_debugActif()
{
    // Vérifie si le mode debug est activé
    if (defined('WP_DEBUG') && WP_DEBUG === true) {
        return true;
    } else {
        return false;
    }
}

//protection du live writer ?
function hpixl_securicheck_isLiveWriterProtected()
{
    // Vérifie si l'action de suppression du lien wlwmanifest a été ajoutée dans functions.php
    return !has_action('wp_head', 'wlwmanifest_link'); // Cela signifie que la protection est en place
}

//l'url du backoffice
function hpixl_securicheck_isBackEndUrlHidden()
{
    $admin_url = get_admin_url();
    $max_redirects = 10; // Nombre maximum de redirections
    $current_url = $admin_url;
    $redirect_count = 0;

    while ($redirect_count < $max_redirects) {
        // Exécution de la requête avec wp_remote_get
        $response = wp_remote_get($current_url, array(
            'timeout' => 15,
            'headers' => array(
                'User-Agent' => 'Mozilla/5.0',
            ),
            'method' => 'HEAD',
            'redirection' => 0, // Ne pas suivre automatiquement les redirections
        ));

        // Vérification de la réponse
        if (is_wp_error($response)) {
            return true; // Considérer que l'accès est protégé en cas d'erreur
        }

        // Récupérer le code HTTP et vérifier s'il y a une redirection
        $http_code = wp_remote_retrieve_response_code($response);

        if ($http_code >= 300 && $http_code < 400) {
            // Récupérer l'URL de redirection dans l'en-tête "Location"
            $redirect_url = wp_remote_retrieve_header($response, 'location');
            if (empty($redirect_url)) {
                break; // Pas de redirection, sortir de la boucle
            }

            $current_url = $redirect_url; // Suivre la redirection
            $redirect_count++;
        } else {
            // Si le code HTTP est 200 et l'URL finale est wp-login.php ou wp-admin
            if ($http_code === 200) {
                if (strpos($current_url, 'wp-login.php') !== false || strpos($current_url, 'wp-admin') !== false) {
                    return false; // L'accès n'est pas protégé
                }
            }
            // Si nous avons un autre code HTTP, considérer l'accès comme protégé
            break;
        }
    }

    // Si nous sommes sortis de la boucle sans trouver wp-login.php ou wp-admin, l'accès est protégé
    return true;
}

//fonction qui check l'en-tete de sécurité HSTS (Strict-Transport-Security)
function hpixl_securicheck_checkHttpHeaders()
{

    $url = home_url('/');

    $response = wp_remote_head($url, [
        'timeout'     => 5,
        'redirection' => 3,
        'user-agent'  => 'Securicheck',
    ]);

    if (is_wp_error($response)) {
        return false;
    }

    $headers = array_change_key_case(
        wp_remote_retrieve_headers($response)->getAll(),
        CASE_LOWER
    );

    $is_https = is_ssl();

    return [
        'strictTransportSecurity' => $is_https && !empty($headers['strict-transport-security']),
        'refererPolicy'           => !empty($headers['referrer-policy']),
        'csp'                     => !empty($headers['content-security-policy']),
        'xFrame'                  => !empty($headers['x-frame-options']),
        'xXssProtection'          => !empty($headers['x-xss-protection']), // obsolète mais info
        'xContentType'            => !empty($headers['x-content-type-options']),
        'permissionPolicy'        => !empty($headers['permissions-policy']),
        'accessControlAllowOrigin' => isset($headers['access-control-allow-origin']), // info seulement
    ];
}

//fonction qui récupère le nombre de révision maxi défini
function hpixl_securicheck_getNombreMaxRevisions()
{
    // Récupère le nombre maximal de révisions configurées
    $max_revisions = -1;

    // Si la constante WP_POST_REVISIONS est définie, utilisez sa valeur
    if (defined('WP_POST_REVISIONS')) {
        $max_revisions = WP_POST_REVISIONS === true ? -1 : intval(WP_POST_REVISIONS);
    }

    return $max_revisions;
}

//fonction qui vérifie si un système de cache est actif sur le site
function hpixl_securicheck_isCacheActif()
{
    // Vérifie si une constante de cache est définie dans wp-config.php
    if (defined('WP_CACHE') && WP_CACHE) {
        return true;
    }

    // Vérifie si des fichiers de cache sont présents dans le répertoire wp-content/cache
    $cache_dir = WP_CONTENT_DIR . '/cache';
    if (is_dir($cache_dir) && (count(glob("$cache_dir/*")) > 0)) {
        return true;
    }

    return false;
}

//fonction qui vérifie que la version de wordpress est bien cachée
function hpixl_securicheck_is_wordpress_version_hidden()
{
    ob_start();
    wp_head();
    $wp_head_content = ob_get_clean();

    return strpos($wp_head_content, '<meta name="generator" content="WordPress"') === false;
}

//fonction qui retourne les plugins installés
function hpixl_securicheck_get_plugins()
{

    // Récupère la liste de tous les plugins
    if (! function_exists('get_plugins')) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }
    if (! function_exists('plugins_api')) {
        require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
    }

    $plugins = get_plugins();
    $plugins_retour = array();

    foreach ($plugins as $slug => $plugin) {
        $version = isset($plugin['Version']) ? $plugin['Version'] : '';
        $name = isset($plugin['Name']) ? $plugin['Name'] : '';
        $plugins_retour[$slug]['Version'] = $version;
        $plugins_retour[$slug]['Name'] = $name;
        // Vérifie si le plugin est actif
        $plugins_retour[$slug]['Actif'] = is_plugin_active($slug) ? 'oui' : 'non';

        // Récupère le slug simple (ex: contact-form-7/contact-form-7.php → contact-form-7)
        $slug_simple = explode('/', $slug)[0];
        // Valeur par défaut
        $last_updated = 'inconnue';
        // Récupère les infos du plugin via l’API WordPress.org
        $api = @plugins_api('plugin_information', array(
            'slug'   => $slug_simple,
            'fields' => array('last_updated' => true),
        ));
        if (! is_wp_error($api) && ! empty($api->last_updated)) {
            // Format lisible : 2023-07-18 → 18/07/2023
            $last_updated = date('d/m/Y', strtotime($api->last_updated));
        }
        $plugins_retour[$slug]['DerniereMAJ'] = $last_updated;
    }

    return $plugins_retour;
}

//fonction qui retourne les plugins à update
function hpixl_securicheck_get_plugin_updates()
{
    $plugins = get_plugin_updates();
    $plugins_retour = array();

    foreach ($plugins as $slug => $plugin) {
        $new_version = isset($plugin->update->new_version) ? $plugin->update->new_version : '';
        $plugins_retour[$slug]['new_version'] = $new_version;
    }
    return $plugins_retour;
}

//fonction qui retourne les themes installés
function hpixl_securicheck_get_themes()
{
    if (! function_exists('themes_api')) {
        require_once ABSPATH . 'wp-admin/includes/theme.php';
    }

    $themes = wp_get_themes();
    $themes_retour = array();

    // Thème actif (enfant) et thème parent
    $current_stylesheet = get_stylesheet();
    $current_template   = get_template();

    foreach ($themes as $slug => $theme) {
        $version = isset($theme->version) ? $theme->version : '';
        $name = isset($theme->name) ? $theme->name : '';
        $themes_retour[$slug]['Version'] = $version;
        $themes_retour[$slug]['Name'] = $name;

        // Vérifie si le thème est actif (enfant ou parent)
        //$themes_retour[$slug]['Actif'] = ($slug === $current_stylesheet || $slug === $current_template);
        $themes_retour[$slug]['Actif'] =
            ($slug === $current_stylesheet || $slug === $current_template)
            ? 'oui'
            : 'non';

        // Récupère le slug simple (ex: contact-form-7/contact-form-7.php → contact-form-7)
        $slug_simple = explode('/', $slug)[0];
        // Valeur par défaut
        $last_updated = 'inconnue';
        // Récupère les infos du plugin via l’API WordPress.org
        $api = @themes_api('theme_information', array(
            'slug'   => $slug_simple,
            'fields' => array('last_updated' => true),
        ));
        if (! is_wp_error($api) && ! empty($api->last_updated)) {
            // Format lisible : 2023-07-18 → 18/07/2023
            $last_updated = date('d/m/Y', strtotime($api->last_updated));
        }
        $themes_retour[$slug]['DerniereMAJ'] = $last_updated;
    }

    return $themes_retour;
}

//fonction qui retourne les thèmes à update
function hpixl_securicheck_get_theme_updates()
{
    $themes = get_theme_updates();
    $themes_retour = array();

    foreach ($themes as $slug => $theme) {
        $new_version = isset($theme->update['new_version']) ? $theme->update['new_version'] : '';
        $themes_retour[$slug]['new_version'] = $new_version;
    }
    return $themes_retour;
}

//fonction qui retourne les connexions failed 30 jours avant la date de l'audit avec l'id passé en paramètre
function hpixl_securicheck_get_connexions_failed_by_audit($id)
{
    global $wpdb;
    //on va chercher la date de l'audit
    $tableAudit = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
    $retour = null;
    if (hpixl_securicheck_table_exists($tableAudit)) {

        $cache_key = 'audit_date_' . $id;
        // Tenter de récupérer le résultat du cache
        $resultatId = wp_cache_get($cache_key);
        if ($resultatId === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultatId = $wpdb->get_results($wpdb->prepare(
                "SELECT date FROM %i WHERE id = %s",
                esc_sql($tableAudit),
                $id
            ));

            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultatId, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        if ($resultatId) {
            //on va chercher les connexions avant cette date
            $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;

            $resultat = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM %i WHERE date <= %s AND date >= %s - INTERVAL 30 DAY and etat = 'failed' ORDER BY date DESC",
                esc_sql($tableAuditLogsConnexions),
                $resultatId[0]->date,
                $resultatId[0]->date
            ));

            $retour = array();
            $i = 0;
            foreach ($resultat as $row) {

                $user1 = get_user_by('login', $row->username);
                $user2 = get_user_by('email', $row->username);
                if ($user1 || $user2) {
                    $row->user_exists = true;
                } else {
                    $row->user_exists = false;
                }
                $i++;
                $retour[$i] = $row;
            }
        }
    }
    return $retour;
}

//fonction qui retourne les connexions failed sur les 30 derniers jours
function hpixl_securicheck_get_connexions_failed_last_30days()
{
    global $wpdb;

    $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
    $retour = array();
    if (hpixl_securicheck_table_exists($tableAuditLogsConnexions)) {

        $cache_key = 'securicheck_audit_logs_failed_last_30_days';

        // Tenter de récupérer le résultat du cache
        $resultat = wp_cache_get($cache_key);
        if ($resultat === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultat = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM %i WHERE etat = %s AND date >= CURDATE() - INTERVAL 30 DAY ORDER BY date DESC",
                esc_sql($tableAuditLogsConnexions),
                'failed'
            ));
            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        $i = 0;
        foreach ($resultat as $row) {

            $user1 = get_user_by('login', $row->username);
            $user2 = get_user_by('email', $row->username);
            if ($user1 || $user2) {
                $row->user_exists = true;
            } else {
                $row->user_exists = false;
            }
            $i++;
            $retour[$i] = $row;
        }
    }
    return $retour;
}

//fonction qui retourne les connexions ok 30 jours avant la date de l'audit avec l'id passé en paramètre
function hpixl_securicheck_get_connexions_ok_by_audit($id)
{
    global $wpdb;
    //on va chercher la date de l'audit
    $tableAudit = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
    $resultat = null;
    if (hpixl_securicheck_table_exists($tableAudit)) {

        $cache_key = 'securicheck_audit_date_for_id_' . $id;

        // Tenter de récupérer le résultat du cache
        $resultatId = wp_cache_get($cache_key);

        if ($resultatId === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultatId = $wpdb->get_results($wpdb->prepare(
                "SELECT date FROM %i WHERE id = %s",
                esc_sql($tableAudit),
                $id
            ));

            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultatId, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        if ($resultatId) {
            //on va chercher les connexions avant cette date
            $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;

            $cache_key = 'securicheck_logs_ok_for_id_.' . $id . '_and_date_' . $resultatId[0]->date;

            // Tenter de récupérer le résultat du cache
            $resultat = wp_cache_get($cache_key);

            if ($resultat === false) {
                // Si le résultat n'est pas en cache, effectuer la requête
                $resultat = $wpdb->get_results($wpdb->prepare(
                    "SELECT * FROM %i WHERE date <= %s AND date >= %s - INTERVAL 30 DAY AND etat = 'ok' ORDER BY date DESC",
                    esc_sql($tableAuditLogsConnexions),
                    $resultatId[0]->date,
                    $resultatId[0]->date
                ));

                // Mettre en cache le résultat pour une utilisation future
                wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
            }
        }
    }
    return $resultat;
}

//fonction qui retourne les connexions ok sur les 30 derniers jours
function hpixl_securicheck_get_connexions_ok_last_30days()
{
    global $wpdb;

    $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
    $resultat = array();
    if (hpixl_securicheck_table_exists($tableAuditLogsConnexions)) {

        $cache_key = 'securicheck_logs_ok_last_30_days';
        // Tenter de récupérer le résultat du cache
        $resultat = wp_cache_get($cache_key);
        if ($resultat === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultat = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM %i WHERE etat = %s AND date >= CURDATE() - INTERVAL 30 DAY ORDER BY date DESC",
                esc_sql($tableAuditLogsConnexions),
                'ok'
            ));
            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }
    }
    return $resultat;
}

//fonction qui retourne les connexions d'administrateurs ok 30 jours avant la date de l'audit avec l'id passé en paramètre
function hpixl_securicheck_get_connexions_ok_admin_by_audit($id)
{
    global $wpdb;
    //on va chercher la date de l'audit
    $tableAudit = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
    $admins = array();
    if (hpixl_securicheck_table_exists($tableAudit)) {

        $cache_key = 'securicheck_audit_date_for_id_' . $id;

        // Tenter de récupérer le résultat du cache
        $resultatId = wp_cache_get($cache_key);

        if ($resultatId === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultatId = $wpdb->get_results($wpdb->prepare(
                "SELECT date FROM %i WHERE id = %s",
                esc_sql($tableAudit),
                $id
            ));

            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultatId, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        if ($resultatId) {

            //on va chercher les connexions avant cette date
            $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;

            $cache_key = 'securicheck_admin_logs_ok_for_' . $id . '_and_date_' . $resultatId[0]->date;
            // Tenter de récupérer le résultat du cache
            $resultat = wp_cache_get($cache_key);
            if ($resultat === false) {
                // Si le résultat n'est pas en cache, effectuer la requête
                $resultat = $wpdb->get_results($wpdb->prepare(
                    "SELECT * FROM %i WHERE date <= %s  AND date >= %s - INTERVAL 30 DAY AND etat = 'ok' ORDER BY date DESC",
                    esc_sql($tableAuditLogsConnexions),
                    $resultatId[0]->date,
                    $resultatId[0]->date
                ));

                // Mettre en cache le résultat pour une utilisation future
                wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
            }

            //on ne garde que les administrateurs
            foreach ($resultat as $row) {
                $user = get_user_by('login', $row->username);
                if ($user && in_array('administrator', $user->roles)) {
                    $admins[] = $row;
                }
            }
        }
    }
    return $admins;
}

//fonction qui retourne les connexions d'administrateurs ok sur les 30 derniers jours
function hpixl_securicheck_get_connexions_ok_admin_last_30days()
{
    global $wpdb;

    $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
    $admins = array();
    if (hpixl_securicheck_table_exists($tableAuditLogsConnexions)) {

        $cache_key = 'securicheck_audit_logs_ok_last_30_days';
        // Tenter de récupérer le résultat du cache
        $resultat = wp_cache_get($cache_key);
        if ($resultat === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultat = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM %i WHERE etat = %s AND date >= CURDATE() - INTERVAL 30 DAY ORDER BY date DESC",
                esc_sql($tableAuditLogsConnexions),
                'ok'
            ));
            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        //on ne garde que les administrateurs
        foreach ($resultat as $row) {
            $user = get_user_by('login', $row->username);
            if ($user && in_array('administrator', $user->roles)) {
                $admins[] = $row;
            }
        }
    }

    return $admins;
}

//fonction qui retourne les connexions d'administrateurs ok sur les 30 derniers jours
function hpixl_securicheck_get_connexions_ok_administrateurs()
{
    global $wpdb;

    $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
    $admins = array();
    if (hpixl_securicheck_table_exists($tableAuditLogsConnexions)) {

        $cache_key = 'securicheck_audit_logs_ok';
        // Tenter de récupérer le résultat du cache
        $resultat = wp_cache_get($cache_key);
        if ($resultat === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultat = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM %i WHERE etat = %s ORDER BY date DESC",
                esc_sql($tableAuditLogsConnexions),
                'ok'
            ));
            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        //on ne garde que les administrateurs
        foreach ($resultat as $row) {
            $user = get_user_by('login', $row->username);
            if ($user && in_array('administrator', $user->roles)) {
                $admins[] = $row;
            }
        }
    }

    return $admins;
}


// fonction qui retourne le nombre de connexions failed par jour sur les 30 derniers jours 
function hpixl_securicheck_count_connexions_failed_by_day()
{
    //on va chercher les infos pour ces 30 jours là
    global $wpdb;

    $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
    $retour = array();
    if (hpixl_securicheck_table_exists($tableAuditLogsConnexions)) {

        $cache_key = 'audit_logs_failed_by_day_last_30_days';

        // Tenter de récupérer le résultat du cache
        $resultat = wp_cache_get($cache_key);

        if ($resultat === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultat = $wpdb->get_results($wpdb->prepare(
                "SELECT all_dates.jour, IFNULL(COUNT(%i.date), 0) AS nombre_connexions
        FROM (
            SELECT CURDATE() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY AS jour
            FROM (
                SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
            ) AS a
            CROSS JOIN (
                SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
            ) AS b
            CROSS JOIN (
                SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
            ) AS c
        ) AS all_dates
        LEFT JOIN %i ON DATE(%i.date) = all_dates.jour
            AND %i.date >= CURDATE() - INTERVAL 30 DAY
            AND %i.etat = %s
        WHERE all_dates.jour >= CURDATE() - INTERVAL 30 DAY
        GROUP BY all_dates.jour
        ORDER BY all_dates.jour ASC;",
                esc_sql($tableAuditLogsConnexions),
                esc_sql($tableAuditLogsConnexions),
                esc_sql($tableAuditLogsConnexions),
                esc_sql($tableAuditLogsConnexions),
                esc_sql($tableAuditLogsConnexions),
                'failed'
            ));

            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }



        $i = 0;

        foreach ($resultat as $row) {
            $i++;
            $timestamp = strtotime($row->jour);

            if (class_exists('IntlDateFormatter')) {
                // Utilisation de IntlDateFormatter si disponible
                $formatter = new IntlDateFormatter('fr_FR', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
                datefmt_set_pattern($formatter, 'dd/MM/yyyy');
                $row->jour = $formatter->format($timestamp);
            } else {
                // Alternative avec DateTime
                $dt = new DateTime($row->jour);
                $row->jour = $dt->format('d/m/Y');
            }

            $retour[$i] = $row;
        }
    }
    return $retour;
}

//fonction qui retourne le nombre de connexions failed sur les 30 derniers jours
function hpixl_securicheck_get_nb_connexions_failed()
{
    global $wpdb;

    //on va chercher les connexions avant cette date
    $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
    if (hpixl_securicheck_table_exists($tableAuditLogsConnexions)) {

        $cache_key = 'securicheck_failed_connections_count';
        // Tenter de récupérer le résultat du cache
        $resultat = wp_cache_get($cache_key);
        if ($resultat === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultat = $wpdb->get_results($wpdb->prepare(
                "SELECT COUNT(id) AS nombre FROM %i WHERE etat = %s AND date >= CURDATE() - INTERVAL 30 DAY;",
                esc_sql($tableAuditLogsConnexions),
                'failed'
            ));
            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultat, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        return $resultat[0]->nombre;
    } else {
        return 0;
    }
}

//fonction qui récupère l'id de l'administrateur principal
function hpixl_securicheck_get_main_admin_id()
{
    $admins = get_users(array(
        'role'    => 'administrator',
        'orderby' => 'user_registered',
        'order'   => 'ASC',
        'number'  => 1,
        'fields'  => 'ID',
    ));

    return ! empty($admins) ? (int) $admins[0] : false;
}

/**
 * Crée une date complète à partir de chaînes de caractères pour la date, les heures et les minutes.
 *
 * @param string $dateString  La date au format 'YYYY-MM-DD'.
 * @param string $hoursString Les heures au format 'HH'.
 * @param string $minutesString Les minutes au format 'MM'.
 * @return DateTime|false L'objet DateTime si la date est valide, false sinon.
 */
/*function hpixl_securicheck_create_full_date($dateString, $hoursString, $minutesString)
{
    // Combine les chaînes pour former une date complète
    $fullDateString = $dateString . ' ' . $hoursString . ':' . $minutesString . ':00';
    // Crée un objet DateTime à partir de la chaîne combinée
    try {
        // $timezone = new DateTimeZone('Europe/Paris');
        $timezone = wp_timezone();

        $date = new DateTime($fullDateString, $timezone);
    } catch (Exception $e) {
        // Si la création échoue, retourne false

        return false;
    }

    // Vérifie si la date est valide
    if ($date && $date->format('Y-m-d H:i:s') === $fullDateString) {
        return $date->getTimestamp();
    } else {
        return false;
    }
}
*/

//valide une adress email
function hpixl_securicheck_is_valid_email($email)
{
    // Utilisation de la fonction filter_var avec FILTER_VALIDATE_EMAIL pour vérifier si l'email est valide
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

/**
 * Fonction qui prend une date au format americain (2024-05-23 08:09:15) en paramètre 
 * et renvoie au format français : 23 mai 2024 à 08:09:15
 */
function hpixl_securicheck_format_date_in_french($dateString)
{
    // Crée une instance de DateTime à partir de la chaîne de date donnée
    $date = new DateTime($dateString);

    // Formate la date selon le format souhaité
    $formattedDate = $date->format('d F Y \à H:i:s');

    // Convertir le nom du mois en français
    $formattedDate = str_replace(
        array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'),
        array('janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'),
        $formattedDate
    );

    return $formattedDate;
}

/**
 * Retourne la date du dernier audit
 */
function hpixl_securicheck_get_date_dernier_audit()
{
    global $wpdb;
    $dateDernierAudit = "";
    $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
    if (hpixl_securicheck_table_exists($table)) {

        $cache_key = 'securicheck_latest_audit_date_' . $table;

        // Tenter de récupérer le résultat du cache
        $resultatRequeteAudit = wp_cache_get($cache_key);
        if ($resultatRequeteAudit === false) {
            // Si le résultat n'est pas en cache, effectuer la requête
            $resultatRequeteAudit = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM %i ORDER BY date DESC LIMIT 1",
                esc_sql($table)
            ));
            // Mettre en cache le résultat pour une utilisation future
            wp_cache_set($cache_key, $resultatRequeteAudit, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
        }

        foreach ($resultatRequeteAudit as $r) {
            $dateDernierAudit = hpixl_securicheck_format_date($r->date);
        }
    }
    return $dateDernierAudit;
}

/**
 * Retourne si la table de la bdd existe
 */
function hpixl_securicheck_table_exists($table_name)
{
    global $wpdb;

    $cache_key = 'securicheck_table_exists_' . $table_name;

    // Tenter de récupérer le résultat du cache
    $cached_result = wp_cache_get($cache_key);
    if ($cached_result === false) {
        // Si le résultat n'est pas en cache, effectuer la requête
        $result = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name));
        // Mettre en cache le résultat pour une utilisation future
        wp_cache_set($cache_key, $result, '', 3600); // Mettre en cache pour 1 heure (3600 secondes)
    } else {
        // Utiliser le résultat mis en cache
        $result = $cached_result;
    }

    if ($result === $table_name) {
        return true;
    } else {
        return false;
    }
}

/**
 * Supprime toutes les données d'un audit
 */
function hpixl_securicheck_delete_audit($id)
{
    global $wpdb;

    //suppression de l'audit
    $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
    if (hpixl_securicheck_table_exists($table)) {

        $wpdb->query(
            $wpdb->prepare(
                "DELETE FROM $table WHERE id = %d",
                $id
            )
        );
    }
    //suppression des de cet audit
    $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_RESULTATS;
    if (hpixl_securicheck_table_exists($table)) {

        $wpdb->query(
            $wpdb->prepare(
                "DELETE FROM $table WHERE id_audit = %d",
                $id
            )
        );
    }
}

/**
 * Supprime les audits si le nombre est plus grand que la limite
 */
function hpixl_securicheck_delete_too_much_audit($limite)
{
    global $wpdb;

    $tableAudit = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;

    // Exécuter la requête préparée
    $wpdb->query($wpdb->prepare(
        "DELETE FROM %i
    WHERE id NOT IN (
        SELECT id
        FROM (
            SELECT id
            FROM %i
            ORDER BY id DESC
            LIMIT %d
        ) AS temp)",
        esc_sql($tableAudit),
        esc_sql($tableAudit),
        $limite
    ));
}

/**
 * Check si l'application passwords est activée ou non
 */
function hpixl_securicheck_is_application_password_active()
{
    return wp_is_application_passwords_available();
}

/**
 * Check si la page archive auteur est désactivée
 */
function hpixl_securicheck_is_author_archive_disabled()
{
    // Récupère un post publié
    $args = array(
        'numberposts' => 1, // Limite à un seul post
        'post_status' => 'publish', // Seuls les posts publiés
        'post_type' => array('post', 'page'), // Inclure à la fois les articles et les pages
    );

    $recent_post = wp_get_recent_posts($args);

    // Si aucun post n'est trouvé
    if (empty($recent_post)) {
        return false; // Pas de post trouvé, ne peut pas tester
    }

    // Récupère l'auteur de ce post
    $post_author_id = $recent_post[0]['post_author'];

    // Récupère l'URL de l'archive auteur pour cet auteur
    $author_url = get_author_posts_url($post_author_id);

    //$response = wp_remote_get($author_url);
    $response = wp_remote_get($author_url, [
        'timeout'     => 5,
        'redirection' => 0,
    ]);

    // Vérifie la réponse HTTP
    if (is_wp_error($response)) {
        return false; // Une erreur s'est produite lors de la requête
    }

    $status_code = wp_remote_retrieve_response_code($response);

    //error_log("hpixl_securicheck_is_author_archive_disabled status_code: " . $status_code);

    // Si la page retourne un 404, cela signifie que l'archive auteur est désactivée
    if (in_array($status_code, [403, 404, 503], true)) {
        return true; // Archive auteur désactivée
    }

    return false; // Archive auteur activée
}

/**
 * Check si le scan d'id des auteurs est désactivé
 */
function hpixl_securicheck_is_scan_author_disabled()
{
    // URL à tester
    $test_url = home_url('/?author=1');

    // Effectue une requête HTTP pour tester l'URL
    $response = wp_remote_get($test_url, [
        'timeout'     => 5,
        'redirection' => 0,
    ]);

    // Vérifie si la requête a échoué
    if (is_wp_error($response)) {
        return false; // Une erreur s'est produite lors de la requête
    }

    // Récupère le code de réponse HTTP
    $status_code = wp_remote_retrieve_response_code($response);

    // Vérifie si le code de réponse est 404 (non trouvé)
    if (in_array($status_code, [403, 404, 503], true)) {
        return true; // Le scan des ID d'auteurs est désactivé
    }

    return false; // Le scan des ID d'auteurs est actif
}

// Action pour gérer l'exportation des données en json des réglages du plugin
add_action('admin_post_hpixl_securicheck_export_reglages_json', function () {

    // Sécurité basique
    if (!current_user_can('manage_options')) {
        wp_die(__('Vous n’avez pas les permissions nécessaires.', 'securicheck'));
    }

    if (
        ! isset($_POST['hpixl_securicheck_export_reglages_nonce']) ||
        ! wp_verify_nonce(
            $_POST['hpixl_securicheck_export_reglages_nonce'],
            'hpixl_securicheck_export_reglages'
        )
    ) {
        wp_die(__('Requête non autorisée (nonce invalide).', 'securicheck'));
    }

    global $wpdb;

    // Récupération de toutes les options Securicheck (free + pro)
    $results = $wpdb->get_results(
        "
        SELECT option_name, option_value
        FROM {$wpdb->options}
        WHERE option_name LIKE 'hpixl_securicheck_%'
        ",
        ARRAY_A
    );

    if ($wpdb->last_error) {
        wp_die(__('Erreur SQL : ', 'securicheck') . $wpdb->last_error);
    }

    if (empty($results)) {
        wp_die(__('Aucun réglage trouvé à exporter.', 'securicheck'));
    }

    // Séparation des options FREE / PRO
    $free_options = [];
    $pro_options  = [];

    foreach ($results as $row) {
        $value = maybe_unserialize($row['option_value']);

        //si securicheck pro est actif alors on récupere ses reglages
        if (is_plugin_active(HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME) && strpos($row['option_name'], 'hpixl_securicheck_pro_') === 0) {
            $pro_options[$row['option_name']] = $value;
        } else {
            $free_options[$row['option_name']] = $value;
        }
    }

    // Version de securicheck-pro si actif
    $version_securicheck_pro = "";
    if (is_plugin_active(HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME)) {
        $pro_plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME);
        $version_securicheck_pro = $pro_plugin_data['Version'] ?? null;
    }

    // Structure finale du JSON
    $export_data = [
        "url_site"             => home_url(),
        'date_export'          => current_time('mysql'),
        "version_securicheck"  => HPIXL_SECURICHECK_PLUGIN_VERSION,
        "version_securicheck-pro" => $version_securicheck_pro,
        'options'              => [
            'free' => $free_options,
            'pro'  => $pro_options,
        ],
    ];

    // Encodage JSON
    $json_data = json_encode(
        $export_data,
        JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
    );

    if (json_last_error() !== JSON_ERROR_NONE) {
        wp_die(__('Erreur lors de l’encodage JSON : ', 'securicheck') . json_last_error_msg());
    }

    // Nom du fichier exporté
    $filename = 'securicheck_export_reglages_' . date('Ymd_His') . '.json';

    // Headers HTTP pour le téléchargement
    header('Content-Type: application/json');
    header('Content-Disposition: attachment; filename=' . $filename);
    header('Content-Length: ' . strlen($json_data));

    // Sortie du fichier
    echo $json_data;
    exit;
});

// Action pour gérer l'exportation des données en json de l'audit souhaité
add_action('admin_post_hpixl_securicheck_export_audit_json', function () {

    if (!current_user_can('manage_options')) {
        wp_die(__('Vous n’avez pas les permissions nécessaires.', 'securicheck'));
    }

    // Vérification du nonce
    if (
        ! isset($_POST['hpixl_securicheck_export_audit_nonce']) ||
        ! wp_verify_nonce(
            $_POST['hpixl_securicheck_export_audit_nonce'],
            'hpixl_securicheck_export_audit'
        )
    ) {
        wp_die(__('Requête non autorisée (nonce invalide).', 'securicheck'));
    }

    // Récupérer l'ID envoyé par le formulaire
    $export_id = isset($_POST['export_id']) ? intval($_POST['export_id']) : 0;

    if ($export_id <= 0) {
        wp_die(__('ID invalide.', 'securicheck'));
    }

    global $wpdb;
    //l'audit
    $table_name = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
    $sql_query = $wpdb->prepare("SELECT * FROM {$table_name} WHERE id = %d", $export_id);

    // Exécuter la requête SQL
    $results = $wpdb->get_results($sql_query, ARRAY_A);
    if ($wpdb->last_error) {
        wp_die(__('Erreur SQL : ', 'securicheck') . $wpdb->last_error);
    }

    if (empty($results)) {
        wp_die(__('Aucun résultat trouvé pour cet ID.', 'securicheck'));
    }

    $audit_data = $results[0];

    //les résultats détaillés de l'audit
    $table_name_resultats = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_RESULTATS;
    $sql_query_resultats = $wpdb->prepare("SELECT * FROM {$table_name_resultats} WHERE id_audit = %d", $export_id);

    // Exécuter la requête SQL
    $results_resultats = $wpdb->get_results($sql_query_resultats, ARRAY_A);
    if ($wpdb->last_error) {
        wp_die(__('Erreur SQL : ', 'securicheck') . $wpdb->last_error);
    }

    if (empty($results_resultats)) {
        wp_die(__('Aucun résultat trouvé pour cet ID.', 'securicheck'));
    }

    // Reformater les résultats en un tableau associatif
    $formatted_results = [];
    foreach ($results_resultats as $result) {
        $action = $result['action'] ?? '';
        $value = $result['resultat'] ?? '';
        $formatted_results[$action] = $value;
    }

    // Structure finale du JSON
    $formatted_data = [
        "url_site" => home_url(),
        'date_export'  => current_time('mysql'),
        "version_securicheck" => HPIXL_SECURICHECK_PLUGIN_VERSION,
        "audit" => [
            "id" => $audit_data['id'] ?? '',
            "date" => $audit_data['date'] ?? '',
            "type" => $audit_data['type'] ?? '',
            "score" => $audit_data['score'] ?? '',
            "pb_total" => $audit_data['pb_total'] ?? '',
            "pb_techniques" => $audit_data['pb_techniques'] ?? '',
            "pb_fonctionnels" => $audit_data['pb_fonctionnels'] ?? '',
            "pb_securite" => $audit_data['pb_securite'] ?? '',
            "pb_performance" => $audit_data['pb_performance'] ?? ''
        ],
        "resultats" => $formatted_results
    ];

    // Générer le contenu JSON
    $json_data = json_encode($formatted_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    if (json_last_error() !== JSON_ERROR_NONE) {
        wp_die(__('Erreur lors de l’encodage JSON : ', 'securicheck') . json_last_error_msg());
    }

    // En-têtes HTTP pour le téléchargement du fichier
    $export_date = $audit_data['date'] ?? 'export';
    $filename = "securicheck_export_audit_" . preg_replace('/[^0-9]/', '', $export_date) . ".json";

    header('Content-Type: application/json');
    header("Content-Disposition: attachment; filename={$filename}");
    header('Content-Length: ' . strlen($json_data));

    // Afficher le JSON pour téléchargement
    echo $json_data;
    exit;
});

/**
 * Retourne l'IP du client de façon sécurisée contre le spoofing.
 *
 * Stratégie automatique sans configuration :
 * - Si REMOTE_ADDR est une IP publique → connexion directe, utilisée telle quelle
 *   (les headers HTTP_CLIENT_IP / X-Forwarded-For sont ignorés car forgeable par le client).
 * - Si REMOTE_ADDR est une IP privée/locale → proxy local détecté (nginx, Apache...).
 *   On lit X-Real-IP ou X-Forwarded-For en prenant la DERNIÈRE IP publique de la liste,
 *   c'est-à-dire celle ajoutée par le proxy de confiance (pas la première, forgeable).
 *
 * Limite : CDN publics (Cloudflare...) où REMOTE_ADDR est l'IP du CDN → on retourne
 * l'IP du CDN, non l'IP du visiteur. Nécessiterait une config dédiée pour être résolu.
 */
function hpixl_securicheck_get_ip()
{
    $remote_addr = isset($_SERVER['REMOTE_ADDR']) ? trim($_SERVER['REMOTE_ADDR']) : '';

    // REMOTE_ADDR publique → connexion directe, impossible à forger
    if (filter_var($remote_addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
        return $remote_addr;
    }

    // REMOTE_ADDR privée/locale → proxy local détecté
    // X-Real-IP (nginx) : positionné par le proxy, non forgeable par le client
    if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
        $ip = trim($_SERVER['HTTP_X_REAL_IP']);
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
            return $ip;
        }
    }

    // X-Forwarded-For : "client [, proxy1, proxy2...]"
    // Lecture de droite à gauche : la dernière IP publique est celle du proxy de confiance
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = array_reverse(array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])));
        foreach ($ips as $ip) {
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $ip;
            }
        }
    }

    // Fallback : REMOTE_ADDR même si privée (environnement local / dev)
    return filter_var($remote_addr, FILTER_VALIDATE_IP) ? $remote_addr : '';
}

// Vérifie si le site peut contacter l'API WordPress.org (nécessaire pour les mises à jour et alertes de sécurité)
function hpixl_securicheck_can_reach_wordpress_org()
{
    $response = wp_remote_get('https://api.wordpress.org', array('timeout' => 5));
    if (is_wp_error($response)) {
        return 0;
    }
    $code = wp_remote_retrieve_response_code($response);
    return ($code > 0 && $code < 500) ? 1 : 0;
}
