const express = require('express');
const exphbs = require('express-handlebars');
const path = require('path');
const cookieParser = require('cookie-parser');
const axios = require('axios');
const bodyParser = require('body-parser');
const Wikiapi = require('wikiapi');
const wiki = new Wikiapi('fr');
const app = express();
const morgan = require('morgan');

app.use(morgan('dev'));

// Configuration du moteur de modèle Handlebars
app.engine('.hbs', exphbs.engine({ extname: '.hbs' }));
app.set('view engine', '.hbs');
app.set('views', path.join(__dirname, 'views'));

// Middleware pour servir les fichiers statiques
app.use(express.static(path.join(__dirname, '/')));

// Utilisation de cookie-parser comme middleware
app.use(cookieParser());

// Middleware pour gérer le thème basé sur le cookie

/*
app.use((req, res, next) => {
    if (req.cookies.theme === 'dark') {
        // Si le cookie "theme" est défini sur "dark", ajoutez la classe "dark" au <html>
        res.locals.theme = 'dark';
    } else {
        // Sinon, retirez la classe "dark"
        res.locals.theme = '';
    }
    next();
});
*/

// Middleware body-parser pour traiter les données POST du formulaire
app.use(bodyParser.urlencoded({ extended: false }));

// ================ FONCTIONS ==============================

// Fonction de nettoyage personnalisée (pour infobox)
function cleanInfoboxText(text) {
    // Supprimer les balises HTML
    const cleanedText = text.replace(/<\/?[^>]+(>|$)/g, "");

    // Supprimer les caractères '{' et '}'
    const cleanedTextWithoutBraces = cleanedText.replace(/[{}]/g, "");

    // Supprimer le caractère '|'
    const cleanedTextWithoutPipe = cleanedTextWithoutBraces.replace(/\|/g, "");

    // Supprimer les caractères '[' et ']'
    const finalText = cleanedTextWithoutPipe.replace(/[\[\]]/g, "");

    return finalText.trim();
}

// Fonction pour récupérer les informations d'un article depuis l'API MediaWiki
async function fetchArticleInfoFromAPI(articleTitle) {
    try {
        // Définir les paramètres de la requête pour obtenir les suggestions de titre
        const suggestionParams = new URLSearchParams({
            action: 'opensearch',
            search: articleTitle,
            format: 'json',
        });

        // Effectuer la requête GET pour obtenir les suggestions de titre
        const suggestionResponse = await axios.get(`https://fr.wikipedia.org/w/api.php?${suggestionParams.toString()}`);
        const suggestionData = suggestionResponse.data;

        // Vérifier s'il y a des suggestions de titre
        if (Array.isArray(suggestionData[1]) && suggestionData[1].length > 0) {
            // Utiliser le premier titre suggéré comme titre de l'article
            articleTitle = suggestionData[1][0];
        }

        // Répéter la requête pour obtenir les informations de l'article avec le titre corrigé ou suggéré
        const params = new URLSearchParams({
            action: 'query',
            titles: articleTitle,
            format: 'json',
            prop: 'extracts|info|revisions|pageimages', // Ajoutez 'pageimages' pour obtenir les informations sur l'image
            inprop: 'url',
            explaintext: true,
            rvprop: 'timestamp|user|size|ids',
            rvlimit: 1,
            piprop: 'original', // Spécifiez 'original' pour obtenir l'URL de l'image originale
        });

        // Effectuer la requête GET à l'API MediaWiki
        const response = await axios.get(`https://fr.wikipedia.org/w/api.php?${params.toString()}`);
        const data = response.data;

        // ==== RECHERCHE INFOBOX ====

        let infobox = {};

        // Vérifiez si articleTitle est défini et non vide
        if (articleTitle) {
            const page_data = await wiki.page(articleTitle);
            const parsed = page_data.parse();

            const variablesExclues = ['image', 'blason', 'drapeau', 'logo', 'légende', 'carte', 'légende-carte', 'Site-Internet', 'siteweb', '_', 'statut', 1, 2, 3, 4, 5, 6, 7, 8, 9];

            // Lire les modèles Infobox, les convertir en JSON.
            parsed.each('template', (template_token) => {
                if (template_token.name.startsWith('Infobox')) {
                    const parameters = template_token.parameters;
                    for (const key of Object.keys(parameters)) {
                        const value = parameters[key];
                        if (value !== '' && !variablesExclues.some(excluded => key.includes(excluded))) {
                            infobox[key] = cleanInfoboxText(value.toString()); // Appliquer la fonction de nettoyage ici
                        }
                    }
                    return parsed.each.exit;
                }
            });

            // Vérifiez si l'infobox est vide
            if (Object.keys(infobox).length === 0) {
                console.log("Warning : Pas d'infobox");
                infobox = {
                    Erreur: "Pas d'infobox sur wikipédia"
                };
            }

        } else {
            return null;
        }

        // ------------------------------------------------------------

        // Vérifier si 'query' existe dans les données
        if (data.query) {
            // Obtenir la première page (il peut y avoir plusieurs résultats, nous prenons le premier)
            const page = Object.values(data.query.pages)[0];

            if (page.missing !== undefined) {
                console.log(`Warning : l'article "${articleTitle}" n'a pas été trouvé.`);
                return null;
            } else {

                // Fonction pour limiter le texte à 300 caractères et s'arrêter au dernier point
                function limitTextTo300Chars(text) {
                    if (text.length <= 300) {
                        // Si le texte est déjà inférieur ou égal à 300 caractères, retournez-le tel quel
                        return text;
                    } else {
                        // Trouvez le dernier point dans les 300 premiers caractères
                        const truncatedText = text.substring(0, 300);
                        const lastPeriodIndex = truncatedText.lastIndexOf('.');

                        if (lastPeriodIndex !== -1) {
                            // S'il y a un point dans les 300 premiers caractères, coupez le texte jusqu'à ce point
                            return truncatedText.substring(0, lastPeriodIndex + 1);
                        } else {
                            // S'il n'y a pas de point, retournez simplement les 200 premiers caractères
                            return truncatedText;
                        }
                    }
                }

                // Extraire les informations
                const articleInfo = {
                    url: page.fullurl,
                    title: page.title,
                    extract: page.extract ? limitTextTo300Chars(page.extract) : 'Non disponible',
                    lastEdit: page.revisions ? new Date(page.revisions[0].timestamp).toLocaleString() : 'Non disponible',
                    numRevisions: page.revisions ? page.revisions[0].revid : 'Non disponible',
                    pageSize: page.revisions ? page.revisions[0].size : 'Non disponible',
                    firstRevisionUser: page.revisions ? page.revisions[0].user : 'Non disponible',
                    latestRevisionId: page.revisions ? page.revisions[0].revid : 'Non disponible',
                    pageId: page.pageid ? page.pageid : 'Non disponible',
                    latestVersion: page.revisions ? page.revisions[0].parentid : 'Non disponible',
                    wordCount: page.extract ? page.extract.split(/\s+/).length : 'Non disponible',
                    charCount: page.extract ? page.extract.length : 'Non disponible',
                    lastContributor: page.revisions ? page.revisions[0].user : 'Non disponible',
                    image: page.original ? page.original.source : 'Non disponible',
                    infobox,
                };

                return articleInfo;
            }
        } else {
            console.log(`Warning :l'article "${articleTitle}" n'a pas été trouvé.`);
            return null;
        }
    } catch (error) {
        console.error('Erreur : lors de la récupération des informations depuis l\'API :', error);
        return null;
    }
}

// ===================== ROUTES ==========================

// Index
app.get('/', async (req, res) => {

    // Renvoyez la page index avec les informations de l'article et de l'infobox
    res.render('contains/index', { pageTitle: 'Accueil' });

});


// Comparaison d'articles
app.post('/search', async (req, res) => {
    try {
        // Récupérez les données du formulaire depuis req.body comme d'habitude
        const articleTitle1 = req.body.articleTitle1;
        const articleTitle2 = req.body.articleTitle2;

        // Utilisez la fonction pour récupérer les informations des articles
        const articleInfo1 = await fetchArticleInfoFromAPI(articleTitle1);
        const articleInfo2 = await fetchArticleInfoFromAPI(articleTitle2);

        // Renvoyez la réponse au format JSON
        res.json({ articleInfo1, articleInfo2 });
    } catch (error) {
        console.error('Erreur lors de la recherche d\'informations sur les articles :', error);
        res.status(500).json({ error: 'Une erreur s\'est produite lors de la recherche d\'informations sur les articles.' });
    }
});

// Historique
app.get('/historique', (req, res) => {
    res.render('contains/historique', { pageTitle: 'Historique' });
});


// Connexion
app.get('/connexion', (req, res) => {
    res.render('contains/signin', { pageTitle: 'Connexion' });
});

// Inscription
app.get('/inscription', (req, res) => {
    res.render('contains/signup', { pageTitle: 'Inscription' });
});


/* EXEMPLE UTILISATION COOKIE

// Changer le thème en fonction de la case cochée
app.post('/toggle-theme', (req, res) => {
    if (req.cookies.theme === 'dark') {
        // Si le thème est actuellement "dark", changez-le en "light"
        res.cookie('theme', 'light', { sameSite: 'None', secure: true });
    } else {
        // Sinon, changez-le en "dark"
        res.cookie('theme', 'dark', { sameSite: 'None', secure: true });
    }
    res.redirect(req.get('referer'));
});
*/


// 404
app.use((req, res, next) => {
    res.status(404).render('contains/404', { title: 'Erreur 404' });
});




// ======================== PORT ===========================

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
    console.log(`Info : le serveur est en écoute sur le port ${PORT}`);
});
