const fs = require("fs");
const csv = require("csv-parser");
const path = require("path");

const generateMoyenne = (scoreType, year, precision = 3) => {
    // Dictionnaire de correspondance scoreType -> colonne CSV
    let dictCorr = {
        "indicateurs": "score_global",
        "indicateursPH": "score_pH",
        "indicateursChlore": "score_Chlore",
        "indicateursNitritesNitrates": "score_Nitrites_Nitrates",
        "indicateursMetauxLourds": "score_Metaux_Lourds",
        "indicateursPesticides": "score_Pesticides"
    };
    let columnName = dictCorr[scoreType];
    return new Promise((resolve, reject) => {
        const filePath = path.join(__dirname, `data/sigmoid_scores_${year}.csv`);
        
        if (!fs.existsSync(filePath)) {
            return reject(new Error(`Fichier introuvable : sigmoid_scores_${year}.csv`));
        }

        let moyenne = 0;
        let length = 0;

        fs.createReadStream(filePath)
            .pipe(csv())
            .on('data', (row) => {
                const score = parseFloat(row[columnName]);
                if (!isNaN(score)) {
                    moyenne += score;
                    length++;
                } else {
                    console.warn(`Valeur non numérique trouvée dans la colonne ${columnName}:`, row[columnName]);
                }
            })
            .on('end', () => {
                if (length === 0) {
                    console.error('Aucun score valide trouvé dans le fichier CSV');
                    return reject(new Error('Aucun score valide trouvé'));
                }
                moyenne = (moyenne / length).toFixed(precision);
                resolve(moyenne);
            })
            .on('error', (error) => {
                console.error('Erreur lors de la lecture du fichier CSV:', error);
                reject(error);
            });
    });
};

const generateMoyenneByYear = async (scoreType) => {
    let years = [2018, 2019, 2020, 2021, 2022, 2023, 2024];
    let moyennes = {};
    for (let year of years) {
        try {
            moyennes[year] = await generateMoyenne(scoreType, year, precision = 4);
        } catch (error) {
            console.error(`Erreur lors du calcul de la moyenne pour l'année ${year}:`, error);
        }
    }
    return moyennes;
}

// Fonction pour générer les moyennes des scores par commune selon le type de score
const generateCommuneAveragesByScoreType = (dept, year, scoreType) => {
    return new Promise((resolve, reject) => {
        const filePath = path.join(__dirname, `data/sigmoid_scores_${year}.csv`);

        if (!fs.existsSync(filePath)) {
            return reject(new Error(`Fichier introuvable : sigmoid_scores_${year}.csv`));
        }

        const scoreColumns = {
            "indicateurs": "score_global",
            "indicateursPH": "score_pH",
            "indicateursChlore": "score_Chlore",
            "indicateursNitritesNitrates": "score_Nitrites_Nitrates",
            "indicateursMetauxLourds": "score_Metaux_Lourds",
            "indicateursPesticides": "score_Pesticides"
        };

        // Vérification du type de score
        if (!scoreColumns[scoreType]) {
            return reject(new Error(`Type de score invalide : ${scoreType}`));
        }

        const averagesByCommune = {};

        fs.createReadStream(filePath)
            .pipe(csv())
            .on('data', (row) => {
                if (parseInt(row.cddept_x) === parseInt(dept)) {
                    const communeCode = row.inseecommune;
                    const score = parseFloat(row[scoreColumns[scoreType]]);

                    if (!isNaN(score)) {
                        if (!averagesByCommune[communeCode]) {
                            averagesByCommune[communeCode] = {
                                name: row.nomcommune,
                                totalScore: 0,
                                count: 0
                            };
                        }
                        averagesByCommune[communeCode].totalScore += score;
                        averagesByCommune[communeCode].count++;
                    }
                }
            })
            .on('end', () => {
                // Calcul de la moyenne pour chaque commune
                const result = Object.values(averagesByCommune).map(commune => ({
                    name: commune.name,
                    average: (commune.totalScore / commune.count)
                }));

                resolve(result);
            })
            .on('error', (error) => {
                reject(error);
            });
    });
};

// Fonction pour générer le top 5 des communes
const generateTop5Communes = (dept, year, scoreType) => {
    return new Promise((resolve, reject) => {
        generateCommuneAveragesByScoreType(dept, year, scoreType)
            .then((averages) => {
                // Tri des communes par score moyen décroissant et récupération des 5 premières
                const top5 = averages
                    .sort((a, b) => b.average - a.average)  // Tri décroissant
                    .slice(0, 5);

                resolve(top5);
            })
            .catch(reject);
    });
};

// Fonction pour générer le flop 5 des communes
const generateFlop5Communes = (dept, year, scoreType) => {
    return new Promise((resolve, reject) => {
        generateCommuneAveragesByScoreType(dept, year, scoreType)
            .then((averages) => {
                // Tri des communes par score moyen croissant et récupération des 5 premières
                const flop5 = averages
                    .sort((a, b) => a.average - b.average)  // Tri croissant
                    .slice(0, 5);

                resolve(flop5);
            })
            .catch(reject);
    });
};

// Export des fonctions
module.exports = {
    generateMoyenne,
    generateMoyenneByYear,
    generateTop5Communes,
    generateFlop5Communes, 
    generateCommuneAveragesByScoreType
};
