<?php
/**
 * Plugin Name: TD Sommaire Automatique
 * Description: Génère automatiquement un sommaire basé sur les H2 du contenu
 * Author: Thomas Dufranne
 * Author URI: https://td-plugins.com
 * Version: 1.2.0
 */

// Sécurité : empêcher l'accès direct
if (!defined("ABSPATH")) {
    exit;
}

/**
 * Variable globale pour stocker les compteurs de sections par post
 */
global $td_sommaire_counters;
$td_sommaire_counters = array();

/**
 * Traiter le contenu pour ajouter les IDs aux H2
 */
function td_process_content_with_ids($content, $post_id = null) {
    if (!$post_id) {
        $post_id = get_the_ID();
    }
    
    if (!$post_id) {
        return $content;
    }
    
    // Initialiser le compteur pour ce post
    global $td_sommaire_counters;
    if (!isset($td_sommaire_counters[$post_id])) {
        $td_sommaire_counters[$post_id] = 1;
    }
    
    // Fonction de callback pour ajouter les IDs
    $callback = function($matches) use ($post_id) {
        global $td_sommaire_counters;
        
        // Créer l'ID unique
        $anchor_id = "post-" . $post_id . "-content-" . $td_sommaire_counters[$post_id];
        $td_sommaire_counters[$post_id]++;
        
        $tag_content = $matches[0];
        $opening_tag = $matches[1];
        $attributes = isset($matches[2]) ? $matches[2] : "";
        $title_text = isset($matches[3]) ? $matches[3] : "";
        
        // Si le H2 a déjà un ID qui commence par "post-", ne pas le modifier
        if (preg_match('/id=["\']post-[^"\']+["\']/i', $attributes)) {
            return $tag_content;
        }
        
        // Si le H2 a un autre ID, le remplacer
        if (preg_match('/id\s*=\s*["\'][^"\']*["\']/i', $attributes)) {
            $attributes = preg_replace('/id\s*=\s*["\'][^"\']*["\']/i', 'id="' . $anchor_id . '"', $attributes);
            return "<h2" . $attributes . ">" . $title_text . "</h2>";
        }
        
        // Si pas d'ID, l'ajouter
        if (!empty($attributes)) {
            return '<h2 id="' . $anchor_id . '"' . $attributes . '>' . $title_text . '</h2>';
        } else {
            return '<h2 id="' . $anchor_id . '">' . $title_text . '</h2>';
        }
    };
    
    // Pattern pour capturer tous les types de H2
    $pattern = '/<h2(\s+[^>]*)?>(.*?)<\/h2>/is';
    $content = preg_replace_callback($pattern, $callback, $content);
    
    return $content;
}

/**
 * Shortcode pour générer le sommaire
 */
function td_sommaire_shortcode($atts) {
    // Récupérer l'ID du post actuel
    $post_id = get_the_ID();
    
    if (!$post_id) {
        return "<!-- Impossible de récupérer l'ID du post -->";
    }
    
    // Récupérer le contenu brut du post
    $post = get_post($post_id);
    if (!$post) {
        return "<!-- Post non trouvé -->";
    }
    
    // Utiliser le contenu brut pour détecter les H2
    $content = $post->post_content;
    
    // Appliquer les filtres de contenu mais sans do_shortcode pour éviter la récursion
    remove_filter("the_content", "do_shortcode", 11);
    $content = apply_filters("the_content", $content);
    add_filter("the_content", "do_shortcode", 11);
    
    // Extraire tous les H2 du contenu
    preg_match_all('/<h2[^>]*>(.*?)<\/h2>/is', $content, $matches);
    
    if (empty($matches[1])) {
        return "<!-- Aucun titre H2 trouvé -->";
    }
    
    // Construire le sommaire
    $output = '<div class="td-sommaire td-sommaire-' . esc_attr($post_id) . '">';
    $output .= '<nav class="td-sommaire-nav" aria-label="Sommaire">';
    $output .= '<ul class="td-sommaire-list">';
    
    foreach ($matches[1] as $index => $title) {
        // Nettoyer le titre des balises HTML
        $clean_title = wp_strip_all_tags($title);
        
        // Créer l'ID correspondant
        $section_num = $index + 1;
        $anchor_id = "post-" . $post_id . "-content-" . $section_num;
        
        // Ajouter l'élément de liste avec le lien
        $output .= '<li class="td-sommaire-item">';
        $output .= '<a href="#' . esc_attr($anchor_id) . '" class="td-sommaire-link" data-post-id="' . esc_attr($post_id) . '">';
        $output .= esc_html($clean_title);
        $output .= '</a>';
        $output .= '</li>';
    }
    
    $output .= '</ul>';
    $output .= '</nav>';
    $output .= '</div>';
    
    return $output;
}
add_shortcode("sommaire", "td_sommaire_shortcode");

/**
 * Filtre pour ajouter les IDs aux H2
 */
function td_filter_content_add_ids($content) {
    // Ne pas traiter si on est dans l'admin
    if (is_admin()) {
        return $content;
    }
    
    // Vérifier si le shortcode est présent
    if (!has_shortcode($content, "sommaire")) {
        return $content;
    }
    
    // Traiter le contenu
    return td_process_content_with_ids($content);
}
// Priorité très haute pour s'exécuter en premier
add_filter("the_content", "td_filter_content_add_ids", 1);

/**
 * Filtre alternatif pour les thèmes qui n'utilisent pas the_content
 */
function td_filter_post_content($content, $post_id, $post) {
    // Ne pas traiter si on est dans l'admin
    if (is_admin()) {
        return $content;
    }
    
    // Vérifier si le shortcode est présent
    if (!has_shortcode($content, "sommaire")) {
        return $content;
    }
    
    // Traiter le contenu
    return td_process_content_with_ids($content, $post_id);
}
add_filter("render_block_core/post-content", "td_filter_post_content", 10, 3);

/**
 * Ajouter les styles CSS pour le sommaire
 */
function td_sommaire_styles() {
    // Ne pas charger si on est dans l'admin
    if (is_admin()) {
        return;
    }
    ?>
    <style>
        /* Styles pour le sommaire */
        .td-sommaire {
            margin: 30px 0;
            padding: 5px 20px;
            background: #f5f5f5;
            border-radius: 8px;
        }
        
        .td-sommaire-nav {
            position: relative;
        }
        
        .td-sommaire-list {
            list-style: none;
            margin: 0;
            padding: 0;
        }
        
        .td-sommaire-item {
            margin: 10px 0;
            position: relative;
            padding-left: 20px;
        }
        
        .td-sommaire-item::before {
            content: "→";
            position: absolute;
            left: 0;
            color: #ffc239;
        }
        
        .td-sommaire-link {
            color: #333;
            text-decoration: none;
            transition: color 0.3s ease;
            display: inline-block;
        }
        
        .td-sommaire-link:hover {
            color: #0073aa;
            text-decoration: underline;
        }
        
        /* Smooth scroll pour les ancres */
        html {
            scroll-behavior: smooth;
        }
        
        /* Espacement pour les titres avec ancres */
        h2[id^="post-"] {
            scroll-margin-top: 80px;
        }
        
        /* Responsive */
        @media (min-width: 1000px) {
            .td-sommaire {
                padding: 25px 30px;
            }
            
            .td-sommaire-item {
                margin: 12px 0;
                padding-left: 25px;
            }
        }
    </style>
    <?php
}
add_action("wp_head", "td_sommaire_styles");

/**
 * Ajouter un script pour le smooth scroll
 */
function td_sommaire_scripts() {
    // Ne pas charger si on est dans l'admin
    if (is_admin()) {
        return;
    }
    ?>
    <script>
        document.addEventListener("DOMContentLoaded", function() {
            // Fonction pour ajouter les IDs manquants aux H2
            function td_ensure_h2_ids() {
                // Trouver tous les sommaires
                const sommaires = document.querySelectorAll(".td-sommaire");
                
                sommaires.forEach(function(sommaire) {
                    // Extraire l'ID du post depuis la classe
                    const classes = sommaire.className.split(" ");
                    let postId = null;
                    
                    classes.forEach(function(className) {
                        if (className.startsWith("td-sommaire-")) {
                            postId = className.replace("td-sommaire-", "");
                        }
                    });
                    
                    if (!postId) return;
                    
                    // Trouver le conteneur parent .wp-block-post
                    const postContainer = sommaire.closest(".wp-block-post");
                    if (!postContainer) return;
                    
                    // Trouver tous les H2 dans .entry-content de ce post
                    const entryContent = postContainer.querySelector(".entry-content");
                    if (!entryContent) return;
                    
                    const headings = entryContent.querySelectorAll("h2");
                    
                    headings.forEach(function(h2, index) {
                        // Si le H2 n'a pas d'ID ou un ID qui ne commence pas par "post-"
                        if (!h2.id || !h2.id.startsWith("post-")) {
                            h2.id = "post-" + postId + "-content-" + (index + 1);
                        }
                    });
                });
            }
            
            // Appliquer les IDs
            td_ensure_h2_ids();
            
            // Gérer les clics sur les liens du sommaire
            const sommaireLinks = document.querySelectorAll(".td-sommaire-link");
            
            sommaireLinks.forEach(function(link) {
                link.addEventListener("click", function(e) {
                    e.preventDefault();
                    
                    const targetId = this.getAttribute("href").substring(1);
                    const targetElement = document.getElementById(targetId);
                    
                    if (targetElement) {
                        // Calculer la position avec offset pour header fixe
                        const offsetTop = targetElement.getBoundingClientRect().top + window.pageYOffset - 80;
                        
                        window.scrollTo({
                            top: offsetTop,
                            behavior: "smooth"
                        });
                        
                        // Mettre à jour l'URL
                        if (history.pushState) {
                            history.pushState(null, null, "#" + targetId);
                        }
                    }
                });
            });
            
            // Gestion des ancres au chargement
            if (window.location.hash) {
                setTimeout(function() {
                    const hash = window.location.hash.substring(1);
                    const targetElement = document.getElementById(hash);
                    
                    if (targetElement) {
                        const offsetTop = targetElement.getBoundingClientRect().top + window.pageYOffset - 80;
                        window.scrollTo({
                            top: offsetTop,
                            behavior: "smooth"
                        });
                    }
                }, 100);
            }
        });
    </script>
    <?php
}
add_action("wp_footer", "td_sommaire_scripts");


/**
 * Ajoute un ID unique à chaque balise H2 dans le contenu d'un article.
 * L'ID est formaté comme suit : post-ID-content-NUM
 * où ID est l'ID de l'article et NUM est un compteur incrémentiel.
 */
add_filter( 'the_content', 'ajouter_id_aux_titres_h2' );

function ajouter_id_aux_titres_h2( $content ) {

    // On s'assure de n'exécuter le code que sur les pages/articles seuls
    // et non sur les archives, la page d'accueil, etc.
    if ( is_singular() && in_the_loop() && is_main_query() ) {

        global $post;
        $post_id = $post->ID;
        $counter = 1;

        // On utilise preg_replace_callback pour trouver chaque H2 et le modifier
        $content = preg_replace_callback(
            '/<h2(.*?)>(.*?)<\/h2>/i', // La regex qui cible les balises H2
            function( $matches ) use ( $post_id, &$counter ) {
                
                $attributes = $matches[1]; // Attributs existants (ex: class="...")
                $title_text = $matches[2]; // Le texte à l'intérieur du H2

                // Si le H2 a déjà un ID, on ne fait rien pour éviter les conflits
                if ( strpos( $attributes, 'id=' ) !== false ) {
                    return $matches[0]; // Retourne la balise H2 originale inchangée
                }

                // On construit le nouvel ID
                $new_id = 'post-' . $post_id . '-content-' . $counter;

                // On incrémente le compteur pour le prochain H2
                $counter++;

                // On reconstruit la balise H2 avec le nouvel ID
                return '<h2 id="' . esc_attr( $new_id ) . '"' . $attributes . '>' . $title_text . '</h2>';
            },
            $content
        );
    }

    return $content; // On retourne le contenu (modifié ou non)
}