import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-balham.css';
import 'ag-grid-enterprise';
import React, { useContext, useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { cssMenu } from '../../../constantes/classes-css';
import { ADMINISTRES, DECISIONS, LISTE_TYPE_SUGGESTIONS, NAVIGATION, POSTES } from '../../../constantes/constantes';
import { getDecisionLabel } from '../../../helpers/i18n-helper';
import AGLocaleText from '../../../i18n/aggrid-locale-fr';
import i18n from '../../../i18n/i18n';
import AppConfigStore, { AppConfigContext } from '../../../stores/AppConfigStore';
import { commonAGGridColumnTypes } from '../../Commun/listes/commonAGGridColumnTypes';
import { commonAGGridFrameworkComponents } from '../../Commun/listes/commonAGGridFrameworkComponents';
import { getRefs } from '../../Commun/listes/commonAGGridFunctions';
import CustomAgGridReact from '../../Commun/listes/CustomAgGridReact';
import { onCellValueChanged } from '../../Commun/listes/fonctionsEtCallbacksAgGrid';
import {
    ajouteElementsCommunsAdministreAMenuContextuel, ajouteElementsCommunsAMenuContextuel, ajouteElementsCommunsPosteAMenuContextuel, supprimeSeparateursSurnumerairesMenuContextuel
} from '../../Commun/listes/helpers/listes-ag-grid-helpers';
import './ListeAffectations.scss';

/**
 * Composant permettant d'afficher une liste de postes ou d'administrés prévus ou suggérés pour la vue d'aide à la décision (volet de droite).
 *
 * @component
 * @param {array} props.columnDefs - Les champs pour construire l'Ag Grid
 * @param {object} props.data - Les données pour remplir l'Ag Grid
 * @param {number} props.nbItems - Le nombre total d'éléments dans la liste
 * @param {string} props.context - Le contexte d'affichage de la liste
 *
 * @example
 * return (
 * <ListeAffectations fields={postesFields} data={rowData} nbItems={nbItems} />
 * )
 */

const ListeAffectations = (props) => {
    const gridId =
        'LA/' +
        props.context.groupeType +
        (props.context.listeType ? '/' + props.context.listeType : '') +
        (props.context.listeVariante ? '/' + props.context.listeVariante : '');

    /** @type {AppConfigStore} */
    const appConfig = useContext(AppConfigContext);

    /* States for using Grid Api */
    const [gridApi, setGridApi] = useState(null);
    const [filterChanged, setFilterChanged] = useState(false);
    const [nbFiltered, setNbFiltered] = useState(0);
    const [isFiltered, setIsFiltered] = useState(false);
    const [isFilterReset, setIsFilterReset] = useState(false);

    const history = useHistory();

    const onGridReady = (params) => {
        setGridApi(params.api);
    };

    /**
     * Options de la grille
     */
    //TODO factoriser les options communes à toutes les liste d'Ogure NG dans CustomAgGridReact
    const gridOptions = {
        domLayout: 'autoHeight',
        groupHeaderHeight: 35,
        headerHeight: 40,
        enableBrowserTooltips: true,
        animateRows: true,
        columnTypes: commonAGGridColumnTypes,
        context: props.context,
        defaultColDef: {
            resizable: true,
            sortable: false,
            filter: false,
            editable: false,
            enableRowGroup: true,
            menuTabs: ['generalMenuTab']
        },
        defaultColGroupDef: { autoHeight: true },
        frameworkComponents: commonAGGridFrameworkComponents,
        localeText: AGLocaleText,
        onFilterChanged: () => setFilterChanged(true),
        onGridReady: onGridReady,
        onCellValueChanged: (params) => onCellValueChanged(params, props.context.groupeType === POSTES ? ADMINISTRES : POSTES, appConfig),
        getRowStyle: (params) => {
            return params?.data?.coupleIdealEnTeteDeListe ? { 'border-bottom': '2px solid gray' } : null;
        },
        rowSelection: 'single',
        //suppressRowClickSelection: true,
        popupParent: document.querySelector('body'),
        getContextMenuItems: (params) => getContextMenuItems(params),
        rowClassRules: {
            misEnAvant: function (params) {
                if (props.context.listeType != LISTE_TYPE_SUGGESTIONS) return false;

                switch (props.context.groupeType) {
                    case POSTES:
                        // L'administré est mis en avant car elle est associée au poste sélectionné
                        return params?.data?.decision_posteId == appConfig.selectedPosteDecision?.id;

                    case ADMINISTRES:
                        // Le poste est mise en avant car elle est associée à l'administré sélectionné
                        return !!params?.data?.isPosteAffecteAAdministreSelectionne;
                }
            }
        },
        getRowNodeId: (data) => data.id
    };

    useEffect(() => {
        if (filterChanged) {
            if (!isFilterReset) {
                if (Object.keys(gridApi.getFilterModel()).length === 0) {
                    setIsFiltered(false);
                } else {
                    setIsFiltered(true);
                    setNbFiltered(gridApi.getDisplayedRowCount());
                }
            } else {
                setIsFilterReset(false);
            }
        }
        setFilterChanged(false);
    }, [filterChanged]);

    useEffect(() => {
        if (isFiltered) {
            setIsFiltered(false);
            setIsFilterReset(false);
            setNbFiltered(0);
        }
    }, [props.data]);

    /**
     * Fonction permettant de définir les éléments du menu contextuel (clic droit)
     *
     * @param {CheckboxSelectionCallbackParams} params - Paramètres concernant la colonne
     * @return - Renvoie les items du menu contextuel
     */
    const getContextMenuItems = (params) => {
        if (params.node.group) return;

        const menuItems = [];

        if (props.context.groupeType === POSTES && params.node) {
            // --- Eléments spécifiques aux administrés suggérés pour un poste
            addContextMenuItemsAdministresPourPoste(menuItems, params);
        } else if (props.context.groupeType === ADMINISTRES && params.node) {
            // --- Eléments spécifiques aux postes suggérés pour un administré
            addContextMenuItemsPostesPourAdministre(menuItems, params);
        }

        ajouteElementsCommunsAMenuContextuel(menuItems);

        supprimeSeparateursSurnumerairesMenuContextuel(menuItems);

        return menuItems;
    };

    /**
     * Ajoute aux éléments du menu ceux spécifiques à la liste des administrés suggérés pour un poste.
     *
     * @param {Array.<Object>} menuItems - Liste des éléments de menus à compléter
     * @param {*} params - Paramètre d'appel à getContextMenuItems
     */
    const addContextMenuItemsAdministresPourPoste = (menuItems, params) => {
        const administreDataNode = params.node?.data;
        console.log('addContextMenuItemsAdministresPourPoste', params);
        console.log('administreDataNode', administreDataNode);

        // Action : fiche détaillée administré (toujours proposée)
        ajouteElementsCommunsAdministreAMenuContextuel(menuItems, administreDataNode, appConfig);

        // Actions : Voir cet administré dans une autre vue
        menuItems.push({
            name: 'Localiser cet administré dans la vue...',
            cssClasses: [cssMenu.svgIcon, 'localiser'],
            subMenu: [
                {
                    name: 'Aide à la décision',
                    cssClasses: [cssMenu.subMenu, cssMenu.noIcon],
                    action: () => {
                        appConfig.setSelectedAdministreDecision(administreDataNode);
                        appConfig.setVueDecision(ADMINISTRES);
                    }
                },
                {
                    name: 'Mon périmètre',
                    cssClasses: [cssMenu.subMenu, cssMenu.noIcon],
                    action: () => {
                        appConfig.setSelectedAdministresPerimetre([administreDataNode]);
                        if (appConfig.typeVuePerimetre === POSTES) {
                            appConfig.setTypeVuePerimetre(ADMINISTRES);
                        }
                        history.push(NAVIGATION.PERIMETRE);
                    }
                }
            ]
        });

        // Actions : Prépositionner ou positionner l'administré du contexte avec le poste sélectionné (sauf si déjà fait)
        const posteUniqueSelectionne = appConfig.selectedPosteDecision;
        const idPosteAssocieAAdministre = administreDataNode.decision_posteId;
        const decision = administreDataNode?.decision_decision;

        if (props.context.listeType == LISTE_TYPE_SUGGESTIONS && idPosteAssocieAAdministre != posteUniqueSelectionne.id) {
            const refs = params.context?.donneesReference;
            const decisionsPossibles = administreDataNode.decisions_possibles?.creation ?? [];
            if (Array.isArray(decisionsPossibles) && decisionsPossibles.length) {
                const submenuDecisionItems = decisionsPossibles.reduce((items, d) => {
                    d && items.push({
                        name: i18n.decision?.[d]?.libelleAction ?? getDecisionLabel(d, refs),
                        cssClasses: [cssMenu.subMenu, cssMenu.svgIcon, 'decision', d],
                        action: () =>
                            // TODO pas de MAJ dans ce cas (voir quand même avec les fonctionnels)
                            appConfig.actionsMetierHelper.creeOuMAJDecisionAdministreAvecPoste(
                                administreDataNode.id,
                                posteUniqueSelectionne.id,
                                d,
                                administreDataNode.decision_decision || DECISIONS.AUCUNE,
                            ),
                            disabled: idPosteAssocieAAdministre == posteUniqueSelectionne.id && decision === d
                    });
                    return items;
                }, []);
                if (submenuDecisionItems.length) {
                    menuItems.push({
                        name: `Lier cet administré avec le poste <em>« ${posteUniqueSelectionne.libelleGroupe} »</em>...`,
                        subMenu: submenuDecisionItems,
                        cssClasses: [cssMenu.svgIcon, 'changerDecision']
                    });
                }
            }
        }

        //Action : annuler décision pour l'administré (sauf s'il n'y en a pas encore)
        if (idPosteAssocieAAdministre && decision) {
            menuItems.push({
                name:
                    'Annuler ' +
                    (decision === DECISIONS.PREPOSITIONNE
                        ? 'le prépositionnement'
                        : decision === DECISIONS.POSITIONNE
                        ? 'le positionnement'
                        : decision === DECISIONS.OMI_EN_COURS
                        ? "l'OMI en cours"
                        : decision === DECISIONS.OMI_ACTIVE
                        ? "l'OMI activé"
                        : decision) + // fallback qui ne devrait jamais arriver
                    ' de cet administré',
                action: () =>
                    appConfig.actionsMetierHelper.creeOuMAJDecisionAdministreAvecPoste(
                        administreDataNode.id,
                        idPosteAssocieAAdministre,
                        DECISIONS.AUCUNE,
                        decision,
                    ),
                cssClasses: [cssMenu.svgIcon, 'annulerDecision']
            });
        }
    }

    /**
     * Ajoute aux éléments du menu ceux spécifiques à la liste des postes suggérés pour un administré.
     *
     * @param {Array.<Object>} menuItems - Liste des éléments de menus à compléter
     * @param {*} params - Paramètre d'appel à getContextMenuItems
     */
    const addContextMenuItemsPostesPourAdministre = (menuItems, params) => {
        const posteDataNode = params.node?.data;
        console.log('posteDataNode', posteDataNode);

        ajouteElementsCommunsPosteAMenuContextuel(menuItems, posteDataNode, appConfig);

        // Actions : Voir ce poste dans une autre vue
        menuItems.push({
            name: 'Localiser ce poste dans la vue...',
            cssClasses: [cssMenu.svgIcon, 'localiser'],
            subMenu: [
                {
                    name: 'Aide à la décision',
                    cssClasses: [cssMenu.subMenu, cssMenu.noIcon],
                    action: () => {
                        appConfig.setSelectedPosteDecision(posteDataNode);
                        appConfig.setVueDecision(POSTES);
                    }
                },
                {
                    name: 'Mon périmètre',
                    cssClasses: [cssMenu.subMenu, cssMenu.noIcon],
                    action: () => {
                        appConfig.setSelectedPostesPerimetreEtITD([posteDataNode]);
                        if (appConfig.typeVuePerimetre === ADMINISTRES) {
                            appConfig.setTypeVuePerimetre(POSTES);
                        }
                        history.push(NAVIGATION.PERIMETRE);
                    }
                }
            ]
        });

        // Actions : Prépositionner ou positionner le poste du contexte avec l'administré sélectionné (sauf si déjà fait)
        const administreUniqueSelectionne = appConfig.selectedAdministreDecision;
        const idAdministreAssocieAPoste = posteDataNode.decision_administreId;
        const decision = administreUniqueSelectionne?.decision_decision;

        if (props.context.listeType == LISTE_TYPE_SUGGESTIONS && idAdministreAssocieAPoste != administreUniqueSelectionne.id) {
            const refs = getRefs(params);
            const decisionsPossibles = administreUniqueSelectionne.decisions_possibles?.creation ?? [];
            if (Array.isArray(decisionsPossibles) && decisionsPossibles.length) {
                const submenuDecisionItems = decisionsPossibles.reduce((items, d) => {
                    d && items.push({
                        name: i18n.decision?.[d]?.libelleAction ?? getDecisionLabel(d, refs),
                        cssClasses: [cssMenu.subMenu, cssMenu.svgIcon, 'decision', d],
                        action: () =>
                            // TODO pas de MAJ dans ce cas (voir quand même avec les fonctionnels)
                            appConfig.actionsMetierHelper.creeOuMAJDecisionAdministreAvecPoste(
                                administreUniqueSelectionne.id,
                                posteDataNode.id,
                                d,
                                administreUniqueSelectionne.decision_decision || DECISIONS.AUCUNE,
                            ),
                        disabled: idAdministreAssocieAPoste === administreUniqueSelectionne.id && decision === d
                    });
                    return items;
                }, []);
                if (submenuDecisionItems.length) {
                    menuItems.push({
                        name: `Lier ce poste avec <em>« ${administreUniqueSelectionne.identite_grade_nom_prenom} »</em>...`,
                        subMenu: submenuDecisionItems,
                        cssClasses: [cssMenu.svgIcon, 'changerDecision']
                    });
                }
            }
        }

        //Action : annuler décision entre l'administré sélectionné et le poste (sauf s'il n'y en a pas encore)
        if (idAdministreAssocieAPoste && idAdministreAssocieAPoste == administreUniqueSelectionne.id && decision) {
            menuItems.push({
                name:
                    'Annuler ' +
                    (decision === DECISIONS.PREPOSITIONNE
                        ? 'le prépositionnement'
                        : decision === DECISIONS.POSITIONNE
                        ? 'le positionnement'
                        : decision === DECISIONS.OMI_EN_COURS
                        ? "l'OMI en cours"
                        : decision === DECISIONS.OMI_ACTIVE
                        ? "l'OMI activé"
                        : decision) + // fallback qui ne devrait jamais arriver
                    ' de ce poste avec <em>« ' +
                    administreUniqueSelectionne.identite_grade_nom_prenom +
                    ' »</em>',
                action: () =>
                    appConfig.actionsMetierHelper.creeOuMAJDecisionAdministreAvecPoste(
                        idAdministreAssocieAPoste,
                        posteDataNode.id,
                        DECISIONS.AUCUNE,
                        decision,
                    ),
                cssClasses: [cssMenu.svgIcon, 'annulerDecision']
            });
        }
    }

    return (
        <div className="flex-grow-1 flex-shrink-1 w-100 AgUpperPane">
            <div className="container-fluid AgContainerFluid p-0">
                <div className="ag-theme-balham">
                    <CustomAgGridReact
                        id={gridId}
                        rowData={props.data}
                        gridOptions={gridOptions}
                        columnDefs={props.columnDefs}
                        persistencePrefix={appConfig.utilisateurConnecte?.id}
                    />
                </div>
            </div>
        </div>
    );
};

export default ListeAffectations;
