import dayjs from 'dayjs';
import extend from 'just-extend';
import { AGGRID_NAVIGATION_KEYS, DECISIONS } from '../../../constantes/constantes';
import * as ColorManipulation from '../../../helpers/color-manipulation';
import { getDecisionLabel } from '../../../helpers/i18n-helper';
import { createConstantsFrom } from '../../../helpers/objects';
import AGLocaleText from '../../../i18n/aggrid-locale-fr';
import i18n from '../../../i18n/i18n';
import { getCompetence, getCompetences, getDepartement, getDepartements, getDomaine, getFiliere, getZones } from '../../Commun/listes/helpers/business-data-helpers';
import { creerFormateurParams, customizeEditorAndStopEditing, getActionsMetierHelper, getMutator, getRefs, getTrue } from './commonAGGridFunctions';

export const FILTER_PARAMS_EXCEL_MODE = 'windows';

/**
 * classes CSS communes
 * @type {{center: string, editable: string, right: string, decision: string}}
 */
export const commonCssClasses = createConstantsFrom(['center', 'editable', 'right', 'decision']);

/**
 * Retourne la valeur d'une cellule ou d'un groupe de cellule.
 *
 * @param {object} params - Les paramètres AG Grid
 * @param {string} colId  - L'id de la colonne (ou null)
 * @param {string} colTypeName - Le nom du type de colonne (ou null)
 * @returns valeur ou ''
 */
export const getValueForCellOrGroupCell = (params, colId, colTypeName) => {
    if (!params.value) return undefined;

    let value;
    if (!params.node?.group) {
        value = params.value;
    } else if ((colId && params.colDef?.colId == colId) || (colTypeName && params.colDef?.type?.includes(colTypeName))) {
        console.log('params', params);
        value = params.node?.groupData['ag-Grid-AutoColumn'];
    } else {
        return '';
    }
    return value;
};

/**
 * Définition des types de colonnes communs à différentes listes AG Grid d'Ogure NG.
 */
export const commonAGGridColumnTypes = (() => {
    const basicTypes = {
        // Colonne sans paramètre (utilisé en cas de surcharge d'un type)
        BLANK: {},

        // Colonne éditable
        editableColumn: {
            editable: (params) => params.colDef?.editableIf?.(params) ?? true,
            cellClassRules: {
                [commonCssClasses.editable]: (params) => params.colDef?.editable?.(params) ?? false
            }
        },

        // Colonne éditable s'il existe une décision
        editableIfDecisionColumn: {
            editable: (params) => params.data?.decision_decision,
            cellClassRules: { [commonCssClasses.editable]: (params) => params.data?.decision_decision },
        },

        // Colonne texte
        textColumn: {
            tooltipValueGetter: (params) => params.value,
            filter: 'agTextColumnFilter'
        },

        // Colonne contenant un ensemble déterminé de valeurs
        setColumn: {
            tooltipValueGetter: (params) => params.value,
            filter: 'agSetColumnFilter',
            filterParams: {
                excelMode: FILTER_PARAMS_EXCEL_MODE
            }
        },

        // Colonne date
        dateColumn: (() => {
            const valueFormatter = (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'dateColumn');
                if (!value) return '';

                const dateStr = (value instanceof dayjs ? value : dayjs(value)).format('DD/MM/YYYY');
                if (dateStr.includes('Invalid')) return i18n.global.donnees.erreur;
                return dateStr;
            };
            return {
                filter: 'agDateColumnFilter',
                valueFormatter,
                tooltipValueGetter: valueFormatter,
                cellEditor: 'dateCellEditor'
            }
        })(),

        // Colonne nombre
        numberColumn: {
            tooltipValueGetter: (params) => params.value,
            filter: 'agNumberColumnFilter',
            cellEditor: 'numberCellEditor'
        },

        // Colonne entier positif
        positiveIntegerColumn: {
            tooltipValueGetter: (params) => params.value,
            filter: 'agNumberColumnFilter',
            cellClassRules: { [commonCssClasses.right]: getTrue },
            cellEditor: 'numberCellEditor',
            cellEditorParams: (params) => {
                return {
                    min: 0,
                    step: 1
                };
            }
        }
    };
    return Object.assign(basicTypes, {
        // Colonne domaine d'EIP
        domaineColumn: {
            width: 80,
            valueFormatter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'domaineColumn');
                if (value === undefined) {
                    return '';
                } else if (!value) {
                    return i18n.global.donnees.vide;
                }

                const domaine = getDomaine(getRefs(params), value);
                return domaine ? domaine.code : '[' + value + ']';
            },
            tooltipValueGetter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'domaineColumn');
                if (!value) {
                    return i18n.global.donnees.vide;
                }

                const domaine = getDomaine(getRefs(params), value);
                return domaine ? domaine.code + ' (' + domaine.libelle + ')' : '[' + value + ']';
            },
            filter: 'agSetColumnFilter',
            filterParams: {
                excelMode: FILTER_PARAMS_EXCEL_MODE,
                valueFormatter: (params) => {
                    if (!params.value) {
                        return AGLocaleText.blanks;
                    }
                    const domaine = getDomaine(getRefs(params), params.value);
                    return domaine ? domaine.code + ' (' + domaine.libelle + ')' : '[' + params.value + ']';
                }
            },
            cellEditor: 'agRichSelectCellEditor',
            cellEditorParams: (params) => {
                return {
                    values: getRefs(params)?.domaines?.map((d) => d.id) ?? [],
                    formatValue: (value) => {
                        const domaine = getDomaine(getRefs(params), value);
                        return domaine ? domaine.code + ' (' + domaine.libelle + ')' : i18n.global.donnees.vide;
                    }
                };
            }
        },

        // Colonne filière d'EIP
        filiereColumn: {
            width: 80,
            valueFormatter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'filiereColumn');
                if (value === undefined) {
                    return '';
                } else if (!value) {
                    return i18n.global.donnees.vide;
                }

                const filiere = getFiliere(getRefs(params), value);
                return filiere ? filiere.code : '[' + value + ']';
            },
            tooltipValueGetter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'filiereColumn');
                if (!value) {
                    return '';
                }

                const filiere = getFiliere(getRefs(params), value);
                return filiere ? filiere.code + ' (' + filiere.libelle + ')' : '[' + value + ']';
            },
            filter: 'agSetColumnFilter',
            filterParams: {
                excelMode: FILTER_PARAMS_EXCEL_MODE,
                valueFormatter: (params) => {
                    if (!params.value) {
                        return AGLocaleText.blanks;
                    }
                    const filiere = getFiliere(getRefs(params), params.value);
                    return filiere ? filiere.code + ' (' + filiere.libelle + ')' : '[' + params.value + ']';
                }
            },
            cellEditor: 'agRichSelectCellEditor',
            cellEditorParams: (params) => {
                const selectedDomaine = params?.data?.EIPFutur_domaine;
                return {
                    values: getRefs(params)?.filieres?.filter((f) => f.domaineId == selectedDomaine).map((f) => f.id) ?? [],
                    formatValue: (value) => {
                        const filiere = getFiliere(getRefs(params), value);
                        return filiere ? filiere.code + ' (' + filiere.libelle + ')' : i18n.global.donnees.vide;
                    }
                };
            }
        },

        // Colonne NF d'EIP
        NFColumn: {
            width: 70,
            valueFormatter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'NFColumn');
                if (value === undefined) {
                    return '';
                } else if (!value) {
                    return i18n.global.donnees.vide;
                }

                const nf = value ? getRefs(params)?.NFById?.get(value.toUpperCase()) : null;
                return nf ? nf.code : '[' + value + ']';
            },
            tooltipValueGetter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'NFColumn');
                if (!value) return '';

                const nf = value ? getRefs(params)?.NFById?.get(value.toUpperCase()) : null;
                return nf ? nf.code : '[' + value + ']';
            },
            filter: 'agSetColumnFilter',
            filterParams: {
                excelMode: FILTER_PARAMS_EXCEL_MODE
            },
            cellEditor: 'agRichSelectCellEditor',
            cellEditorParams: (params) => {
                return {
                    values: getRefs(params)?.NF?.map((nf) => nf.code) ?? [],
                    formatValue: (value) => {
                        const nf = value ? getRefs(params)?.NFById?.get(value.toUpperCase()) : null;
                        return nf ? nf.code : i18n.global.donnees.vide;
                    }
                };
            }
        },

        // Colonne compétences
        competencesColumn: {
            width: 200,
            tooltipValueGetter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'competencesColumn');
                if (!value) {
                    return '';
                }

                const competences = getCompetences(getRefs(params), value);
                const libellesCompetences = competences.length
                    ? competences.filter((c) => typeof c !== 'undefined' && c !== null).map((c) => c.id)
                    : [];
                return libellesCompetences.length ? libellesCompetences.join(', ') : '';
            },
            valueFormatter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'competencesColumn');
                if (!value) {
                    return '';
                }

                const competences = getCompetences(getRefs(params), value);
                const libellesCompetences = competences.length
                    ? competences.filter((c) => typeof c !== 'undefined' && c !== null).map((c) => c.id)
                    : [];
                return libellesCompetences.length ? libellesCompetences.join(', ') : '';
            },
            filter: 'agSetColumnFilter',
            filterParams: {
                excelMode: FILTER_PARAMS_EXCEL_MODE,
                valueFormatter: (params) => {
                    if (!params.value) {
                        return AGLocaleText.blanks;
                    }
                    const competence = getCompetence(getRefs(params), params.value);
                    return competence ? competence.libelle : '[' + params.value + ']';
                }
            },
            cellEditor: 'competencesCellEditor',
            suppressKeyboardEvent: (params) => {
                return params.editing && AGGRID_NAVIGATION_KEYS.includes(params.event.keyCode);
            }
        },

        // Liste de départements
        departementsColumn: {
            width: 160,
            tooltipValueGetter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'departementsColumn');
                if (!value) {
                    return '';
                }

                const departements = getDepartements(getRefs(params), value);
                const libellesDepartements = departements.length
                    ? departements.filter((d) => d !== null).map((d) => d.code + (d.libelle != d.code ? ' (' + d.libelle + ')' : ''))
                    : null;
                return libellesDepartements ? libellesDepartements.join(', ') : '';
            },
            valueFormatter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'departementsColumn');
                if (!value) {
                    return '';
                }

                const departements = getDepartements(getRefs(params), value);
                const libellesDepartements = departements.length ? departements.filter((d) => d !== null).map((d) => d.code) : null;
                return libellesDepartements ? libellesDepartements.join(', ') : '';
            },
            filter: 'agSetColumnFilter',
            filterParams: {
                excelMode: FILTER_PARAMS_EXCEL_MODE,
                valueFormatter: (params) => {
                    if (!params.value) {
                        return AGLocaleText.blanks;
                    }
                    const departement = getDepartement(getRefs(params), params.value);
                    return departement
                        ? departement.code + (departement.libelle != departement.code ? ' (' + departement.libelle + ')' : '')
                        : '[' + params.value + ']';
                }
            },
            cellEditor: 'departementsCellEditor',
            suppressKeyboardEvent: (params) => {
                return params.editing && AGGRID_NAVIGATION_KEYS.includes(params.event.keyCode);
            }
        },

        // Liste de départements
        zonegeographiqueColumn: {
            width: 160,
            tooltipValueGetter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'zonegeographiqueColumn');

                if (!value) {
                    return '';
                }
                const zones = getZones(value);
                return zones ? zones.join(', ') : '';
            },
            valueFormatter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'zonegeographiqueColumn');
                if (!value) {
                    return '';
                }
                const zones = getZones(value);
                return zones ? zones.join(', ') : '';
            },
            filter: 'agSetColumnFilter',
            filterParams: {
                excelMode: FILTER_PARAMS_EXCEL_MODE
            },
            cellEditor: 'zonesCellEditor',
            suppressKeyboardEvent: (params) => {
                return params.editing && AGGRID_NAVIGATION_KEYS.includes(params.event.keyCode);
            }
        },

        // Colonne pondération
        ponderationColumn: {
            width: 65,
            filter: false,
            menuTabs: [],
            tooltipValueGetter: (params) =>
                typeof params.value != 'undefined' && params.value !== null && !isNaN(Number.parseFloat(params.value))
                    ? Number.parseFloat(params.value).toFixed(1) + '%'
                    : '',
            cellRenderer: 'pourcentageCellRenderer',
            cellRendererParams: {
                decimals: 1
            },
            cellStyle: (params) => {
                return {
                    backgroundColor: ColorManipulation.getColorForPercentage(
                        parseFloat(params.value) / 100,
                        1,
                        ColorManipulation.COLOR_GRADIENT_WHITE_GREEN,
                        true
                    )
                };
            },
            cellClassRules: {
                [commonCssClasses.center]: getTrue,
                'editableNoBackground': getTrue
            },

            cellEditor: 'ponderationsCellEditor',
            suppressKeyboardEvent: (params) => {
                return params.editing && AGGRID_NAVIGATION_KEYS.includes(params.event.keyCode);
            }
        },

        // Colonne classement en pourcentage
        classementPourcentageColumn: {
            width: 70,
            filter: false,
            menuTabs: [],
            tooltipValueGetter: (params) =>
                typeof params.value != 'undefined' && params.value !== null && !isNaN(Number.parseFloat(params.value))
                    ? Number.parseFloat(params.value).toFixed(params.decimals) + '%'
                    : '',
            cellRenderer: 'pourcentageCellRenderer',
            cellRendererParams: {
                decimals: 0
            },

            cellStyle: (params) => {
                if (typeof params.value != 'undefined' && params.value !== null && params.value !== '' && params.value >= 0) {
                    return {
                        backgroundColor: ColorManipulation.getColorForPercentage(
                            parseFloat(params.value) / 100,
                            0.5,
                            ColorManipulation.COLOR_GRADIENT_EXCEL_RED_YELLOW_GREEN,
                            true
                        )
                    };
                }
            },
            cellClassRules: { [commonCssClasses.center]: getTrue }
        },

        // Colonne % pourvu
        pourvoiementPourcentageColumn: {
            width: 65,
            filter: false,
            menuTabs: [],
            tooltipValueGetter: (params) =>
                typeof params.value != 'undefined' && params.value !== null && !isNaN(Number.parseFloat(params.value))
                    ? Number.parseFloat(params.value).toFixed(params.decimals) + '%'
                    : '',
            cellRenderer: 'pourcentageCellRenderer',
            cellRendererParams: {
                decimals: 0
            },
            cellStyle: (params) => {
                if (typeof params.value != 'undefined' && params.value !== null && params.value !== '' && params.value >= 0) {
                    return {
                        backgroundColor: ColorManipulation.getColorForPercentage(
                            parseFloat(params.value) / 100,
                            0.5,
                            ColorManipulation.COLOR_GRADIENT_EXCEL_RED_YELLOW_GREEN,
                            true
                        )
                    };
                }
            },
            cellClassRules: { [commonCssClasses.center]: getTrue }
        },

        // Colonne classement en rang sur max 10
        classementRangColumn: {
            width: 55,
            filter: false,
            menuTabs: [],
            tooltipValueGetter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'classementRangColumn');
                if (!value) return '';

                return value ? value + '°' : '';
            },
            valueFormatter: (params) => {
                const value = getValueForCellOrGroupCell(params, null, 'classementRangColumn');
                if (!value) return '';

                return value ? value + '°' : '';
            },
            cellStyle: (params) => {
                if (params.value) {
                    return {
                        backgroundColor: ColorManipulation.getColorForPercentage(
                            Math.max(0, 11 - params.value) / 10,
                            0.5,
                            ColorManipulation.COLOR_GRADIENT_EXCEL_RED_YELLOW_GREEN,
                            true
                        )
                    };
                }
            },
            cellClassRules: { [commonCssClasses.right]: getTrue }
        },

        ...(() => {
            // colonne de notes
            const notesColumn = {
                filter: 'agTextColumnFilter',
                cellRenderer: 'notesCellRenderer',
                cellEditor: 'notesCellEditor',
                suppressKeyboardEvent: (params) => {
                    return params.editing && AGGRID_NAVIGATION_KEYS.includes(params.event.keyCode);
                },
                cellClassRules: { [commonCssClasses.center]: getTrue },
                width: 75
            };


            // colonne de notes d'utilisateurs
            const notesUtilisateurColumn = extend(true, {}, basicTypes.editableIfDecisionColumn, notesColumn, {
                headerName: 'No\u00ADtes PAM',
            });
            return { notesColumn, notesUtilisateurColumn};
        })(),

        ...(() => {
            // colonne de notes non editable
            const notesColumnNonEditable = {
                filter: 'agTextColumnFilter',
                cellRenderer: 'notesCellRenderer',
                cellEditor: 'notesCellViewer',
                suppressKeyboardEvent: (params) => {
                    return params.editing && AGGRID_NAVIGATION_KEYS.includes(params.event.keyCode);
                },
                cellClassRules: { [commonCssClasses.center]: getTrue },
                width: 75
            };


            // colonne de notes d'utilisateurs
            const notesUtilisateurColumnNonEditable = extend(true, {}, basicTypes.editableIfDecisionColumn, notesColumnNonEditable, {
                headerName: 'No\u00ADtes PAM',
            });
            return { notesColumnNonEditable, notesUtilisateurColumnNonEditable};
        })(),

        // colonne de décision
        decisionColumn: extend(true, {}, basicTypes.setColumn, (() => {
            const _formatter = creerFormateurParams(params => getDecisionLabel(params.value, getRefs(params)));
            const _valueFormatter = (params) => _formatter(params, '', '[' + params.value + ']');
            const _editable = (params) => {
                // la décision n'est pas créée par cette colonne
                if (!params.data?.decision_decision) {
                    return false;
                }
                const decisions = params.data?.decisions_possibles?.maj;
                return Array.isArray(decisions) && decisions.length;
            }
            return {
                headerName: 'Dé\u00ADci\u00ADsion',
                valueFormatter: _valueFormatter,
                tooltipValueGetter: _valueFormatter,
                filterParams: {
                    valueFormatter: (params) => _formatter(params, AGLocaleText.blanks, '[' + params.value + ']')
                },
                editable: _editable,
                cellRenderer: 'decisionCellRenderer',
                cellRendererParams: { valueFormatter: _valueFormatter },
                cellClassRules: {
                    [commonCssClasses.decision]: getTrue,
                    [commonCssClasses.editable]: _editable,
                },
                cellEditor: 'agRichSelectCellEditor',
                cellEditorParams: (params) => ({
                    values: params.data?.decisions_possibles?.maj,
                    useFormatter: true,
                    stopEditing: customizeEditorAndStopEditing(params, (params, editor) => {
                        editor.isCancelAfterEnd = () => {
                            getActionsMetierHelper(params)?.creeOuMAJDecisionAdministreAvecPoste(
                                params?.data?.id,
                                params?.data?.decision_posteId,
                                editor.getValue(),
                                params.value || DECISIONS.AUCUNE
                            ).then((val) => val && getMutator(params)?.());
                            return true;
                        }
                    }),
                }),
                width: 100
            }
        })()),

        // colonne de date de décision
        dateDecisionColumn: extend(true, {}, basicTypes.dateColumn, {
            headerName: 'Da\u00ADte dé\u00ADci\u00ADsion',
            cellClassRules: { [commonCssClasses.center]: getTrue },
            width: 120
        }),

        /*
        // Colonne de sélection par checkbox
        cbSelectionColumn: {
            headerName: '',
            headerClass: '',
            suppressColumnsToolPanel: true,
            suppressFiltersToolPanel: true,

            checkboxSelection: true,

            width: 42,
            minWidth: 42,
            maxWidth: 200,
            resizable: false,
            suppressSizeToFit: true,
            suppressMovable: true,
            suppressCellFlash: true,

            pinned: 'left',
            lockPinned: true,
            lockPosition: true,
            lockVisible: true,

            sortable: false,
            filter: false,
            menuTabs: [],
            suppressMenu: true,

            valueFormatter: ({ value }) => {
                return '';
            }
        },
        */
    });
})();

/**
 * types de colonnes communs
 * @type {{BLANK: string, editableColumn: string, editableIfDecisionColumn: string, textColumn: string, setColumn: string,
 * dateColumn: string, numberColumn: string, positiveIntegerColumn: string, domaineColumn: string, filiereColumn: string,
 * NFColumn: string, competencesColumn: string, departementsColumn: string, zonegeographiqueColumn: string,
 * ponderationColumn: string, classementPourcentageColumn: string, pourvoiementPourcentageColumn: string, classementRangColumn: string,
 * notesColumn: string, notesUtilisateurColumn: string, decisionColumn: string, dateDecisionColumn: string,
 * notesColumnNonEditable: string, notesUtilisateurColumn: string, decisionColumn: string, dateDecisionColumn: string}}
 */
export const commonColTypes = createConstantsFrom(Object.keys(commonAGGridColumnTypes));
