const express = require("express");
const router = express.Router();
const fs = require("fs");
const PizZip = require("pizzip");
const Docxtemplater = require("docxtemplater");
const logger = require("../utils/logger");
const path = require("path");
const moment = require("moment");
const parcoursService = require("../services/parcoursService");
const contratService = require("../services/contratService");
const globalService = require("../services/globalService");
const userService = require("../services/userService");
const constantesFAC = require("../constantes/json-modulateur-fac");


require("moment/locale/fr");
moment.locale("fr");




router.post("/fac/projet/:numParcours", async (req, res) => {
    const content = fs.readFileSync(
        path.resolve("src/templates/template-projet-fac.docx"),
        "binary"
    );

    const zip = new PizZip(content);
    const doc = new Docxtemplater(zip, {paragraphLoop: true, linebreaks: true});
    const numParcours = req.params.numParcours.toUpperCase();

    const parcours = await parcoursService.getParcoursByNumParcours(numParcours);
    const contrat = await contratService.getContratById(parcours.contrat);
    const client = contrat?.["@expand"]?.client || {};
    const intermediaire = contrat?.["@expand"]?.intermediaire || {};
    const fac = contrat?.["@expand"]?.enCours || null;
    const projet = fac?.["@expand"]?.projet || null;


    const moyenTransportList = ["terrestre", "maritime", "aerien", "postal", "fluvial"]
    const selectedTransportList = []

    try {
        moyenTransportList.forEach((transport) => {
            if (projet[transport] !== "") {
                selectedTransportList.push(transport)
            }
        })
    } catch (error) {}

    
    var transportListVirguleEt
    
    if (selectedTransportList.length > 1) {
        transportListVirguleEt = selectedTransportList
        .slice(0, selectedTransportList.length - 1)
        .join(', ')
        + ' et ' + selectedTransportList[selectedTransportList.length - 1]
    } else {
        transportListVirguleEt = selectedTransportList.toString()
    }

    
    //au féminin
    const transportListOuEt = selectedTransportList.join(" et/ou ")
        .replace('fluvial', "fluviale")
        .replace('postal', 'postale')
        .replace('aerien', 'aerienne')


    const listAssAdd = [];

    try {
        projet.assureAdditionnel.forEach((objet) => {
            listAssAdd.push(objet.nom + " - Adresse : " + objet.adresse + " - Siret : " + objet.siret);
        });
    } catch (error) {}

    const risqueTransport = {
        "achat": "des contrats d'achat",
        "vente": "des contrats de vente",
        "sav": "des opérations de SAV",
        "demo": "des démonstrations",
        "transfert": "des transferts inter-usines"
    }

    Object.keys(risqueTransport).forEach((risque) => {
        if (!projet.risqueTransport.includes(risque)) {
            delete risqueTransport[risque]
        }
    })

    const listRisqueTransport = Object.keys(risqueTransport).map((key) => risqueTransport[key])

    const mondeEntier = (fac.zones.includes('zone1') &&
        fac.zones.includes('zone2') &&
        fac.zones.includes('zone3') &&
        fac.zones.includes('zone4') &&
        fac.zones.includes('zone5') &&
        fac.zones.includes('zone6'))

    const hasZone456 = (fac.zones.includes('zone4') &&
        fac.zones.includes('zone5') &&
        fac.zones.includes('zone6'))

    const hasGarOptAuto = projet.garOpt.includes('auto')
    const hasGarOptEmballage = projet.garOpt.includes('emballage')
    const hasGarOptEtiquette = projet.garOpt.includes('etiquette')
    const hasGarOptTemperature = projet.garOpt.includes('temperature')
    const hasGarOptMarque = projet.garOpt.includes('marque')
    const hasTPPC = fac.tppc
    const hasMarchandiseExposition = fac.nbVehicExpo > 0

    const condition4 = (hasGarOptAuto || hasGarOptEmballage || hasGarOptEtiquette || hasGarOptMarque || hasTPPC || hasMarchandiseExposition)
    const hasGarOpt = projet.garOpt.length > 0
    const condition2 = hasGarOpt || hasTPPC || hasMarchandiseExposition

    const anneeProchaine = moment().add(1, 'years').format('YYYY')
    const dateFin = (projet.dateFin == "00/00" || projet.dateFin == "00/00/0000") ? "A PRECISER" : projet.dateFin
    const dateEffet = (projet.dateEffet == "00/00" || projet.dateEffet == "00/00/0000") ? "A PRECISER" : projet.dateEffet
    const dateEcheance = (projet.dateEcheance == "00/00" || projet.dateEcheance == "00/00/0000") ? "A PRECISER" : projet.dateEcheance + '/' + anneeProchaine

    const renderObject = {
        nomClient: client.nom,
        adrClient: client.adresse,
        postalClient: client.codePostal,
        villeClient: client.ville,
        numClient: client.numClient,

        nomInter: intermediaire.nom,
        adrInter: intermediaire.adresse,
        postalInter: intermediaire.codePostal,
        villeInter: intermediaire.ville,
        oriasInter: intermediaire.numOrias,
        hasOrias: intermediaire.numOrias == "" ? false : true,
        numInter: intermediaire.numTelephone,
        mailInter: intermediaire.mail,
        hasMail: intermediaire.mail ? true : false,
        numProjet: contrat.numSaisine ? contrat.numSaisine : contrat.numContrat,

        hasCP: (contrat.type == "AN" || contrat.type == "TEMPORAIRE"),
        hasRemplacement: (contrat.type == "REMPLACEMENT"),
        hasRGAuto: (fac.rg == "auto"),
        hasRGDemande: (fac.rg == 'demande'),
        hasRG: (fac.rg == 'demande' || fac.rg == 'auto'),
        hasEtendue: (fac.typeRG == "etendue"),
        hasWaterborne: (fac.typeRG == "waterborne"),
        hasProgrammeInternational: projet.programmeInternational,

        hasAssuresAdditionnels: listAssAdd.length > 0,
        listAssAdd: listAssAdd,
        hasTemporaire: contrat.type == "TEMPORAIRE",
        actAssure: fac.actAssure,
        typeMar: fac.typeMar,

        listMoyenTransportEtOu: transportListOuEt,
        listMoyenTransportVirguleEt: transportListVirguleEt,

        listRisqueTransport: listRisqueTransport,

        depart: projet.lieuDepart,
        arrivee: projet.lieuArrivee,
        dateJour: moment().format("DD MMMM YYYY"),
        dateEffet: dateEffet,
        dateFin: dateFin,
        dateEcheance: dateEcheance,

        hasMarchandiseExposition: hasMarchandiseExposition,
        hasMondeEntier: mondeEntier,
        hasZone1: fac.zones.includes('zone1'),
        hasZone2: fac.zones.includes('zone2'),
        hasZone3: fac.zones.includes('zone3'),
        hasZone4: fac.zones.includes('zone4'),
        hasZone5: fac.zones.includes('zone5'),
        hasZone6: fac.zones.includes('zone6'),
        hasZone456: hasZone456,
        hasTPPC: hasTPPC,
        hasTPPCTousRisques: projet.typeTPPC.includes('tousRisques'),
        hasTPPCFlotteND: projet.typeTPPC.includes('flotteND'),

        capitalMax: projet.capitalMax,
        franchiseTransport: projet.franchiseTransport,
        condition4: condition4,
        hasGarOpt: hasGarOpt,
        condition2: condition2,
        hasGarOptAuto: hasGarOptAuto,
        hasGarOptEmballage: hasGarOptEmballage,
        hasGarOptEtiquette: hasGarOptEtiquette,
        hasGarOptMarque: hasGarOptMarque,
        hasGarOptTemperature: hasGarOptTemperature,
        capitalTPPC: fac.capitalTPPC,
        franchiseExpo: fac.franchiseExpo,
        hasCG: projet.valeurAssuree.includes('cg'),
        hasDerogation: projet.valeurAssuree.includes('derogation'),
        hasVaBasePrix: projet.valeurAssureeBase.includes('prix'),
        hasVaBaseAchat: projet.valeurAssureeBase.includes('achat'),
        hasVaBaseVente: projet.valeurAssureeBase.includes('vente'),

        hasAerienTousRisques: fac.aerien.includes('tousRisques'),
        hasAerienEventMaj: fac.aerien.includes('eventMaj'),
        hasMaritimeTousRisques: fac.maritime.includes('tousRisques'),
        hasMaritimeEventMaj: fac.maritime.includes('eventMaj'),
        hasTerrestreTousRisques: fac.terrestre.includes('tousRisques'),
        hasTerrestreEventMaj: fac.terrestre.includes('eventMaj'),
        hasPostalTousRisques: fac.postal.includes('tousRisques'),
        hasPostalEventMaj: fac.postal.includes('eventMaj'),
        hasFluvialTousRisques: fac.fluvial.includes('tousRisques'),
        hasFluvialEventMaj: fac.fluvial.includes('eventMaj'),
        hasFranchiseTransport: projet.franchiseTransport !== "",

        cotRO: globalService.customFormatNumber(fac.cotRO),
        cotRG: globalService.customFormatNumber(fac.cotRG),
        cotProvRO: globalService.customFormatNumber(fac.cotProvRO),
        cotProvRG: globalService.customFormatNumber(fac.cotProvRG),
        cotComptant: globalService.customFormatNumber(projet.cotComptant),
        tauxCotRO: globalService.customFormatNumber(fac.tauxCotRO, true),
        tauxCotRG: globalService.customFormatNumber(fac.tauxCotRG, true),
        cotAnnuelle: globalService.customFormatNumber(fac.primeHT),
        cotIrred: globalService.customFormatNumber(fac.primeMini),
        capitalTPPC: globalService.customFormatNumber(fac.capitalTPPC),
        capitalExpo: globalService.customFormatNumber(fac.capitalExpo),
        franchiseTPPC: globalService.customFormatNumber(fac.franchiseTPPC),
        chiffreAffaires: globalService.customFormatNumber(fac.ca),

        hasMensuel: (projet.tempo == "mensuel"),
        hasChiffreAffaires: (projet.typeContrat == "chiffreAffaires"),
        hasAvisAliments: (projet.typeContrat == "avisAliments"),
        hasPartResultat: projet.participationResultat,
        hasAgentMutualiste: (intermediaire.type == "AGENT MUTUALISTE"),
        hasAgent: (intermediaire.type == "AGENT MUTUALISTE" || intermediaire.type == "AGENT NON MUTUALISTE"),
        hasCourtier: (intermediaire.type == "COURTIER"),
        tempo: projet.tempo,
    }

    try {
        doc.render(renderObject)
    } catch (error) {
        const e = {
            message: error.message,
            name: error.name,
            stack: error.stack,
            properties: error.properties,
        };
        logger.log('error', JSON.stringify({error: e}));

        // Envoyez une réponse d'erreur si le rendu échoue
        return res.status(500).send("Erreur lors de la génération du document");
    }

    const buf = doc.getZip().generate({type: "nodebuffer"});
    const formattedDate = moment().format('DD-MM-YYYY-HH-mm-ss')

    // Génération du nom de fichier
    const sanitizedClientNom = client.nom
        .replace(/[^\w\s.-]/gi, "")
        .replace(/\s+/g, "-");

    const filename = `Projet-${contrat.produit}-${parcours.numParcours}-${sanitizedClientNom}-${formattedDate}`;

    // Définit le type de contenu et un nom de fichier par défaut pour le téléchargement
    res.setHeader(
        "Content-Type",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    );

    res.setHeader(
        "Content-Disposition",
        "attachment; filename=" + filename + ".docx"
    );

    // Envoie le buffer au client, déclenchant le téléchargement
    res.send(buf);
});

//generate declinaison tarifaire FAC
router.post("/fac/tarif/:numParcours", async (req, res) => {
    // TODO Attention conditionner en fonction du type de CP

    const content = fs.readFileSync(
        path.resolve("src/templates/template-declinaison-tarifaire-fac.docx"),
        "binary"
    );

    const zip = new PizZip(content);
    const doc = new Docxtemplater(zip, {paragraphLoop: true, linebreaks: true});

    const numParcours = req.params.numParcours.toUpperCase();
    const parcours = await parcoursService.getParcoursByNumParcours(numParcours);
    const contrat = await contratService.getContratById(parcours.contrat);
    const client = contrat?.["@expand"]?.client || {};
    const fac = contrat?.["@expand"]?.enCours || {};
    const tarif = fac?.["@expand"]?.tarif || {};
    const user = await userService.getUserById(parcours.dernierUtilisateur);

    function getSelectedFranchise(franchiseId) {
        switch (franchiseId) {
            case "sansFranchise":
                return tarif.sansFranchise
            case "franchise350":
                return tarif.franchise350
            case "franchise750":
                return tarif.franchise750
        }
    }

    function getSelectedFranchiseTitre(franchiseId) {
        switch (franchiseId) {
            case "sansFranchise":
                return "Sans Franchise"
            case "franchise350":
                return "Franchise 350 €"
            case "franchise750":
                return "Franchise 750 €"

        }
    }

    function initialeMaj(str) {
        return typeof str == "string" ? str.charAt(0).toUpperCase() + str.slice(1) : ""
    }


    const selectedFranchiseTitre = getSelectedFranchiseTitre(tarif.selectedFranchise)
    const selectedFranchise = getSelectedFranchise(tarif.selectedFranchise)

    const transports = []
    if (fac.terrestre !== "") {
        transports.push("Terrestre")
    }
    if (fac.maritime !== "") {
        transports.push("Maritime")
    }
    if (fac.aerien !== "") {
        transports.push("Aerien")
    }
    if (fac.postal !== "") {
        transports.push("Postal")
    }
    if (fac.fluvial !== "") {
        transports.push("Fluvial")
    }
    if (fac.multimodal !== "") {
        transports.push('Multimodal')
    }

    const listTransports = transports.join(', ')

    const hasMondeEntier = (
        fac.zones.includes("zone1") &&
        fac.zones.includes("zone2") &&
        fac.zones.includes("zone3") &&
        fac.zones.includes("zone4") &&
        fac.zones.includes("zone5") &&
        fac.zones.includes("zone6")
    )

    const typeRO = tarif.typeRO == "tousRisques" ? "Tous Risques" : "Evenements Majeurs"
    var typePolice
    switch (tarif.typePolice) {
        case "ca":
            typePolice = "Police au Chiffre d'Affaires";
            break;

        case "national":
            typePolice = "Police au Voyage National";
            break;

        case "international":
            typePolice = "Police au Voyage International";
            break;
    }

    try {
        doc.render({

            matricule: user.matricule,
            hasContrat: contrat.numContrat || false,
            numContrat: contrat.numContrat,
            hasSaisine: contrat.numSaisine || false,
            numSaisine: contrat.numSaisine,
            nomClient: client.nom,

            actAssuree: fac.actAssuree,
            montantSin: tarif.sinistres,
            franchiseSelected: selectedFranchiseTitre,
            typeMar: fac.typeMar,
            ca: fac.ca,

            montantGarantir: tarif.montantGarantir,
            conditionnement: constantesFAC.objModCond?.[tarif.conditionnement]?.nom ?? "",
            typeMar: fac.typeMar,

            transports: listTransports,
            hasMondeEntier: hasMondeEntier,
            hasZone1: fac.zones.includes("zone1"),
            hasZone2: fac.zones.includes("zone2"),
            hasZone3: fac.zones.includes("zone3"),
            hasZone4: fac.zones.includes("zone4"),
            hasZone5: fac.zones.includes("zone5"),
            hasZone6: fac.zones.includes("zone6"),

            hasZone1Achats: tarif.fluxAchats?.zone == "zone1",
            hasZone2Achats: tarif.fluxAchats?.zone == "zone2",
            hasZone3Achats: tarif.fluxAchats?.zone == "zone3",
            hasZone4Achats: tarif.fluxAchats?.zone == "zone4",
            hasZone5Achats: tarif.fluxAchats?.zone == "zone5",
            hasZone6Achats: tarif.fluxAchats?.zone == "zone6",
            conditionnementAchats: constantesFAC.objModCond[tarif.fluxAchats?.conditionnement]?.nom ?? "",

            hasZone1Ventes: tarif.fluxVentes?.zone == "zone1",
            hasZone2Ventes: tarif.fluxVentes?.zone == "zone2",
            hasZone3Ventes: tarif.fluxVentes?.zone == "zone3",
            hasZone4Ventes: tarif.fluxVentes?.zone == "zone4",
            hasZone5Ventes: tarif.fluxVentes?.zone == "zone5",
            hasZone6Ventes: tarif.fluxVentes?.zone == "zone6",
            conditionnementVentes: constantesFAC.objModCond[tarif.fluxVentes?.conditionnement]?.nom ?? "",

            hasFluxGlobal: tarif.typeFlux == "global",
            hasFluxDetailles: tarif.typeFlux == "detailles",
            hasFluxVentes: (tarif.fluxVentes),
            hasFluxAchats: (tarif.fluxAchats),
            hasFluxIntersites: tarif.fluxIntersites,
            fluxAchats: tarif.fluxAchats,
            fluxVentes: tarif.fluxVentes,
            transportVentes: initialeMaj(tarif.fluxVentes?.transport),
            transportAchats: initialeMaj(tarif.fluxAchats?.transport),


            typeRO: typeRO,
            typePolice: typePolice,
            hasTPPC: fac.tppc,
            hasMarExpo: (fac.nbVehicExpo > 0),
            hasRG: fac.rg == "auto",
            hasRGAchats: (tarif.fluxAchats?.typeRG),
            hasRGVentes: (tarif.fluxVentes?.typeRG),


            tarif350: tarif.franchise350.proposition,
            // pourcentAct350: parseFloat(tarif.franchise350.pourcentAct) * 100,
            // pourcentCA350: parseFloat(tarif.franchise350.pourcentCA) * 100,
            // pourcentMar350: parseFloat(tarif.franchise350.pourcentMar) * 100,
            // pourcentFranchise350: parseFloat(tarif.franchise350.pourcentFranchise) * 100,
            tauxRO350: tarif.franchise350.tauxRO,
            tauxRG350: tarif.franchise350.tauxRG,
            franchiseTPPC350: tarif.franchise350.franchiseTPPC ?? "",
            franchiseExpo350: tarif.franchise350.franchiseExpo ?? "",

            tarif750: tarif.franchise750.proposition,
            // pourcentAct750: parseFloat(tarif.franchise750.pourcentAct) * 100,
            // pourcentCA750: parseFloat(tarif.franchise750.pourcentCA) * 100,
            // pourcentMar750: parseFloat(tarif.franchise750.pourcentMar) * 100,
            // pourcentFranchise750: parseFloat(tarif.franchise750.pourcentFranchise) * 100,
            tauxRO750: tarif.franchise750.tauxRO,
            tauxRG750: tarif.franchise750.tauxRG,
            franchiseTPPC750: tarif.franchise750.franchiseTPPC ?? "",
            franchiseExpo750: tarif.franchise750.franchiseExpo ?? "",

            tarifSansFranchise: tarif.sansFranchise.proposition,
            // pourcentActSansFranchise: parseFloat(tarif.sansFranchise.pourcentAct) * 100,
            // pourcentCASansFranchise: parseFloat(tarif.sansFranchise.pourcentCA) * 100,
            // pourcentMarSansFranchise: parseFloat(tarif.sansFranchise.pourcentMar) * 100,
            // pourcentFranchiseSansFranchise: parseFloat(tarif.sansFranchise.pourcentFranchise) * 100,
            franchiseTPPCSansFranchise: tarif.sansFranchise.franchiseTPPC ?? "",
            franchiseExpoSansFranchise: tarif.sansFranchise.franchiseExpo ?? "",
            tauxROSansFranchise: tarif.sansFranchise.tauxRO,
            tauxRGSansFranchise: tarif.sansFranchise.tauxRG,

            tarifSelected: selectedFranchise.proposition,
            tarifCommercial: fac.primeHT,
            franchiseTPPCSelected: selectedFranchise.franchiseTPPC ?? "",
            franchiseExpoSelected: selectedFranchise.franchiseExpo ?? "",
            tauxROSelected: fac.tauxCotRO,
            tauxRGSelected: fac.tauxCotRG 
        });
    } catch (error) {
        const e = {
            message: error.message,
            name: error.name,
            stack: error.stack,
            properties: error.properties,
        };
        logger.log("error", JSON.stringify({error: e}));

        // Envoyez une réponse d'erreur si le rendu échoue
        return res.status(500).send("Erreur lors de la génération du document");
    }

    const buf = doc.getZip().generate({type: "nodebuffer"});
    const currentDate = new Date();

    // Formatage de la date au format "JJ-MM-AAAA-HH-MM-SS"
    const day = String(currentDate.getDate()).padStart(2, "0");
    const month = String(currentDate.getMonth() + 1).padStart(2, "0");
    const year = currentDate.getFullYear();
    const hours = String(currentDate.getHours()).padStart(2, "0");
    const minutes = String(currentDate.getMinutes()).padStart(2, "0");
    const seconds = String(currentDate.getSeconds()).padStart(2, "0");
    const formattedDate = `${day}-${month}-${year}-${hours}-${minutes}-${seconds}`;

    // Génération du nom de fichier
    const sanitizedClientNom = client.nom
        .replace(/[^\w\s.-]/gi, "")
        .replace(/\s+/g, "-");
    const filename = `Tarif-${contrat.produit}-${parcours.numParcours}-${sanitizedClientNom}-${formattedDate}`;

    // Définit le type de contenu et un nom de fichier par défaut pour le téléchargement
    res.setHeader(
        "Content-Type",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    );

    res.setHeader(
        "Content-Disposition",
        "attachment; filename=" + filename + ".docx"
    );

    // Envoie le buffer au client, déclenchant le téléchargement
    res.send(buf);
});

module.exports = router;
