import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { toDayjsAtStartOfDayOrDefault, toDayjsOrNull } from '../../listes/commonAGGridFunctions';

// format standard (et attendu) pour les inputs de type date
const HTML_DATE_FORMAT = 'YYYY-MM-DD';

const dateToHtml = (value) => toDayjsOrNull(value)?.format(HTML_DATE_FORMAT) ?? '';

/**
 * Composant d'édition d'une date dans une cellule d'AG Grid.
 * fortement inspiré de la documetation : https://www.ag-grid.com/react-data-grid/component-cell-editor/
 *
 * @component
 * @param {any}       props.value       Valeur initiale (tout type accepté par dayjs, de préférence Date ou dayjs). optionnel
 * @param {any}       props.min         Valeur min      (tout type accepté par dayjs, de préférence Date ou dayjs). optionnel
 * @param {any}       props.max         Valeur max      (tout type accepté par dayjs, de préférence Date ou dayjs). optionnel
 * @param {string}    props.className   Classe CSS à appliquer. optionnel
 * @param {boolean}   props.nullable    Indique si l'absence de valeur est valide. défaut : une valeur vide n'est pas valide
 */
// TODO composant à refactoriser via un AbstractCellEditor (à la manière de AbstractPopinEditor) ?
const DateCellEditor = forwardRef((props, ref) => {
    const [value, setValue] = useState(dateToHtml(props.value));
    const refInput = useRef(null);

    useEffect(() => {
        // focus on the input
        setTimeout(() => refInput.current.focus());
    }, []);

    /* Component Editor Lifecycle methods */
    useImperativeHandle(ref, () => ({
        // the final value to send to the grid, on completion of editing
        getValue: () => {
            let dateValue = toDayjsAtStartOfDayOrDefault(value, null, HTML_DATE_FORMAT)
            if (!dateValue) {
                return dateValue;
            }
            // nouvelle valeur invalide, renvoie la valeur initiale
            if (!dateValue.isValid()) {
                return props.value;
            }
            const min = toDayjsAtStartOfDayOrDefault(props.min);
            if (min?.isValid() && min.isAfter(dateValue)) {
                dateValue = min;
            }
            const max = toDayjsAtStartOfDayOrDefault(props.max);
            if (max?.isValid() && max.isBefore(dateValue)) {
                dateValue = max;
            }
            // note : si max avant min il y a de toute façon un problème
            return dateValue.toDate()
        },

        // Gets called once when editing is finished (eg if Enter is pressed).
        // If you return true, then the result of the edit will be ignored.
        isCancelAfterEnd: () => !props.nullable && !value
    }));

    const onChange = (event) => setValue(event.target.value);
    return (
        <div className="ag-custom-component-popup">
            <input
                className={'DateCellEditor ' + (props.className ?? '')}
                type="date"
                ref={refInput}
                value={value}
                min={dateToHtml(props.min)}
                max={dateToHtml(props.max)}
                onChange={onChange}
            />
        </div>
    );
});

DateCellEditor.displayName = 'DateCellEditor';

export default DateCellEditor;