// js/calendar_admin.js

document.addEventListener('DOMContentLoaded', function(){
    const calendarEl = getElementOrThrow('calendar');
    let selected_start_string = null;
    let event_selected = false; // pour event.remove()

    const calendar = new FullCalendar.Calendar(calendarEl,{
        editable: true,
        locale: 'fr',
        //timeZone: 'local', // à modifier pour être à l'heure d'un autre pays
        initialView: 'dayGridMonth',
        headerToolbar:{
            left: 'prev,next today',
            center: 'title',
            //right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
            right: 'dayGridMonth,timeGridWeek,listWeek'
        },
        slotMinWidth: 70,
        defaultAllDay: false,

        // numéros de semaine
        //weekNumbers: true,
        //weekText: 's',
        
        // vue mois
        contentHeight: 600, // après initialisation: calendar.setOption('contentHeight', 650);
        //aspectRatio: 1.5, // après initialisation: calendar.setOption('aspectRatio', 1.8);
        // pour recalculer la taille au redimensionnement du parent, exécuter: calendar.updateSize()
        stickyHeaderDates: true, // garder les en-tête de colonnes lors du scroll
        fixedWeekCount: false, // avec false, affiche 4, 5 ou 6 semaines selon le mois
        selectable: true, // sélection de jours en cliquant dessus
        longPressDelay: 300, // 1000ms par défaut
        navLinks: true, // numéros de jour et de semaines clicables
        
        // vue semaine
        slotEventOverlap: true, // superposition (limitée) de deux évènements simultanés
        allDayContent: 'Journée', // texte dans la case "toute la journée"
        nowIndicator: true, // barre rouge pour maintenant

        // params en plus: https://fullcalendar.io/docs/events-json-feed
        events: 'index.php?action=get_events', // fichier PHP qui retourne les événements
        
        select: function(info){
            selected_start_string = info.startStr; // variable "globale"
            event_selected = false;
            const modal = getElementOrThrow('event_modal');
            let checked = '';
            let input = 'datetime-local';

            // on veut des chaines de la forme 2025-05-20T07:05
            // il faut retirer les secondes et le fuseau horaire du format ISO, c'est chiant
            // on enverra par contre une chaine ISO au serveur pour avoir un enregistrement correct
            
            let start_value;
            let end_value;
            const end = new Date(info.endStr);

            if(calendar.view.type == 'dayGridMonth'){
                const start = new Date(info.startStr);
                start_value = start.toISOString().split('T')[0] + 'T10:00';
                
                end.setDate(end.getDate() - 1); // jour de fin modifié pour ne pas faire bizarre pour l'utilisateur
                end_value = end.toISOString().split('T')[0] + 'T10:30';
            }
            else if(calendar.view.type == 'timeGridWeek' || calendar.view.type == 'timeGridDay'){
                const start_array = info.startStr.split("T");
                const end_array = info.endStr.split("T");

                // clic sur la ligne "Journée", = 'dayGridMonth'
                if(start_array.length == 1){
                    checked = 'checked';
                    input = 'date';
                    start_value = info.startStr;
                    end.setDate(end.getDate() - 1);
                    end_value = end.toISOString().split('T')[0];
                }
                else if(start_array.length == 2){
                    start_value = start_array[0] + "T" + start_array[1].substr(0,5); // format 2025-06-12T10:00
                    end_value = end_array[0] + "T" + end_array[1].substr(0,5);
                }
            }

            const modal_content = `<div id="form_event">
                    <div class="event_title_box">
                        <h2>Nouvel évènement</h2>
                    </div>
                    <div class="">
                        <label for="event_title">Nom</label>
                        <input type="text" id="event_title">
                    </div>
                    <div class="">
                        <label for="event_description">Description</label>
                        <textarea id="event_description" cols="27"></textarea>
                    </div>
                    <div class="">
                        <input type="checkbox" id="event_all_day" class="event_all_day" ` + checked + `>
                        <label for="event_all_day">Journée entière</label>
                    </div>
                    <div class="">
                        <label for="event_start">Début</label>
                        <input type="` + input + `" id="event_start" value="` + start_value + `">
                    </div>
                    <div class="">
                        <label for="event_end">Fin</label>
                        <input type="` + input + `" id="event_end" value="` + end_value + `">
                    </div>
                    <div class="">
                        <label for="event_color">Couleur</label>
                        <input type="color" id="event_color" value="#3788D8">
                    </div>
                    <button class="submit_new_event">Enregistrer</button>
                    <button class="event_close_button">Annuler</button>
                </div>`;
            modal.innerHTML = modal_content;
            calendar.updateSize();
        },
        // sélection d'une date simple sur mobile, évite des problèmes de conflit avec eventClick
        dateClick: function(info){
            if(window.matchMedia('(pointer: coarse)').matches){
                const end = new Date(info.date);
                calendar.view.type == 'dayGridMonth' ? end.setDate(end.getDate() + 1) : end.setMinutes(end.getMinutes() + 30);
                // vue date: la fin est une date exclue
                // vue semaine: durée de 30min par défaut

                const local_end_date_array = end.toLocaleDateString().split('/');
                let local_end_str = local_end_date_array[2] + '-' + local_end_date_array[1] + '-' + local_end_date_array[0];

                if(calendar.view.type != 'dayGridMonth'){
                    local_end_str += 'T' + end.toLocaleTimeString();
                }

                // on a besoin de deux chaînes représentant l'heure locale pour obtenir le même objet "info" qu'avec l'évènement select
                // la vue "dayGridMonth" nécessite deux paramètres, par sécurité on en enverra toujours deux
                calendar.select(info.dateStr, local_end_str);
            }
        },
        //unselect: function(event, view){},
        eventClick: function(info){
            event_selected = true; // variable "globale"
            const modal = getElementOrThrow('event_modal');
            const checked = info.event.allDay ? 'checked' : '';
            const input = info.event.allDay ? 'date' : 'datetime-local';

            // change des objets Date en chaînes compatibles avec les input
            function formatDate(date){
                return date.getFullYear() + '-' + (date.getMonth() + 1).toString().padStart(2, '0') + '-' + date.getDate().toString().padStart(2, '0')
                    + (info.event.allDay ? '' : 'T' + date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0'));
            }
            function minusOneDay(date){
                date.setDate(date.getDate() - 1); // jour de fin modifié pour ne pas faire bizarre pour l'utilisateur
                return date;
            }

            const formated_start = formatDate(info.event.start);
            const formated_end = formatDate(info.event.allDay ? minusOneDay(info.event.end) : info.event.end);
            
            const modal_content = `<div id="form_event" style="border-color: ` + info.event.backgroundColor +`;">
                    <div class="event_title_box">
                        <h2>Modifier un évènement</h2>
                    </div>
                    <div class="">
                        <label for="event_title">Nom</label>
                        <input type="text" id="event_title" value="` + info.event.title + `">
                        <input type="hidden" id="event_id" value="` + info.event.id + `">
                    </div>
                    <div class="">
                        <label for="event_description">Description</label>
                        <textarea id="event_description" cols="27">` + info.event.extendedProps.description + `</textarea>
                    </div>
                    <div class="">
                        <input type="checkbox" id="event_all_day" class="event_all_day" ` + checked + `>
                        <label for="event_all_day">Journée entière</label>
                    </div>
                    <div class="">
                        <label for="event_start">Début</label>
                        <input type="` + input + `" id="event_start" value="` + formated_start + `">
                    </div>
                    <div class="">
                        <label for="event_end">Fin</label>
                        <input type="` + input + `" id="event_end" value="` + formated_end + `">
                    </div>
                    <div class="">
                        <label for="event_color">Couleur</label>
                        <input type="color" id="event_color" value="` + info.event.backgroundColor + `">
                    </div>
                    <button class="submit_update_event">Modifier</button>
                    <button class="event_close_button">Annuler</button>
                    <button class="delete_event">Supprimer</button>
                </div>`;
            modal.innerHTML = modal_content;
            calendar.updateSize();
        },
        viewDidMount: function(info){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...)
            if(selected_start_string){
                calendar.gotoDate(new Date(selected_start_string));
            }
        },
        //datesSet: function(info){}, // déclenché lorsque des dates affichées sont chargées (= comme viewDidMount + changement de date)
    });
    
    function hideModal(){
        const modal = getElementOrThrow('event_modal');
        event_selected = false;
        modal.innerHTML = '';
        calendar.updateSize();
    }

    function submitEvent(new_event){
        const event_title_input = getElementOrThrow('event_title');
        const event_description_input = getElementOrThrow('event_description');
        const event_all_day_input = getElementOrThrow('event_all_day');
        const event_start_input = getElementOrThrow('event_start');
        const event_end_input = getElementOrThrow('event_end');
        const event_color_input = getElementOrThrow('event_color');
        assertElementType(event_title_input, HTMLInputElement);
        assertElementType(event_description_input, HTMLTextAreaElement);
        assertElementType(event_all_day_input, HTMLInputElement);
        assertElementType(event_start_input, HTMLInputElement);
        assertElementType(event_end_input, HTMLInputElement);
        assertElementType(event_color_input, HTMLInputElement);

        const event_title = event_title_input.value;
        const event_description = event_description_input.value;
        const event_all_day = event_all_day_input.checked;
        let event_start = event_start_input.value;
        let event_end = event_end_input.value;
        const event_color = event_color_input.value; // #3788d8 par défaut
        
        let event_id = '';
        if(!new_event){
            const event_id_input = getElementOrThrow('event_id');
            assertElementType(event_id_input, HTMLInputElement);
            event_id = event_id_input.value;
        }

        // contrôle de saisie
        if(event_title.length !== 0 && event_start.length !== 0 && event_end.length !== 0 && event_color.length !== 0
            && (new_event || event_id.length !== 0))
        {
            if(event_all_day){
                // on remet le jour de fin exclu
                const tmp_object = new Date(event_end);
                tmp_object.setDate(tmp_object.getDate() + 1);
                event_end = tmp_object.toISOString().split('T')[0];
            }
            else{
                event_start = new Date(event_start).toISOString();
                event_end = new Date(event_end).toISOString();
            }

            // contrôle date/heure de fin après le début
            if(event_start > event_end || (!event_all_day && event_start == event_end)){
                toastNotify("Erreur: la fin de l'évènement doit se situer après son début.");
                return;
            }

            // création
            if(new_event){
                const event = {
                    id: '',
                    title: event_title,
                    description: event_description,
                    allDay: event_all_day,
                    start: event_start,
                    end: event_end,
                    color: event_color
                };

                fetch('index.php?action=new_event', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(event),
                })
                .then(response => response.json())
                .then(data => {
                    if(data.success){
                        event.id = data.id;
                        calendar.addEvent(event);
                        hideModal();
                    }
                })
                .catch((error) => {
                    console.error('Error:', error);
                });
                
            }
            // modification
            else{
                const event = calendar.getEventById(event_id);
                if(!event){
                    throw new Error("Événement non trouvé !");
                }
                if(event){
                    const event_copy = {
                        id: parseInt(event.id),
                        description: event_description,
                        title: event_title,
                        allDay: event_all_day,
                        start: event_start,
                        end: event_end,
                        color: event_color
                    };

                    fetch('index.php?action=update_event', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify(event_copy),
                    })
                    .then(response => response.json())
                    .then(data => {
                        if(data.success){
                            event.setProp('title', event_title);
                            event.setExtendedProp('description', event_description);
                            event.setAllDay(event_all_day);
                            event.setStart(event_start);
                            event.setEnd(event_end);
                            event.setProp('color', event_color);
                            hideModal();
                        }
                    })
                    .catch((error) => {
                        console.error('Error:', error);
                    });
                }
                else{
                    console.log("Événement non trouvé !");
                }
            }
        }
        else{
            // notif input vide
            console.log('erreur: input vide');
        }
    }

    function checkAllDay(){
        const event_start_input = getElementOrThrow('event_start');
        const event_end_input = getElementOrThrow('event_end');
        const event_all_day = getElementOrThrow('event_all_day');
        assertElementType(event_start_input, HTMLInputElement);
        assertElementType(event_end_input, HTMLInputElement);
        assertElementType(event_all_day, HTMLInputElement);

        const start = event_start_input.value;
        const end = event_end_input.value;

        if(event_all_day.checked){
            event_start_input.type = 'date';
            event_end_input.type = 'date';

            event_start_input.value = start.split('T')[0];
            event_end_input.value = end.split('T')[0];
        }
        else{
            event_start_input.type = 'datetime-local';
            event_end_input.type = 'datetime-local';

            event_start_input.value = start + 'T10:00';
            event_end_input.value = end + 'T11:00';
        }
    }
    function removeEvent(){
        if(!confirm("Voulez-vous vraiment supprimer cet évènement du calendrier?")){
            return;
        }
        const event_tag = document.getElementById('event_id'); // cible input hidden
        if(!event_tag || !(event_tag instanceof HTMLInputElement)){
            return;
        }
        const event_id = event_tag.value;
        const event = calendar.getEventById(event_id);
        if(!event){
            throw new Error("Événement non trouvé !");
        }
        
        fetch('index.php?action=remove_event', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({'id': event_id}),
        })
        .then(response => response.json())
        .then(data => {
            if(data.success){
                event.remove();
                hideModal();
            }
        })
        .catch((error) => {
            console.error('Error:', error);
        });
        event_selected = false;
    }

    // touches de clavier
    document.addEventListener('keydown', function(event){
        if(event.key === 'Escape'){
            hideModal();
        }
        else if(event.key === 'Delete' && event_selected === true){
            removeEvent();
        }
    });

    // boutons dans la "modale"
    // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement
    document.addEventListener('click', function(event){
    	if(!event.target){
            throw new Error('évènement click non conforme');
        }
        assertElementType(event.target, HTMLElement);
        if(event.target.classList.contains('event_close_button')){
            hideModal();
        }
        else if(event.target.classList.contains('event_all_day')){
            checkAllDay();
        }
        else if(event.target.classList.contains('submit_new_event')){
            submitEvent(true);
        }
        else if(event.target.classList.contains('submit_update_event')){
            submitEvent(false);
        }
        else if(event.target.classList.contains('delete_event')){
            removeEvent();
        }
    });

    calendar.render();
});