/////////////////////////////////////////////////
// APPELS DES MODULES
/////////////////////////////////////////////////
const path = require("path");
// CALCUL DE DATE
const moment = require('moment');
// uuid
const { v4: uuidv4 } = require('uuid');
const mysql = require('mysql2');
const mysql_promise = require('mysql2/promise');
const fetch = require('node-fetch');
const fs = require('fs/promises');
const nodemailer = require('nodemailer');

/////////////////////////////////////////////////
// APPELS DES MODULES PERSOS
/////////////////////////////////////////////////
// loggings
const logger = require("../public/js/app/logger_adhesion");
// DB
const { connect_DB_promise } = require('../modules/db/databaseconnect');

////////////////////////////////////////////////////
// FILE NAME
////////////////////////////////////////////////////
const filename = path.parse(__filename).base;



const runSync_prof_strapi = async function(req, res) {

    // LOG - Récupération du numéro de session web
    // en mode CRON il n'y a pas de session web, donc pas de req.session, donc on met "cron" à la place
    const sid = req?.session?.id || "cron";
    logger.info(`sid=${sid}`, { numsession: sid, label: filename });

    logger.info("======================================", { numsession: sid, label: filename });
    logger.info("======== FUNCTION sync_prof_strapi ==========", { numsession: sid, label: filename });
    logger.info("======================================", { numsession: sid, label: filename });

    ////////////////////////////////////////////////////
    // VARIABLES
    ////////////////////////////////////////////////////



    // On récupère les variables de ENV
    const {
        DOMAIN_STRAPI,
        strapi_token,
        db_connection_host,
        db_connection_port,
        db_connection_user,
        db_connection_password,
        db_connection_database
    } = process.env;
    logger.info(`DOMAIN_STRAPI=${DOMAIN_STRAPI}, db_connection_host=${db_connection_host}`, { numsession: sid, label: filename });

    ////////////////////////////////////////////////////
    // CONNEXION DATABASE
    ////////////////////////////////////////////////////
    // Initialisation de la connexion avec la BD
    const db_connection_promise = await mysql_promise.createConnection({
        host: db_connection_host,
        port: db_connection_port,
        user: db_connection_user,
        password: db_connection_password,
        database: db_connection_database
    });
    //console.log("db_connection_promise = ", db_connection_promise);

    ////////////////////////////////////////////////////
    // FONCTIONS
    ////////////////////////////////////////////////////

    // Récupération de la lat, long et région, de toutes les villes de France et Dom-TOM, depuis le json
    // pour l'ajout de la lat, long et region dans les données de strapi pour le prof
    let CP_MAP = null;
    async function loadCpMap(filePath = "src/data/cp_region_lat_long.json") {
        if (CP_MAP) return CP_MAP;
        const buf = await fs.readFile(filePath, "utf8");
        CP_MAP = JSON.parse(buf);
        return CP_MAP;
    }

    // ==== GEO helpers ====
    // Fonctions pour normaliser le code postal saisie dans le formulaire par l’adhérent
    function normalizeCp(cp) {
        if (!cp) return null;
        const s = String(cp).trim().replace(/\s+/g, "");
        return /^\d{5}$/.test(s) ? s : null;
    }
    function pickProfPostalCode(row) {
        return (
            normalizeCp(row.adherent_prof_ecole1_cp) || null
        );
    }

    // helper pour convertir en nombre sûr (gère "48,85" et strings)
    const toNum = (v) => {
        if (v == null) return null;
        const n = (typeof v === "number") ? v : parseFloat(String(v).replace(",", "."));
        return Number.isFinite(n) ? n : null;
    };

    // ==== FONCTION D'AJOUT DES PROFS DANS STRAPI ====
    const upsert = async (payload) => {
        logger.info("======== FUNCTION upsert ==========", { numsession: sid, label: filename });

        // on cherche les professeurs dont adherent_mail est égal à payload.data.adherent_mail. Si pas d’email, on met "".
        // URLSearchParams classe native de JavaScript (dans Node.js et dans les navigateurs) qui sert à construire et manipuler des chaînes de requête (?clé=valeur&clé2=valeur2)
        // ex de sortie q = filters%5Badherent_mail%5D%5B%24eq%5D=julie%40test.com
        logger.info(`search = ${payload.data.adherent_mail}`, { numsession: sid, label: filename });
        const q = new URLSearchParams({ "filters[adherent_mail][$eq]": payload.data.adherent_mail || "" });
        // URL d'interogration strapi
        const getUrl = `${DOMAIN_STRAPI}/api/adherent-professeurs?${q.toString()}`;
        // Recherche dans Strapi
        const r0 = await fetch(getUrl, { headers: { Authorization: `Bearer ${strapi_token}` }});
        // lis le corps de la réponse HTTP et convertis-le depuis du JSON en objet JavaScript utilisable
        const j0 = await r0.json();
        const found = j0?.data?.[0];
        logger.info(`found  = ${found?.attributes?.adherent_mail}`, { numsession: sid, label: filename });
        console.log("found = ", found);

        if (found?.id) {
            // déjà présent → on met à jour avec les nouvelles données
            const putUrl = `${DOMAIN_STRAPI}/api/adherent-professeurs/${found.id}`;
            logger.info(`putUrl  = ${putUrl}`, { numsession: sid, label: filename });
            console.log("payload = ", payload);
            const r = await fetch(putUrl, {
                method: "PUT",
                headers: {
                    "Content-Type": "application/json",
                    Authorization: `Bearer ${strapi_token}`
                },
                body: JSON.stringify(payload)
            });

            //console.log("r du fetch : ", r);

            if (!r.ok) {
                const txt = await r.text();
                throw new Error(`PUT ${putUrl} -> ${r.status} ${txt}`);
            }
            const j = await r.json();
            return { action: "update", id: j?.data?.id ?? found.id };
        } else {
            const postUrl = `${DOMAIN_STRAPI}/api/adherent-professeurs`;
            logger.info(`postUrl  = ${postUrl}`, { numsession: sid, label: filename });
            const r = await fetch(postUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    Authorization: `Bearer ${strapi_token}`
                },
                body: JSON.stringify(payload)
            });
            if (!r.ok) {
                const txt = await r.text();
                throw new Error(`POST ${postUrl} -> ${r.status} ${txt}`);
            }
            const j = await r.json();
            return { action: "create", id: j?.data?.id };
        }
    };

    ////////////////////////////////////////////////////
    // LANCEMENT DES FONCTIONS
    ////////////////////////////////////////////////////
    try {

        // ==== AJOUT DES PROFS DANS STRAPI ====
        let creates = 0, errors = 0, attempted = 0, updates = 0;

        // ==== RÉCUPÉRATION DES DONNÉES SUR LES PROFS DANS LA DB ADUZUKI (SQL) ====
        const [rows] = await db_connection_promise.query(`
            SELECT
                ID,
                association_suzuki,
                adherent_nom,
                adherent_prenom,
                adherent_mail,
                adherent_telephone_mobile,
                adherent_prof_instrument1,
                adherent_prof_instrument1_esa,
                adherent_prof_instrument2,
                adherent_prof_instrument2_esa,
                adherent_prof_sece,
                adherent_prof_ecole1,
                adherent_prof_ecole1_mail,
                adherent_prof_ecole1_web,
                adherent_prof_ecole1_cp,
                adherent_prof_ecole1_ville,
                adherent_prof_ecole2,
                adherent_prof_ecole2_mail,
                adherent_prof_ecole2_web,
                adherent_prof_ecole2_cp,
                adherent_prof_ecole2_ville,
                adherent_prof_ecole3,
                adherent_prof_ecole3_mail,
                adherent_prof_ecole3_web,
                adherent_prof_ecole3_adresse,
                adherent_prof_ecole3_cp,
                adherent_prof_ecole3_ville
            FROM adherent_professeur
        `);
        //console.log('rows = ', rows);

        // Lancement de la récupération des lat, long et régions depuis le json
        const cpMap = await loadCpMap("src/data/cp_region_lat_long.json");
        //console.log("CP_MAP = ", CP_MAP);

        // TRAITEMENT DE CHAQUE PROF DE LA BD POUR L'AJOUTER DANS STRAPI
        for (const r of rows) {
            // 3.1 choisir le CP prioritaire
            const cp = pickProfPostalCode(r);
            let geo_lat = null, geo_lng = null, geo_region = null;

            if (cp && cpMap[cp]) {
                const meta = cpMap[cp];
                // tolérance: on ne renseigne que si lat/lng sont présents
                geo_lat    = toNum(meta.lat);
                geo_lng    = toNum(meta.lng);
                geo_region = meta.region ? String(meta.region) : null;
            }

            // 3.2 payload de base
            const data = {
                association_suzuki: r.association_suzuki?.trim() || null,
                adherent_nom: r.adherent_nom?.trim() || null,
                adherent_prenom: r.adherent_prenom?.trim() || null,
                adherent_mail: r.adherent_mail?.toString().trim().toLowerCase() || null,
                adherent_telephone_mobile: r.adherent_telephone_mobile?.trim() || null,
                adherent_prof_instrument1: r.adherent_prof_instrument1?.trim() || null,
                adherent_prof_instrument1_niveau: r.adherent_prof_instrument1_esa?.trim() || null,
                adherent_prof_instrument2: r.adherent_prof_instrument2?.trim() || null,
                adherent_prof_instrument2_niveau: r.adherent_prof_instrument2_esa?.trim() || null,
                adherent_prof_sece: r.adherent_prof_sece?.trim() || null,
                adherent_prof_ecole1: r.adherent_prof_ecole1?.trim() || null,
                adherent_prof_ecole1_mail: r.adherent_prof_ecole1_mail?.trim() || null,
                adherent_prof_ecole1_web: r.adherent_prof_ecole1_web?.trim() || null,
                adherent_prof_ecole1_cp: r.adherent_prof_ecole1_cp?.trim() || null,
                adherent_prof_ecole1_ville: r.adherent_prof_ecole1_ville?.trim() || null,
                adherent_prof_ecole2: r.adherent_prof_ecole2?.trim() || null,
                adherent_prof_ecole2_mail: r.adherent_prof_ecole2_mail?.trim() || null,
                adherent_prof_ecole2_web: r.adherent_prof_ecole2_web?.trim() || null,
                adherent_prof_ecole2_cp: r.adherent_prof_ecole2_cp?.trim() || null,
                adherent_prof_ecole2_ville: r.adherent_prof_ecole2_ville?.trim() || null,
                adherent_prof_ecole3: r.adherent_prof_ecole3?.trim() || null,
                adherent_prof_ecole3_mail: r.adherent_prof_ecole3_mail?.trim() || null,
                adherent_prof_ecole3_web: r.adherent_prof_ecole3_web?.trim() || null,
                adherent_prof_ecole3_adresse: r.adherent_prof_ecole3_adresse?.trim() || null,
                adherent_prof_ecole3_cp: r.adherent_prof_ecole3_cp?.trim() || null,
                adherent_prof_ecole3_ville: r.adherent_prof_ecole3_ville?.trim() || null,
                adherent_prof_ecole3_ville: r.adherent_prof_ecole3_ville?.trim() || null,
                Saison: "2025/2026",
                // >>> Injecte UNIQUEMENT des scalaires, si valides
                ...(geo_region ? { adherent_prof_ecole1_region: geo_region } : {}),
                ...(geo_lat    != null ? { adherent_prof_ecole1_lat:  geo_lat } : {}),
                ...(geo_lng    != null ? { adherent_prof_ecole1_long: geo_lng } : {})
            };

            // champs obligatoires minimum
            if (!data.adherent_mail || !data.adherent_nom || !data.adherent_prenom) {
                console.warn(`skip: mail/nom/prenom manquants`);
                continue;
            }

            try {
                attempted++;
                const res = await upsert({ data });
                if (res.action === "create") creates++;
                else if (res.action === "update") updates++;
            } catch (e) {
                errors++;
                console.error(`ETL error ->`, e.message);
            }
        }

        await db_connection_promise.end();

        logger.info(`Done. attempted=${attempted} updates=${updates} created=${creates} errors=${errors}`, { numsession: sid, label: filename });
        
        
        ///////////////////////////////////////////////////////////////////////
        // ENVOIE MAIL APRES EXECUTION
        logger.info("MAIL MAJ ANNUAIRE PROF ENVOI AVANT", { numsession: sid });
        var transporter = nodemailer.createTransport({
            service: 'gmail',
            auth: {
                user: process.env.nodemailer_user,
                pass: process.env.nodemailer_pass
            }
        });
        var mail_objet = "ADUZUKI - CRON MAJ ANNUAIRE PROF";
        mail_html = "<p>Pour l'administrateur de l'application ADUZUKI,</p><br><p>Ceci est le mail d'envoi pour confirmer l'exécution du Webhook de mise à jour de l'annuaire des profs qui se fait la nuit à 4h.</p>";
        mail_html += "<p>- nombre de <strong>professeurs à ajouter</strong> : ";
        mail_html += attempted;
        mail_html += "</p>";
        mail_html += "<p>- nombre de <strong>professeurs créés</strong> : ";
        mail_html += creates;
        mail_html += "</p>";
        mail_html += "<p>- nombre de <strong>professeurs non ajoutés</strong> pour cause probable de doublon : ";
        mail_html += updates;
        mail_html += "</p>";
        mail_html += "<p>- nombre d'<strong>erreurs</strong> : ";
        mail_html += errors;
        mail_html += "</p>";
        
        mail_html += "<br><p>Julie Chaumard</p><p>Développeuse web de l'agence Parisweb.art</p>";
        
        var mailOptions = {
            from: 'afps.inscription@gmail.com',
            to: "projet@parisweb.art",
            subject: mail_objet,
            html: mail_html
        };

        transporter.sendMail(mailOptions, function(error, info){
            if (error) {
            logger.info("error" + error, { numsession: sid });
            } else {
            logger.info("Email envoyé: " + info.response, { numsession: sid });
            }
        });
        logger.info("MAIL MAJ ANNUAIRE PROF ENVOI APRES", { numsession: sid });

        
        
        // --- Réponse HTTP IMMÉDIATE
        const retour = {
            ok: true,
            attempted,
            creates,
            updates,
            errors
        };

        logger.info("sync_prof_strapi terminé", { label: filename, numsession: sid });
        res.status(200).json(retour);

    } catch (e) {
        logger.error("sync_prof_strapi FAILED", {
        label: filename,
        numsession: sid,
        message: e.message,
        stack: e.stack
        });
        // Réponse d’erreur JSON claire
        return res.status(500).json({ ok: false, error: e.message });
    }
    
}

/////////////////////////////////////////////////
// EXPORT DE MODULE POUR QU'IL SOIT LU DANS LES AUTRES FICHIERS JS
/////////////////////////////////////////////////

module.exports = {
    runSync_prof_strapi
}