<?php
defined('ABSPATH') || exit;


if (!class_exists('hpixl_securicheck_audit')) {

    class hpixl_securicheck_audit
    {
        public $id_audit;
        public $score;
        public $date;
        public $resultats;
        public $type;

        public function __construct($id, $type)
        {
            $this->date = "N/A";
            $this->id_audit = "0";
            $this->score = 0;
            $this->type = $type;

            if ($id) {
                $this->chargerAudit($id);
            } else {
                $this->creerAudit($this->type);
            }
            if ($this->resultats) {
                $this->score = $this->resultats->score_audit;
            }
        }


        /**
         * Insertion d'un nouvel audit en bdd
         */
        public function creerAudit()
        {

            global $wpdb;
            $tableAudit = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
            if (hpixl_securicheck_table_exists($tableAudit)) {
                // Obtenez l'horodatage actuel selon le fuseau horaire de WordPress
                $current_time = current_time('timestamp');
                // Formatez l'horodatage en utilisant le fuseau horaire de WordPress
                $date = date_i18n('Y-m-d H:i:s', $current_time);
                //maj de l'audit avec la date
                $this->date = hpixl_securicheck_format_date($date);

                $wpdb->query($wpdb->prepare(
                    "INSERT INTO %i (date, type) VALUES (%s, %s)",
                    esc_sql($tableAudit),
                    $date,
                    $this->type
                ));

                //l'id de l'audit créé
                $this->id_audit  =  0;
                // Vérifier si l'insertion a réussi
                if ($wpdb->last_error === '') {
                    // L'insertion a réussi, obtenir l'ID de l'audit créé
                    $this->id_audit  = $wpdb->insert_id;
                } else {
                    // L'insertion a échoué, gérer l'erreur ici
                    echo "Erreur lors de la création de l'audit : " . esc_html($wpdb->last_error);
                }


                //on fait tous les tests lié à l'audit
                $resultats = new hpixl_securicheck_resultatAudit($this->id_audit, true);

                //on ajout les resultats à l'audit
                $this->resultats = $resultats;
                //on ajoute le score à l'audit
                $this->score = $this->resultats->score_audit;

                // Données à mettre à jour
                $wpdb->query($wpdb->prepare(
                    "UPDATE %i 
                    SET score = %d, 
                        pb_total = %d, 
                        pb_techniques = %d, 
                        pb_fonctionnels = %d, 
                        pb_securite = %d, 
                        pb_performance = %d 
                    WHERE id = %d",
                    esc_sql($tableAudit),
                    $this->score,
                    $this->resultats->nb_total_erreurs,
                    $this->resultats->nb_erreurs_etat_technique,
                    $this->resultats->nb_erreurs_etat_fonctionnel,
                    $this->resultats->nb_erreurs_securite,
                    $this->resultats->nb_erreurs_etat_performances,
                    $this->id_audit
                ));


                //envoi du mail pour avertir
                $destinataire = get_option('admin_email'); // valeur par défaut
                $option_notif_audit = get_option('hpixl_securicheck_toggle_notifications');
                $option_destinataire = get_option('hpixl_securicheck_destinataire_email_notifications');
                if (!empty($option_notif_audit) && $option_notif_audit) {
                    if (!empty($option_destinataire) && $option_destinataire && hpixl_securicheck_is_valid_email($option_destinataire)) {
                        $destinataire = $option_destinataire;
                    }

                    //le tableau avec le nb d'erreurs par critere
                    $tableauNbErreurs = array();
                    $tableauNbErreurs['nb_total_erreurs'] = $this->resultats->nb_total_erreurs;
                    $r = $this->resultats;
                    $tableauNbErreurs['nb_erreurs_etat_technique'] = $r->nb_erreurs_etat_technique;
                    $anomalies_etat_technique = array();
                    if ($r->isPhpSupported)      { $anomalies_etat_technique[] = sprintf(__('Version PHP obsolète (%s)', 'securicheck'), $r->phpVersion); }
                    if ($r->isTlsSupported)      { $anomalies_etat_technique[] = sprintf(__('Version TLS obsolète (%s)', 'securicheck'), $r->tlsVersion); }
                    if ($r->isBddSupported)      { $anomalies_etat_technique[] = sprintf(__('Version BDD obsolète (%s)', 'securicheck'), $r->bddVersion); }
                    if (!$r->canReachWordpressOrg) { $anomalies_etat_technique[] = __('WordPress.org inaccessible', 'securicheck'); }
                    $tableauNbErreurs['anomalies_etat_technique'] = $anomalies_etat_technique;

                    $tableauNbErreurs['nb_erreurs_etat_fonctionnel'] = $r->nb_erreurs_etat_fonctionnel;
                    $anomalies_etat_fonctionnel = array();
                    if ($r->nb_maj_plugins > 0)  { $anomalies_etat_fonctionnel[] = sprintf(__('Plugins à mettre à jour (%d)', 'securicheck'), $r->nb_maj_plugins); }
                    if ($r->nb_maj_themes > 0)   { $anomalies_etat_fonctionnel[] = sprintf(__('Thèmes à mettre à jour (%d)', 'securicheck'), $r->nb_maj_themes); }
                    if ($r->maj_wordpress === 'oui') { $anomalies_etat_fonctionnel[] = __('WordPress à mettre à jour', 'securicheck'); }
                    if ($r->nb_old_plugins > 0)  { $anomalies_etat_fonctionnel[] = sprintf(__('Plugins désactivés (%d)', 'securicheck'), $r->nb_old_plugins); }
                    if ($r->nb_old_themes > 2)   { $anomalies_etat_fonctionnel[] = sprintf(__('Thèmes inactifs (%d)', 'securicheck'), $r->nb_old_themes); }
                    $tableauNbErreurs['anomalies_etat_fonctionnel'] = $anomalies_etat_fonctionnel;

                    $tableauNbErreurs['nb_erreurs_etat_performances'] = $r->nb_erreurs_etat_performances;
                    $anomalies_etat_performances = array();
                    if ($r->nbMaxiRevisions > 10 || $r->nbMaxiRevisions == -1) { $anomalies_etat_performances[] = sprintf(__('Nombre de révisions trop élevé (%s)', 'securicheck'), $r->nbMaxiRevisions == -1 ? __('illimité', 'securicheck') : $r->nbMaxiRevisions); }
                    if (!$r->isCacheActif) { $anomalies_etat_performances[] = __('Pas de cache activé', 'securicheck'); }
                    $tableauNbErreurs['anomalies_etat_performances'] = $anomalies_etat_performances;

                    $tableauNbErreurs['nb_erreurs_securite_technique'] = $r->nb_erreurs_securite_technique;
                    $anomalies_technique = array();
                    if (!$r->isHttps)                                                      { $anomalies_technique[] = __('Site non HTTPS', 'securicheck'); }
                    if ($r->prefixBdd === 'wp_')                                           { $anomalies_technique[] = __('Préfixe BDD par défaut (wp_)', 'securicheck'); }
                    if ($r->compteAdminExiste)                                             { $anomalies_technique[] = __('Compte "admin" existant', 'securicheck'); }
                    if ($r->nbAdmin > 1)                                                   { $anomalies_technique[] = __('Plusieurs comptes administrateurs', 'securicheck'); }
                    if (!$r->isXmlRpcDisabled)                                             { $anomalies_technique[] = __('XML-RPC activé', 'securicheck'); }
                    if (!$r->isLiveWriterProtected)                                        { $anomalies_technique[] = __('Windows Live Writer non protégé', 'securicheck'); }
                    if ($r->isApiRestDisabled == 0)                                        { $anomalies_technique[] = __('API REST non restreinte', 'securicheck'); }
                    if (!$r->isEditeurFichierDisabled)                                     { $anomalies_technique[] = __('Éditeur de fichiers activé', 'securicheck'); }
                    if (!$r->isDirNavigationProtected)                                     { $anomalies_technique[] = __('Navigation dans les dossiers activée', 'securicheck'); }
                    if (!$r->isUploadsProtected)                                           { $anomalies_technique[] = __('Dossier uploads non protégé', 'securicheck'); }
                    if (!$r->isServerSignatureHidden)                                      { $anomalies_technique[] = __('Signature serveur visible', 'securicheck'); }
                    if (!$r->isPhpVersionHidden)                                           { $anomalies_technique[] = __('Version PHP visible', 'securicheck'); }
                    if (!$r->isWpConfigProtected)                                          { $anomalies_technique[] = __('wp-config.php non protégé', 'securicheck'); }
                    if (!$r->isHtAccessProtected)                                          { $anomalies_technique[] = __('.htaccess non protégé', 'securicheck'); }
                    if ($r->isModeDebugOn)                                                 { $anomalies_technique[] = __('Mode debug activé', 'securicheck'); }
                    if (!$r->boUrl)                                                        { $anomalies_technique[] = __('URL du backoffice non masquée', 'securicheck'); }
                    if (!$r->isWordpressVersionHidden)                                     { $anomalies_technique[] = __('Version WordPress visible', 'securicheck'); }
                    if ($r->id_admin_principal == 1)                                       { $anomalies_technique[] = __('ID administrateur principal = 1', 'securicheck'); }
                    if (isset($r->is_hotlinking_disabled) && $r->is_hotlinking_disabled !== 'oui') { $anomalies_technique[] = __('Hotlinking non protégé', 'securicheck'); }
                    if ($r->is_chatgpt_accessible)                                         { $anomalies_technique[] = __('Site accessible par ChatGPT', 'securicheck'); }
                    if ($r->is_application_password_active)                                { $anomalies_technique[] = __('Mots de passe d\'application activés', 'securicheck'); }
                    if (!$r->isArchiveAuthorDisabled)                                      { $anomalies_technique[] = __('Archive auteur accessible', 'securicheck'); }
                    if (!$r->isScanAuthorDisabled)                                         { $anomalies_technique[] = __('Énumération des auteurs possible', 'securicheck'); }
                    $tableauNbErreurs['anomalies_securite_technique'] = $anomalies_technique;

                    $tableauNbErreurs['nb_erreurs_securite_enTetesHTTP'] = $this->resultats->nb_erreurs_securite_enTetesHTTP;
                    $anomalies_entetes = array();
                    if (!$r->isHstsOk)                      { $anomalies_entetes[] = 'Strict-Transport-Security'; }
                    if (!$r->isRefererPolicyOk)             { $anomalies_entetes[] = 'Referrer-Policy'; }
                    if (!$r->isCspOk)                       { $anomalies_entetes[] = 'Content-Security-Policy'; }
                    if (!$r->isXFrameOptionsOk)             { $anomalies_entetes[] = 'X-Frame-Options'; }
                    if (!$r->isXXssProtectionOk)            { $anomalies_entetes[] = 'X-XSS-Protection'; }
                    if (!$r->isXContentTypeOptionsOk)       { $anomalies_entetes[] = 'X-Content-Type-Options'; }
                    if (!$r->isPermissionsPolicyOk)         { $anomalies_entetes[] = 'Permissions-Policy'; }
                    if (!$r->isAccessControlAllowOriginOk)  { $anomalies_entetes[] = 'Access-Control-Allow-Origin'; }
                    $tableauNbErreurs['anomalies_securite_enTetesHTTP'] = $anomalies_entetes;
                    $tableauNbErreurs['nb_maj_plugins'] = $this->resultats->nb_maj_plugins;
                    $tableauNbErreurs['liste_plugins_maj'] = array();
                    if ($tableauNbErreurs['nb_maj_plugins'] > 0 && is_array($this->resultats->misesAJourPlugins)) {
                        foreach ($this->resultats->misesAJourPlugins as $slug => $update_info) {
                            $name        = isset($this->resultats->listePlugins[$slug]['Name']) ? $this->resultats->listePlugins[$slug]['Name'] : $slug;
                            $version     = isset($this->resultats->listePlugins[$slug]['Version']) ? $this->resultats->listePlugins[$slug]['Version'] : '';
                            $new_version = isset($update_info['new_version']) ? $update_info['new_version'] : '';
                            $tableauNbErreurs['liste_plugins_maj'][] = array(
                                'name'        => $name,
                                'version'     => $version,
                                'new_version' => $new_version,
                            );
                        }
                    }
                    $tableauNbErreurs['nb_maj_themes'] = $this->resultats->nb_maj_themes;
                    $tableauNbErreurs['liste_themes_maj'] = array();
                    if ($tableauNbErreurs['nb_maj_themes'] > 0 && is_array($this->resultats->misesAJourThemes)) {
                        foreach ($this->resultats->misesAJourThemes as $slug => $update_info) {
                            $name        = isset($this->resultats->listeThemes[$slug]['Name']) ? $this->resultats->listeThemes[$slug]['Name'] : $slug;
                            $version     = isset($this->resultats->listeThemes[$slug]['Version']) ? $this->resultats->listeThemes[$slug]['Version'] : '';
                            $new_version = isset($update_info['new_version']) ? $update_info['new_version'] : '';
                            $tableauNbErreurs['liste_themes_maj'][] = array(
                                'name'        => $name,
                                'version'     => $version,
                                'new_version' => $new_version,
                            );
                        }
                    }
                    $tableauNbErreurs['nbMajWordpress']       = $this->resultats->nbMajWordpress;
                    $tableauNbErreurs['wp_version']           = $this->resultats->wp_version;
                    $tableauNbErreurs['wp_latest_version']    = $this->resultats->wp_latest_version;
                    $tableauNbErreurs['nbConnexionsOk'] = $this->resultats->nbConnexionsOk;
                    $tableauNbErreurs['nbConnexionsOkAdmin'] = $this->resultats->nbConnexionsOkAdmin;
                    $tableauNbErreurs['nbFailedConnexions'] = $this->resultats->nbFailedConnexions;


                    //envoi de mail en fin d'audit si la fonction existe
                    hpixl_securicheck_envoi_mail_fin_audit($destinataire, $this->score, $tableauNbErreurs);

                    // on vérifie si on l'utilisateur a défini une limite du nombre d'audit en base de données
                    $hasNbAuditLimit = get_option('hpixl_securicheck_toggle_limite_nombre_audit');
                    $nbLimitAUdit = get_option('hpixl_securicheck_text_limite_nombre_audit');
                    if ($hasNbAuditLimit) {
                        if (is_numeric($nbLimitAUdit) && ctype_digit((string) $nbLimitAUdit)) {
                            hpixl_securicheck_delete_too_much_audit($nbLimitAUdit);
                        }
                    }
                }
            }
        }

        /**
         * Chargement d'un audit en bdd avec son id
         */
        public function chargerAudit($id)
        {
            global $wpdb;

            if ($id && $id >= 0) {
                //si id alors on charge l'audit qui a l'id selectionné
                $this->id_audit = $id;
                //chargement de la date de l'audit concerné
                $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
                if (hpixl_securicheck_table_exists($table)) {

                    $cache_key = 'securicheck_charger_audit_result_' . $id;
                    // 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 WHERE id = %d ORDER BY date DESC LIMIT 1",
                            esc_sql($table),
                            $id
                        ));
                        // 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) {
                        $this->date = hpixl_securicheck_format_date($r->date);
                    }
                }
            } else {
                //si pas d'id alors on charge le dernier audit
                $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
                if (hpixl_securicheck_table_exists($table)) {

                    $cache_key = 'securicheck_latest_audit_result_' . $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) {
                        $this->id_audit = $r->id;
                        $this->date = hpixl_securicheck_format_date($r->date);
                        $this->score = $r->score;
                    }
                }
            }
            // les résultats de l'audit concerné
            $this->resultats = new hpixl_securicheck_resultatAudit($this->id_audit, false);
        }
    }
}
