/**
 * Bibliothèque de fonctions et callbacks communes à l'implémentation des listes AG Grid dans Ogure NG.
 */

import { toast } from 'react-toastify';
import { ADMINISTRES, COMPETENCES_SEPARATEUR, DECISIONS, DEPARTEMENTS_SOUHAITES_SEPARATEUR, MARQUES_SEPARATEUR, POSTES, ZONES_SEPARATEUR } from '../../../constantes/constantes';
import AppConfigStore from '../../../stores/AppConfigStore';
import { getRefs, toDayjsOrNull } from './commonAGGridFunctions';
import { getEmails, sendMail, getSVId } from '../../../helpers/misc-helpers';

/**
 * Callback permettant de mettre à jour les informations modifiées
 *
 * @param {Object} params - paramètres
 * @param {string} groupeType - Type de groupe : ADMINISTRES ou POSTES
 * @param {object} appConfig - Contexte applicatif
 * @void - Met à jour les infos modifiées
 */
export const onCellValueChanged = (params, groupeType, appConfig) => {
    const colId = params.column.getId();

    console.log('onCellValueChanged GLOBAL', colId, params);

    switch (groupeType) {
        case ADMINISTRES:
            onCellValueChangedAdministre(params, appConfig);
            break;

        case POSTES:
            onCellValueChangedPoste(params, appConfig);
            break;
    }
};

/**
 * Callback permettant de mettre à jour les informations modifiées concernant un administré.
 *
 * @param {Object} params - paramètres
 * @param {AppConfigStore} appConfig - Contexte applicatif
 * @void - Met à jour les infos modifiées
 */
function onCellValueChangedAdministre(params, appConfig) {
    const colId = params.column.getId();
    let propName = undefined;
    let newValue = params.newValue;
    let domaineFiliereData = {};

    switch (colId) {
        case 'affectationFuture_dateAffectationFuture':
            propName = 'a_date_affectation';
            newValue = toDayjsOrNull(newValue)?.format('YYYY-MM-DD') ?? null;
            break;

        case 'PAMEnCours_anneePrevisibleMutation':
            propName = 'a_annee_previsible_mutation';
            break;

        case 'PAMEnCours_marques':
            propName = 'a_liste_id_marques';
            newValue = newValue.join(MARQUES_SEPARATEUR);
            break;

        case 'PAMEnCours_notesUtilisateur':
            propName = 'a_notes_gestionnaire';
            newValue = newValue || null;
            break;

        case 'affectationFuture_notes_FE':
            propName = 'a_situationfuture_notes_fe';
            newValue = newValue || null;
            break;

        case 'PAMEnCours_avis':
            propName = 'a_statut_pam';
            break;

        case 'decision_ciat':
            propName = 'a_ciat_pam';
            newValue = newValue;
            break;

        case 'decision_specifique':
            propName = 'a_specifique_pam';
            newValue = ['SHM', 'PPE', 'ITD'].includes(newValue) ? newValue : null;
            break;

        case 'notes_pam':
            propName = 'notes_pam';
            newValue = newValue || null;
            break;

        case 'EIPFutur_domaine':
            // RAZ filière si domaine id incompatible
            const filiereActuelle = appConfig.donneesReference.filieresById.get(params?.data?.EIPFutur_filiere);
            const filieresDuDomaine = appConfig.donneesReference.filieres.filter((f) => f.domaineId == newValue);
            if (!newValue || (filiereActuelle && filiereActuelle.domaineId && filiereActuelle.domaineId != newValue)) {
                // RAZ de la filière : 1ère filière dispo pour le domaine, sinon null
                setTimeout(() => {
                    params.node.setDataValue('EIPFutur_filiere', filieresDuDomaine && filieresDuDomaine.length ? filieresDuDomaine[0].id : null);
                    params.api.tabToNextCell();
                });
            }
            // On ne met pas à jour tout de suite, on le fera en même temps que la filière
            return;

        case 'EIPFutur_filiere':
            // Mise à jour simultanée du domaine et de la filière
            propName = 'a_filiere_futur';
            domaineFiliereData['a_domaine_futur'] = params?.data?.EIPFutur_domaine;
            domaineFiliereData['a_filiere_futur'] = newValue;
            break;

        case 'EIPFutur_NF':
            propName = 'a_nf_futur';
            domaineFiliereData['a_nf_futur'] = newValue;
            break;

        case 'competences_competences':
            propName = 'a_liste_id_competences';
            newValue = newValue.join(COMPETENCES_SEPARATEUR);
            break;

        case 'FORMOB_departements_souhaites':
            propName = 'a_liste_depts_souhaites_pam';
            newValue = newValue.join(DEPARTEMENTS_SOUHAITES_SEPARATEUR);
            break;

        case 'FORMOB_zones_geographiques':
            propName = 'a_liste_zones_geographiques_shm_pam';
            newValue = newValue.join(ZONES_SEPARATEUR);
            break;

        case 'situationFuture_dateStatutFutur':
            propName = 'date_statut_futur';
            newValue = toDayjsOrNull(newValue)?.format('YYYY-MM-DD') ?? null;
            break;

        case 'situationFuture_dateSuiviPrevisionnel':
            propName = 'date_suivi_previsionnel_situation';
            newValue = toDayjsOrNull(newValue)?.format('YYYY-MM-DD') ?? null;
            break;

        case 'situationFuture_statutFutur':
            propName = 'statut_futur';
            break;

        case 'situationFuture_suiviPrevisionnel':
            propName = 'suivi_previsionnel_situation';
            newValue = newValue || null;
            break;
    }

    if (propName) {
        // Cas par défaut
        let updatedData = {};
        updatedData[propName] = newValue ?? null;

        if (propName.startsWith('de_')) {
            // --- MISE A JOUR DE LA DECISION -----------------------------
            if (!params?.data?.id_pam) {
                toast.error("Impossible de mettre à jour la décision (id d'administré absent).");
                return;
            }
            appConfig.managers.decisions.update(params?.data?.id_pam, updatedData)
            .catch((reason) => {
                console.error(reason);
                toast.error(
                    'Une erreur est survenue lors de l\'enregistrement de la valeur du champ "' +
                        params.column.colDef.headerName +
                        '". Veuillez contacter un administrateur.',
                    {
                        autoClose: false
                    }
                );
            });
        } else if (['a_filiere_futur'].includes(propName)) {
            domaineFiliereData['a_nf_futur'] = params?.data?.EIPFutur_NF;
            let msgConfirmation =
            "Confirmez-vous l'envoi de l'administré d\' id :\n    " +
            params?.data?.id +
            '\nvers le sous-vivier :' +
            '\n    - de domaine : ' + domaineFiliereData['a_domaine_futur'] +
            '\n    - de filière : ' + domaineFiliereData['a_filiere_futur'] +
            '\n    - de niveau fonctionnel : ' + domaineFiliereData['a_nf_futur'] +
            '\n?';

            if (!window.confirm(msgConfirmation)) {
                toast.info('Opération annulée.');
                return;
            } else {
                appConfig.managers.administres
                    .update(params?.data?.id, domaineFiliereData)
                    .then((response) => {
                        alert("L'administré « " +
                            params?.data?.id +
                            ' » a bien été envoyé dans le sous-vivier « ' +
                            domaineFiliereData['a_domaine_futur'] + ', ' +
                            domaineFiliereData['a_filiere_futur'] + ', ' +
                            domaineFiliereData['a_nf_futur'] +
                            ' ». Pensez à en informer le gestionnaire qui devra dorénavant le prendre en charge.'
                        );
                    })
                    .catch((reason) => {
                        console.error(reason);
                        toast.error(
                            "Erreur lors de l'envoi de l'administré « " +
                            params?.data?.id +
                            ' »  vers le sous-vivier « ' +
                            domaineFiliereData['a_domaine_futur'] + ', ' +
                            domaineFiliereData['a_filiere_futur'] + ', ' +
                            domaineFiliereData['a_nf_futur'] +
                            ' ». ' +
                            'Ce sous-vivier n\'est pas en base.',
                            { autoClose: false }
                        );
                    });
            }
        } else if (['a_nf_futur'].includes(propName)) {
            domaineFiliereData['a_domaine_futur'] = params?.data?.EIPFutur_domaine
            domaineFiliereData['a_filiere_futur'] = params?.data?.EIPFutur_filiere
            let msgConfirmation =
            "Confirmez-vous l'envoi de l'administré d\'id :\n    " +
            params?.data?.id +
            '\nvers le sous-vivier :' +
            '\n    - de domaine : ' + domaineFiliereData['a_domaine_futur'] +
            '\n    - de filière : ' + domaineFiliereData['a_filiere_futur'] +
            '\n    - de niveau fonctionnel : ' + domaineFiliereData['a_nf_futur'] +
            '\n?';

            if (!window.confirm(msgConfirmation)) {
                toast.info('Opération annulée.');
                return;
            } else {
                appConfig.managers.administres
                    .update(params?.data?.id, domaineFiliereData)
                    .then((response) => {
                        alert("L'administré « " +
                            params?.data?.id +
                            ' » a bien été envoyé dans le sous-vivier « ' +
                            domaineFiliereData['a_domaine_futur'] + ', ' +
                            domaineFiliereData['a_filiere_futur'] + ', ' +
                            domaineFiliereData['a_nf_futur'] +
                            ' ». Pensez à en informer le gestionnaire qui devra dorénavant le prendre en charge.'
                        );
                    })
                    .catch((reason) => {
                        console.error(reason);
                        toast.error(
                            "Erreur lors de l'envoi de l'administré « " +
                            params?.data?.id +
                            ' »  vers le sous-vivier « ' +
                            domaineFiliereData['a_domaine_futur'] + ', ' +
                            domaineFiliereData['a_filiere_futur'] + ', ' +
                            domaineFiliereData['a_nf_futur'] +
                            ' ». ' +
                            'Ce sous-vivier n\'est pas en base.',
                            { autoClose: false }
                        );
                    });
            }
        } else {
            // --- MISE A JOUR DE L'ADMINISTRE ---------------------------
            updatedData['annee_pam'] = appConfig.PAMSelectionne ?? null;
            appConfig.managers.administres
            .update(params?.data?.id, updatedData)
            .then((response) => {
                alert("Mise à jour du champ effectuée avec succès"
                );
            })            
            .catch((reason) => {
                console.error(reason);
                toast.error(
                    'Une erreur est survenue lors de l\'enregistrement de la valeur du champ "' +
                        params.column.colDef.headerName +
                        '". Veuillez contacter un administrateur.',
                    {
                        autoClose: false
                    }
                );
            });
        }
    }
}

/**
 * Callback permettant de mettre à jour les informations modifiées concernant un poste.
 *
 * @param {Object} params - paramètres
 * @param {AppConfigStore} appConfig - Contexte applicatif
 * @void - Met à jour les infos modifiées
 */
function onCellValueChangedPoste(params, appConfig) {
    const colId = params.column.getId();
    let propName = undefined;
    let newValue = params.newValue;

    switch (colId) {
        case 'PAMEnCours_marques':
            propName = 'p_liste_id_marques';
            newValue = newValue.join(MARQUES_SEPARATEUR);
            break;

        case 'PAMEnCours_notesUtilisateur':
            propName = 'p_notes_gestionnaire_pam';
            newValue = newValue || null;
            break;

        case 'PAMEnCours_priorisationPcp':
            propName = 'p_priorisation_pcp_pam';
            newValue = newValue || null;
            break;

        case 'PAMEnCours_propositionsArmement':
            propName = 'propositions_armement_pam';
            newValue = (
                (value, refs) => value ? refs?.find(r => r.libelle === value)?.id ?? value : null
            )(newValue, getRefs(params)?.propositionsArmement);
            break;

        case 'p_itd_cellule':
            propName = 'p_itd_cellule';
            newValue = newValue || null;
            break;

        case 'poste_CIAT':
            propName = 'p_ciat';
            newValue = newValue;
            break;

        case 'poste_specifique':
            propName = 'p_specifique';
            newValue = ['SHM', 'PPE', 'ITD'].includes(newValue) ? newValue : null;
            break;

        case 'poste_competences':
            propName = 'competence';
            newValue = newValue.join(COMPETENCES_SEPARATEUR);
            break;

        case 'decision_decision':
            appConfig.actionsMetierHelper.creeOuMAJDecisionAdministreAvecPoste(
                params?.data?.decision_administreId,
                params?.data?.decision_posteId,
                params?.data?.decision_decision,
                params.oldValue || DECISIONS.AUCUNE,
                () => {
                    //FIXME revenir à l'ancienne valeur SANS redéclencher onCellValueChanged (ou en ne faisant rien dans ce cas-là)
                    //params.api.undoCellEditing();
                    //params.node.setDataValue('decision_decision', params.oldValue);
                }
            );
            return;
        //break;

        case 'notes_pam':
            propName = 'notes_pam';
            newValue = newValue || null;
            break;

        case 'priorite_fe':
            propName = 'p_avis_fe_pam'
            break;

        case 'priorite_drhat':
           propName = 'p_avis_pam'
            break;

        case 'direct_commissionne':
            propName = 'p_direct_commissionne_pam';
            break;
        
        case 'organisme_infoReo':
            propName= 'p_annee'
            break;
    }

    // Colonnes nb d'avis sur le poste
    if (colId.startsWith('p_nb_')) {
        propName = colId;
    }

    if (propName) {
        let updatedData = {};
        updatedData[propName] = newValue ?? null;

        if (propName.startsWith('de_')) {
            // --- MISE A JOUR DE LA DECISION -----------------------------
            if (!params?.data?.decision_administreId) {
                toast.error("Impossible de mettre à jour la décision (id d'administré absent).");
                return;
            }

            appConfig.managers.decisions.update(params?.data?.decision_administreId, updatedData).catch((reason) => {
                console.error(reason);
                toast.error(
                    'Une erreur est survenue lors de l\'enregistrement de la valeur du champ "' +
                        params.column.colDef.headerName +
                        '". Veuillez contacter un administrateur.',
                    {
                        autoClose: false
                    }
                );
            });
        } else {
            // --- MISE A JOUR DU POSTE ---------------------------
            updatedData['annee_pam'] = appConfig.PAMSelectionne ?? null;
            appConfig.managers.postes.update(params?.data?.id, updatedData)
            .then( res  => {
                propName == 'p_itd_cellule' ? res.data.info ? toast.info(res.data.info) : toast.success('Mise à jour réussie.') : '';
            })
            .then((response) => {
                alert("Mise à jour du champ effectuée avec succès"
                );
            })            
            .catch((reason) => {
                console.error(reason);
                toast.error(
                    'Une erreur est survenue lors de l\'enregistrement de la valeur du champ "' +
                        params.column.colDef.headerName +
                        '". Veuillez contacter un administrateur.',
                    {
                        autoClose: false
                    }
                );
            });
        }
    }
}

/**
 * Calcule la taille en largeur prise par toutes les colonnes
 */
const getDisplayedColumnsTotalWidth = (columns) => {
    let size = 0;
    columns.forEach((c) => (size = size + c.actualWidth));
    return size;
};

/**
 * Change automatiquement la taille des colonnes une fois que les données sont chargées.
 */
export const autoSizeColumns = (params) => {
    return; // TODO à retirer une fois que la fonction sera améliorée

    const allCols = params.columnApi.getAllDisplayedColumns();
    const allColumnsWidth = getDisplayedColumnsTotalWidth(allCols);

    // Agrandit la taille de la dernière colonne pour remplir totalement le tableau
    if (params.clientWidth > allColumnsWidth) {
        const lastCol = allCols[allCols.length - 1];
        params.columnApi.setColumnWidth(lastCol, params.clientWidth - allColumnsWidth + lastCol.actualWidth);
        //FIXME TODO la largeur à retirer dépend de la présence ou non des outils à droite
        //FIXME TODO la propriété params.clientWidth n'est pas toujours présente
    }
};

/**
 * Callback indiquant si une colonne porte la case à cocher de sélection
 * (détermination de la 1ère colonne affichée, même en cas de modification de l'ordre par l'utilisateur)
 *
 * @param {Object} params - paramètres
 * @returns indique si la colonne porte la case à cocher de sélection
 */
export const hasCheckboxSelection = (params) => {
    if (!params.data) return false;

    let curColId = params.column.getColId();
    let index = params.columnApi.getAllDisplayedColumns().findIndex((col) => col.getColId() === curColId);

    return index == 0;
};
