/////////////////////////////////////////////////
// APPELS DES MODULES
/////////////////////////////////////////////////
const moment = require('moment');
const ejs = require('ejs');
const nodemailer = require('nodemailer');
const path = require("path");
const stripe = require('stripe')(process.env.STRIPE_PRIVATE_KEY);
const pdf = require("pdf-creator-node");
const fs = require("fs");
const mysql = require('mysql2');
const mysql_promise = require('mysql2/promise');

// Weasyprint
const weasyprint = require("htmltopdf-weasyprint");

/////////////////////////////////////////////////
// APPELS DES MODULES PERSOS
/////////////////////////////////////////////////
// loggings
const logger = require("../public/js/app/logger_wuzuki");
// Envoie mail
const envoie_mail = require("../modules/envoie_mail");
// DB
const { connect_DB_promise } = require('../modules/db/databaseconnect');
const { generateInsertSQL, extractValues } = require('../modules/db/sqlqueries');


/////////////////////////////////////////////////
// APPELS DES FONCTIONS
/////////////////////////////////////////////////
// FAIRE UNE PAUSE
const sleep = require("./../modules/sleep");

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

/////////////////////////////////////////////////
// GOOGLE SHEET PARAMETERS
/////////////////////////////////////////////////
const { GoogleSpreadsheet } = require('google-spreadsheet');
const GS_creds = require('../inscriptionsafps-53b60452f63d.json');
const { error } = require("console");
// Initialize the sheet - doc ID is the long id in the sheets URL
const GS_don = new GoogleSpreadsheet(process.env.gsheet_don);


/////////////////////////////////////////////////
// VARIABLES GLOBALES
/////////////////////////////////////////////////

/////////////////////////////////////////////////
// ENREGISTREMENT DES INFORMATIONS SAISIES
// ENVOIE VERS STRIPE POUR PAIEMENT
/////////////////////////////////////////////////
const post_form_don = async function(req, res){
  logger.info("======================================");
  logger.info("======== FUNCTION post_form_don ==========");
  logger.info("======================================");

  /////////////////////////////////////////////////
  // RÉCUPÉRATION DES DONNÉES DU FORMULAIRE DANS LA SESSION EN COURS et dans la tableau DATA
  /////////////////////////////////////////////////

  // un tableau : pour récupérer en même temps les informations saisies dans un tableau
  let data = [];
  
  // Boucle sur les noms des champs
  // ajout des infos dans le tablea
  ['montant', 'nom', 'prenom', 'adresse_rue', 'adresse_complement', 'adresse_codepostal', 'adresse_ville', 'adresse_pays', 'mail', 'telephone_mobile', 'commentaire'].forEach(field => {
    req.session[field] = req.body[field];
    data.push({[field] : req.body[field]});
    logger.info("#0" + field + " = " + req.body[field], { numsession: req.session.id, label: filename});
  });
  console.log("data = ", data);


  /////////////////////////////////////////////////
  // AJOUT DANS LA BASE DE DONNÉES
  /////////////////////////////////////////////////

  try {
    //Connexion
    let db_connection_promise = await connect_DB_promise();
    
    // AJOUT DON
    if (req.session.montant) {
      let table = "don";
      
      // Fusionner les objets du tableau "data" qui contient les infos saisis dans le formulaire en un seul objet pour pouvoir le traiter dans la fonction "generateInsertSQL"
      const mergedData = Object.assign({}, ...data);
      console.log("mergedData = ", mergedData);

      // Appel de la fonction qui génère la requête SQL
      const sql = generateInsertSQL(table, mergedData);
      console.log("sql = ", sql);
      const values = extractValues(mergedData);
      console.log("values = ", values);

      // lancement de la requête
      const [result_sql, fields] = await db_connection_promise.execute(sql, values);
      logger.info("#1 result_sql Row ID added : " + result_sql.insertId, { numsession: req.session.id, label: filename});


      /////////////////////////////////////////////////
      // ENVOIE VERS STRIPE
      
      logger.info("======== ENVOIE VERS STRIPE ==========", { label: filename });

      // STRIPE - ETAPE 1 - CREER l'INTENTION DE PAIEMENT
      const session_stripe = await stripe.checkout.sessions.create({
        
        metadata: {app: "don", identifiant: result_sql.insertId, montant: req.session.montant, nom: req.session.nom +" "+ req.session.prenom},
        
        customer_email: req.session.mail,

        mode: 'payment',
        
        success_url: process.env.STRIPE_DON_SUCCESSURL,
        cancel_url: process.env.STRIPE_DON_CANCELURL,

        line_items: [{
          price_data: {
            currency: 'eur',
            unit_amount: req.session.montant * 100,
            product_data: {
              name: 'Don AFPS',
              description: 'DON AFPS depuis site AFPS',
            },
          },
          quantity: 1,
        }],
        success_url:  process.env.STRIPE_DON_SUCCESSURL,
        cancel_url: process.env.STRIPE_DON_CANCELURL,
      });

      res.redirect(session_stripe.url)

    } else {
      // Les informations saisies sont vides
      logger.info("Il y a un problème avec la saisie des informations du formulaire", { numsession: req.session.id });
      req.session.affiche_err_1 = 'Il y a un problème avec la saisie des informations du formulaire, veuillez recommencer.';
      res.redirect('/don');
    }

  } catch (error) {
      // Echec de connection à la BD
      logger.error("Il y a un problème avec la connection à la base de données ou Stripe post_form_don : " + error, { numsession: req.session.id });
      req.session.affiche_err_1 = '"Il y a un problème système connexion base de données, veuillez recommencer, "' + error;
      res.redirect('/don');
  }




}


/////////////////////////////////////////////////
// RETOUR STRIPE
/////////////////////////////////////////////////
const don_accompte_reussi = async function(req, res) {
    logger.info("======================================");
    logger.info("======== FUNCTION don_accompte_reussi ==========");
    logger.info("======================================");
    //////////////////////////////////////////////////////////////////////////////
    // RETOUR STRIPE
    let id = req.query.id;
    const session_stripe = await stripe.checkout.sessions.retrieve(id);
    let customer_email = session_stripe.customer_email;
    let payment_status = session_stripe.payment_status;
    let amount_total = session_stripe.amount_total/100;
    let stripe_customer = session_stripe.customer;
    let stripe_payment_intent = session_stripe.payment_intent;
    let payment_method_types = session_stripe.payment_method_types;
    let stripe_status = session_stripe.status;

    console.log("payment_status = ", payment_status);
    console.log("stripe_customer = ", stripe_customer);
    console.log("stripe_payment_intent = ", stripe_payment_intent);
    console.log("payment_method_types = ", payment_method_types);
    console.log("stripe_status = ", stripe_status);

    //////////////////////////////////////////////////////////////////////////////
    // PRÉPARATION PAGE PAIEMENT RÉUSSI
    moment.locale('fr');
    let now = moment().format("YYYY-MM-DD HH:mm:ss");
    res.locals.today = now;
    res.locals.montant = amount_total;
    res.locals.mail = customer_email;

    //////////////////////////////////////////////////////////////////////////////
    // AFFICHAGE PAGE PAIEMENT RÉUSSI
    res.render('don/page_templates/don_paiement_reussi.ejs');
}

/////////////////////////////////////////////////
// RETOUR STRIPE
/////////////////////////////////////////////////
const don_accompte_annule = async function(req, res) {
  logger.info("======================================");
  logger.info("======== FUNCTION don_accompte_annule ==========");
  logger.info("======================================");
  //////////////////////////////////////////////////////////////////////////////
  // RETOUR STRIPE
  let id = req.query.id;
  const session_stripe = await stripe.checkout.sessions.retrieve(id);
  let customer_email = session_stripe.customer_email;
  let payment_status = session_stripe.payment_status;
  let amount_total = session_stripe.amount_total/100;
  let stripe_customer = session_stripe.customer;
  let stripe_payment_intent = session_stripe.payment_intent;
  let payment_method_types = session_stripe.payment_method_types;
  let stripe_status = session_stripe.status;

  console.log("payment_status = ", payment_status);
  console.log("stripe_customer = ", stripe_customer);
  console.log("stripe_payment_intent = ", stripe_payment_intent);
  console.log("payment_method_types = ", payment_method_types);
  console.log("stripe_status = ", stripe_status);

  //////////////////////////////////////////////////////////////////////////////
  // PRÉPARATION PAGE PAIEMENT RÉUSSI
  moment.locale('fr');
  let now = moment().format("YYYY-MM-DD HH:mm:ss");
  res.locals.today = now;
  res.locals.montant = amount_total;
  res.locals.mail = customer_email;



  //////////////////////////////////////////////////////////////////////////////
  // AFFICHAGE PAGE PAIEMENT ANNULÉE
  res.render('don/page_templates/don_paiement_annule.ejs');
}


/////////////////////////////////////////////////
// WEBHOOK STRIPE
// BD STATUS PAIEMENT
// ENVOIE PDF JUSTIFICATIF PAR MAIL
// AJOUT DANS LA GOOGLE SHEET
/////////////////////////////////////////////////
async function wh_stripe_don(req, res, event) {

  logger.info("======================================");
  logger.info("======== FUNCTION wh_stripe_don ==========");
  logger.info("======================================");

  moment.locale('fr');
  let now = moment().format("DD/MM/YYYY");
  let dateheure = moment().format("YYYY-MM-DDTHH-mm");

  
  try {
    /////////////////////////////////////////////////
    // MODIFICATION BD STATUS PAYMENT

    //Connexion DB
    let db_connection_promise = await connect_DB_promise();
    
    // AJOUT STATUS PAIEMENT
    let table = "don";

    let sql = 'UPDATE ';
    sql += table;
    sql += ' SET ';
    sql += 'stripe_retour = "' + event.data.object.id + '", ';
    sql += 'statut_paiement = "' + event.data.object.payment_status + '" ';
    sql += ' WHERE id = ' + event.data.object.metadata.identifiant;

    logger.info("#2 sql : " + sql, { numsession: req.session.id, label: filename});

    // lancement de la requête
    const [result_sql, fields] = await db_connection_promise.execute(sql);
    logger.info("#2 result_sql Row ID changed : " + result_sql.changedRows, { numsession: req.session.id, label: filename});

    /////////////////////////////////////////////////
    // SI PAIEMENT RÉUSSI
    if (event.data.object.payment_status === "paid") {

      /////////////////////////////////////////////////
      // RÉCUPÉRATION DES INFOS DE LA BASE DE DONNÉES
      let sql_select = 'SELECT * FROM ';
      sql_select += table;
      sql_select += ' WHERE id = ' + event.data.object.metadata.identifiant;

      logger.info("#3 sql_select : " + sql_select, { numsession: req.session.id, label: filename});
      // lancement de la requête
      const [result_sql_select, fields_select] = await db_connection_promise.execute(sql_select);
      logger.info("REQUETE SQL - result_sql_select = " + result_sql_select.length, { numsession: req.session.id, label: filename});
      logger.info("#3 result_sql_select nom : " + result_sql_select[0].nom, { numsession: req.session.id, label: filename});

      /////////////////////////////////////////////////
      // PDF JUSTIFICATIF DE DON

      const data = {
        nom: result_sql_select[0].nom + ' ' + result_sql_select[0].prenom,
        rue: result_sql_select[0].adresse_rue,
        complement: result_sql_select[0].adresse_complement,
        ville: result_sql_select[0].adresse_codepostal + ' ' + result_sql_select[0].adresse_ville,
        pays: result_sql_select[0].adresse_pays,
        montant: result_sql_select[0].montant,
        date: now
      };
      const htmlContent = await ejs.renderFile('./pdf/template/don_wp.html', data);
      const buffer = await weasyprint(htmlContent);
      const pdfOutputPath = path.join(__dirname, `../pdf/don/don_${result_sql_select[0].nom}_${dateheure}.pdf`);
      fs.writeFileSync(pdfOutputPath, buffer);
      logger.info("PDF CREATED", { numsession: req.session.id, label: filename});

      /////////////////////////////////////////////////
      // ENVOIE MAIL CONFIRM + JUSTIF
      var attachment_name = `${result_sql_select[0].nom}_justificatif_don_AFPS_${dateheure}.pdf`;
      var mail_objet = `ASSOCIATION FRANÇAISE POUR LA PÉDAGOGIE SUZUKI - VOTRE DON - ${result_sql_select[0].nom}`;
      var mail_html = `<p>Bonjour,</p><br><p>Nous vous remercions chaleureusement pour votre don de ${result_sql_select[0].montant}€ à l'Association Française pour le Pédagogie Suzuki.</p><br><p>Veuillez trouver le justificatif en pièce jointe.</p><br><p>Association Française pour la pédagogie Suzuki<br>Chez Anne PAGES<br>30 rue des Tattes<br>74500 PUBLIER</p>`;
      var mailOptions = {
        from: 'afps.inscription@gmail.com',
        to: result_sql_select[0].mail,
        subject: mail_objet,
        html: mail_html,
        attachments: [{
            filename: attachment_name,
            path: pdfOutputPath
        }],
      };
      envoie_mail.envoie_mail(mailOptions);

      /////////////////////////////////////////////////
      // AJOUT GOOGLE SHEET
      await GS_don.useServiceAccountAuth(GS_creds);
      await GS_don.loadInfo();
      let GS_sheet_don = GS_don.sheetsByTitle['dons'];
      await GS_sheet_don.addRows (
        [
          {
            id: result_sql_select[0].id,
            date: result_sql_select[0].date_auto,
            montant: result_sql_select[0].montant,
            nom: result_sql_select[0].nom,
            prenom: result_sql_select[0].prenom,
            adresse_rue: result_sql_select[0].adresse_rue,
            adresse_complement: result_sql_select[0].adresse_complement,
            adresse_codepostal: result_sql_select[0].adresse_codepostal,
            adresse_ville: result_sql_select[0].adresse_ville,
            adresse_pays: result_sql_select[0].adresse_pays,
            mail: result_sql_select[0].mail,
            telephone_mobile: result_sql_select[0].telephone_mobile,
            commentaire: result_sql_select[0].commentaire,
            statut_paiement: result_sql_select[0].statut_paiement,
            stripe_retour: result_sql_select[0].stripe_retour
          }
        ]
      );
      logger.info("AJOUT GOOGLESHEET FIN", { numsession: req.session.id, label: filename});

    }


  } catch (error) {
      // Echec de connection à la BD
      logger.error("Il y a un problème avec wh_stripe_don : " + error, { numsession: req.session.id });
      return res.status(400).send(`Webhook Error: ${error.message}`);
  }

  res.json({ received: true });

}

/////////////////////////////////////////////////
// TEST WEASYPRINT
/////////////////////////////////////////////////
async function test_weasyprint(req, res, event) {
  try {
    const htmlFilePath = path.join(__dirname, '../pdf/template/don_wp.html');
    const htmlContent = fs.readFileSync(htmlFilePath, 'utf-8');
    const buffer = await weasyprint(htmlContent);
    fs.writeFileSync("./pdf/don/output.pdf", buffer);
    logger.info("PDF CREATED", { numsession: req.session.id, label: filename});
  } catch (error) {
    logger.error("Il y a un problème avec WeasyPrint : " + error, { numsession: req.session.id });
  }
}


/////////////////////////////////////////////////
// EXPORT DE MODULE POUR QU'IL SOIT LU DANS LES AUTRES FICHIERS JS
/////////////////////////////////////////////////
module.exports = {
  post_form_don,
  don_accompte_reussi,
  don_accompte_annule,
  wh_stripe_don,
  test_weasyprint
}

