{% extends "sco_page.j2" %}

{% block styles %}
{{ super() }}
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/assiduites.css">
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/minitimeline.css">

<style>
    .ui-timepicker-container,#ui-datepicker-div{
        z-index: 5 !important;
    }
    #new_periode,
    #actions {
        display: flex;
        flex-direction: column;
        width: fit-content;
        gap: 0.5em;
    }

    #actions {
      flex-direction: row;
      align-items: center;
      margin: 5px 0;
    }
    #actions label{
      margin: 0;
    }

    #fix {
        display: flex;
        flex-direction: row;
        gap: 1em;
        justify-content: space-between;
        width: fit-content;
    }

    #fix>.box {
        border: 1px solid #444;
        border-radius: 0.5em;
        padding: 1em;
    }

    .timepicker {
        width: 5em;
        text-align: center;
    }

    #moduleimpl_select {
        width: 10em;
    }

    #tableau-periode {
        display: flex;
        flex-direction: column;
        overflow-x: scroll;
        max-width: var(--sco-content-max-width);
    }

    #tableau-periode .pdp {
        width: 5em;
        border-radius: 8px;
    }

    .header {
        background-color: #f9f9f9;
        padding: 10px;
        text-align: center;
        border: 1px solid #ddd;
    }
    
    .cell, .header {
        border: 1px solid #ddd;
        padding: 10px;
        display: flex;
        flex-direction: column;
        align-items: center;
        background-color: #f9f9f9;
    }
    .header{
        justify-content: space-between;
    }

    .cell {
        display: flex;
        align-items: center;
        justify-content: center;
        border: 1px solid #ddd;
        padding: 10px;
        text-align: center;
        width: 256px;
    }
    .cell p{
        text-align: center;
    }
    .sticky {
        position: sticky;
        top: 0;
        background-color: #f9f9f9;
        z-index: 2;
    }

    .cell .assiduite-bubble {
        display: block;
        top: 0;
        z-index: 0;
        width: 100% !important;
        min-width: inherit !important;
    }

    .assi-btns {
      display: flex;
      gap: 4px;
    }
    
    .pointer{
        cursor: pointer;
    }

    .ligne{
        display: flex;
        gap: 1px;
    }

</style>

{% endblock styles %}

{% block scripts %}
{{ super() }}
<script src="{{scu.STATIC_DIR}}/js/etud_info.js"></script>
<script src="{{scu.STATIC_DIR}}/js/assiduites.js"></script>
<script src="{{scu.STATIC_DIR}}/js/date_utils.js"></script>
{% include "sco_timepicker.j2" %}

<script>

/**
 * Permet d'ajouter une nouvelle période au tableau
 * Par défaut la période est générèe avec les valeurs des inputs
 * Si une période est passée en paramètre, alors on utilise ses valeurs
 * @param {Object} period  - La période à ajouter
 */
async function nouvellePeriode(period = null) {
  // On récupère l'id de la période
  let periodId;
  if (period) {
    periodId = period.periodId;
  } else {
    periodId = currentPeriodId++;
  }

  // On récupère les valeurs des inputs
  let date = document.getElementById("date").value;
  let debut = document.getElementById("debut").value;
  let fin = document.getElementById("fin").value;
  let moduleimpl_id = document.getElementById("moduleimpl_select").value;
  const moduleimpl = await getModuleImpl({ moduleimpl_id: moduleimpl_id });

  // Si une période est passée en paramètre, on utilise ses valeurs
  if (period) {
    date = period.date_debut.format("DD/MM/YYYY");
    debut = period.date_debut.format("HH:mm");
    fin = period.date_fin.format("HH:mm");
    moduleimpl_id = period.moduleimpl_id;
  }else{
    //Sinon on vérifie qu'on a bien des valeurs
    const text = document.createTextNode("Veuillez remplir tous les champs pour ajouter une plage.")
    if (date == "" || debut == "" || fin == "" || moduleimpl_id == "") {
      openAlertModal(
        "Erreur",
        text
      );
      return;
    }
  }

  // Vérification de la plage horaire
  // On génère une date de début et de fin de la période
  const date_debut = new Date(
    $("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + debut
  );
  const date_fin = new Date(
    $("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + fin
  );
  date_debut.add(1, "seconds");

  // On vérifie que les dates sont valides
  if (!date_debut.isValid()){
    const p = document.createElement("p");
    p.textContent = "La date de début n'est pas valide.";
    openAlertModal(
      "Erreur",
      p,
    );
    return;
  }
  if (!date_fin.isValid()){
    const p = document.createElement("p");
    p.textContent = "La date de fin n'est pas valide.";
    openAlertModal(
      "Erreur",
      p,
    );
    return;
  }

  // On vérifie que l'heure de fin est supérieure à l'heure de début
  if (date_debut >= date_fin) {
    const p = document.createElement("p");
    p.textContent = "La plage horaire n'est pas valide. L'heure de fin doit être "+
    "supérieure à l'heure de début.";
    openAlertModal(
      "Erreur",
      p,
    );
    return;
  }

  // On ajoute la nouvelle période au tableau
  let periodeDiv = document.createElement("div");
  periodeDiv.classList.add("cell", "header");
  periodeDiv.id = `periode-${periodId}`;
  
  const periodP = document.createElement("p");
  periodP.textContent = `Plage du ${date} de ${debut} à ${fin}`;

  // On ajoute le moduleimpl
  const modP = document.createElement("p");
  modP.textContent = moduleimpl;

  // On ajoute le bouton pour supprimer la période
  const close = document.createElement("button");
  close.textContent = "❌";
  close.addEventListener("click", () => {
    // On supprime toutes les cases du tableau correspondant à cette période
    document
      .querySelectorAll(
        `[data-periodeid="${periodeDiv.getAttribute("data-periodeid")}"]`
      )
      .forEach((e) => e.remove());
    // On supprime la période de la Map periodes
    periodes.delete(Number(periodeDiv.getAttribute("data-periodeid")));
  });
  //On ajoute les éléments au DOM
  periodeDiv.appendChild(periodP);
  periodeDiv.appendChild(modP);
  periodeDiv.appendChild(close);
  periodeDiv.setAttribute("data-periodeid", periodId);
  document.getElementById("tete-table").appendChild(periodeDiv);

  // On récupère les étudiants (etudids)
  let etudids = [
    ...document.querySelectorAll(".ligne[data-etudid]"),
  ].map((e) => e.getAttribute("data-etudid"));

  // Préparation de la requête
  const url =
    `../../api/assiduites/group/query?date_debut=${date_debut.toFakeIso()}` +
    `&date_fin=${date_fin.toFakeIso()}&etudids=${etudids.join(
      ","
    )}&with_justifs`;

  //Si la période n'existait pas, alors on l'ajoute à la Map
  if (!period) {
    periodes.set(periodId, {
      date_debut: date_debut.clone().add(-1, "seconds"),
      date_fin: date_fin,
      moduleimpl_id: moduleimpl_id,
      periodId: periodId,
    });
  }

  // On récupère les incriptions au module
  const inscriptions = await getInscriptionModule(moduleimpl_id);

  // On récupère les assiduités
  await fetch(url)
    // On convertit la réponse en JSON
    .then((res) => {
      if (!res.ok) {
        throw new Error("Network response was not ok");
      }
      return res.json();
    })
    // On traite les données
    .then((data) => {
      for (let etudid of etudids) {
        // On crée une case pour chaque étudiant
        let cell = document.createElement("div");
        cell.classList.add("cell");
        cell.setAttribute("data-etudid", etudid);
        cell.setAttribute("data-periodeid", periodId);
        cell.id = `cell-${etudid}-${periodId}`;
        document.querySelector(`.ligne[data-etudid="${etudid}"]`).appendChild(cell);

        //Vérification inscription au module
        // Si l'étudiant n'est pas inscrit, on le notifie et on passe à l'étudiant suivant
        const inscrit =
          inscriptions == null ? true : inscriptions.find((e) => e == etudid);
        if (!inscrit) {
          cell.textContent = "Non inscrit";
          cell.classList.add("non-inscrit");
          continue;
        }

        //Gestion des assiduités déjà existantes
        const assiduites = data[etudid];
        // Si l'étudiant n'a pas d'assiduité, on crée les boutons assiduité
        if (assiduites.length == 0) {

            const assi_btns = document.createElement('div');
            assi_btns.classList.add('assi-btns');

          ["present", "retard", "absent"].forEach((value) => {
            const cbox = document.createElement("input");
            cbox.type = "checkbox";
            cbox.value = value;
            cbox.name = `rbtn_${etudid}_${periodId}`;
            cbox.classList.add("rbtn", value);

            // Event pour être sur qu'un seul bouton est coché à la fois
            cbox.addEventListener("click", (event) => {
              const parent = event.target.parentElement;
              parent.querySelectorAll(".rbtn").forEach((ele) => {
                if (ele.value != value) {
                  ele.checked = false;
                }
              });
            });
            // Si une valeur par défaut est donnée alors on l'applique
            cbox.checked = etatDef.value == value;

            assi_btns.appendChild(cbox);
          });
          cell.appendChild(assi_btns);
        } else {
          // Si une (ou plus) assiduité sont trouvée pour la période
          // alors on affiche les informations  de la première assiduité
          setupAssiduiteBubble(cell, assiduites[0]);
        }
      }
    })
    //Si jamais la requête échoue, on affiche un message d'erreur dans la console
    .catch((error) => {
      console.error("Error:", error);
    });

    document.getElementById("tableau-periode").classList.remove("hidden");
}
/**
 * Permet de récupérer la saisie puis créer les assiduités grâce à l'api
 */
function sauvegarderAssiduites() {
  // Initialisation de la liste des assiduités à créer
  let assiduitesData = [];
  // Pour chaque période, on récupère les assiduités saisies
  for (let [periodeId, periode] of periodes.entries()) {
    // On prend chaque cellule correspondant à la période
    const cells = document.querySelectorAll(
      `.cell[data-periodeid="${periodeId}"][data-etudid]`
    );
    // Pour chaque cellule, on récupère l'état de l'assiduité
    cells.forEach((cell) => {
      const etudid = cell.getAttribute("data-etudid");
      const etat = cell.querySelector(".rbtn:checked")?.value;
      // Il est possible que l'état soit null
      // - Cas où l'étudiant n'est pas inscrit
      // - Cas où l'étudiant avait déjà une assiduité
      if (etat) {
        // On génère un objet "assiduité"
        /*
        {
            etudid: <int>,
            etat: <string>,
            date_debut: <string>,
            date_fin: <string>,
            moduleimpl_id: <int>,
            periodId: <int>
        }
        */
        assiduitesData.push({
          etudid: etudid,
          etat: etat,
          ...periode,
        });
      }
    });
  }

  // Une fois les assiduités générées, on les envoie à l'api
  async_post(
    "../../api/assiduites/create",
    assiduitesData,
    // Si la requête passe
    async (data) => {
      // On supprime toutes les cases du tableau pour le mettre à jour
      document.querySelectorAll("[data-periodeid]").forEach((e)=>e.remove())

      // On recrée les périodes
      // (cela permet de redemander les assiduités, donc mettre à jour les cases)
      for (let periode of periodes.values()) {
        await nouvellePeriode(periode);
      }

      // Si il y n'a pas d'erreur, on affiche un message de succès
      if (data.errors.length == 0) {
        const span = document.createElement("span");
        span.textContent = "Les assiduités ont bien été sauvegardées.";
        openAlertModal(
          "Sauvegarde des assiduités",
          span,
          null,
          "var(--color-present)"
        );
        return;
      }
      // Si il y a des erreurs, on les affiche
      if (data.errors.length > 0) {
        // On crée une map pour regrouper les erreurs par période
        const erreurs = new Map();
        data.errors.forEach((err) => {
          // Pour chaque période on créer une liste d'erreurs
          // format : [message, etudid]
          const assi = assiduitesData[err.indice];
          const msg = err.message;
          const periodErrors = erreurs.get(assi.periodId) || [];

          // Récupération du nom de l'étudiant
          const etud = document.querySelector(
            `#head-${assi.etudid} span`
          ).textContent;
          periodErrors.push([`Erreur pour ${etud} : ${msg}`, assi.etudid]);
          erreurs.set(assi.periodId, periodErrors);
        });

        // Création du DOM
        /*
        <ul>
            <li>
                Période du ... de ... à ...
                <ul>
                    <li>Erreur pour ...</li>
                    <li>Erreur pour ...</li>
                </ul>
            /li>
        </ul>
        */

        const ul = document.createElement("ul");
        //Pour chaque période on créer un titre "periode du ... de ... à ..."
        for (let [periodeId, periodErrors] of erreurs.entries()) {
          const period = periodes.get(periodeId);
          const li = document.createElement("li");
          // On affiche la période
          li.textContent = `Plage du ${period.date_debut.format(
            "DD/MM/YYYY HH:mm"
          )} à ${period.date_fin.format("HH:mm")}`;

          // Nous emmène à la période lorsqu'on clique dessus
          li.addEventListener("click", () => {
            location.href = `#periode-${periodeId}`;
          });
          li.classList.add("pointer");

          // Pour chaque erreur, on créer un élément de liste
          const ul2 = document.createElement("ul");
          periodErrors.forEach((err) => {
            const li2 = document.createElement("li");
            li2.textContent = err[0];
            li2.classList.add("pointer");

            // Nous emmène à la case de l'étudiant lorsqu'on clique dessus
            li2.addEventListener("click", () => {
              location.href = `#cell-${err[1]}-${periodeId}`;
            });
            ul2.appendChild(li2);
          });
          li.appendChild(ul2);
          ul.appendChild(li);
        }

        openAlertModal(
          "Erreurs lors de la sauvegarde des assiduités",
          ul,
          "Les autres assiduités ont bien été sauvegardées."
        );
      }
    },
    (e) => {
      console.error("Erreur lors de la création des assiduités", e);
    }
  );
}

// Mis en place des variables globales
let currentPeriodId = 0;
const periodes = new Map();
const moduleimpls = new Map();
const inscriptionsModules = new Map();
const nonWorkDays = [{{ nonworkdays| safe }}];

// Vérification du forçage de module
window.forceModule = "{{ forcer_module }}" == "True";
if (window.forceModule) {
  if (moduleimpl_select.value == "") {
    document.getElementById("forcemodule").style.display = "block";
    add_periode.disabled = true;
  }
  // Désactivation du bouton d'ajout de période si aucun module n'est sélectionné
  // et affichage du message de forçage de module
  moduleimpl_select?.addEventListener("change", (e) => {
    if (e.target.value != "") {
      document.getElementById("forcemodule").style.display = "none";
      add_periode.disabled = false;
    } else {
      document.getElementById("forcemodule").style.display = "block";
      add_periode.disabled = true;
    }
  });
}
/**
 * Fonction exécutée au lancement de la page
 * - On affiche ou non les photos des étudiants
 * - On vérifie si la date est un jour travaillé
 */
async function main() {
  const checked = localStorage.getItem("scodoc-etud-pdp") == "true";
  afficherPDP(checked);
  $("#date").on("change", async function (d) {
    // On vérifie si la date est un jour travaillé
    dateCouranteEstTravaillee();
  });
}

main();

</script>

{% endblock scripts %}

{% block title %}
{{title}}
{% endblock title %}

{% block app_content %}

<h2>Signalement différé de l'assiduité {{gr |safe}}</h2>


<div id="fix">
    <!-- Nouvelle Plage
        Permet de créer une nouvelle ligne pour une nouvelle Plage
        (
            Jour, -> datepicker
            Heure de début, -> timepicker
            Heure de fin -> timepicker
            ModuleImplId -> select (liste des modules tout semestre confondu)
        )
    --->

    <div id="new_periode" class="box">
        <label for="date">
            Date :
            <input type="text" name="date" id="date" class="datepicker">
        </label>
        <label for="debut">
            Heure de début :
            <input type="text" name="debut" id="debut" class="timepicker">
        </label>
        <label for="fin">
            Heure de fin :
            <input type="text" name="fin" id="fin" class="timepicker">
        </label>

        <label for="moduleimpl_select">
            <div id="forcemodule" style="display: none; margin:10px 0px;">
                Vous devez spécifier le module ! (voir réglage préférence du semestre)
            </div>
            Module :
            {{moduleimpl_select | safe}}
        </label>

        <button id="add_periode" onclick="nouvellePeriode()">Ajouter une plage</button>
    </div>
</div>
<!-- Boutons d'actions
        - Sauvegarder
        - Afficher la photo de profil
        - Assiduité par défaut (aucune, present, retard, absent)
    --->
    <br>
<div id="actions" class="flex">
    <button id="save" onclick="sauvegarderAssiduites()">ENREGISTRER</button>
    <label for="pdp">
        Photo de profil :
        <input type="checkbox" name="pdp" id="pdp" checked onclick="afficherPDP(this.checked)">
    </label>

    <label for="etatDef">
    Intialiser les étudiants comme : 
    <select name="etatDef" id="etatDef">
        <option value="">-</option>
        <option value="present">présents</option>
        <option value="retard">en retard</option>
        <option value="absent">absents</option>
    </select>
    </label>
    
</div>

<!-- Tableau à double entrée 
        Colonne : Etudiants (Header = Nom, Prénom, Photo (si actif))
        Ligne : Période (Header = Jour, Heure de début, Heure de fin, ModuleImplId)
        Contenu : 
            - bouton assiduité (présent, retard, absent)
            - Bouton conflit si conflit de période
    --->

<div id="tableau-periode" class="grid-table">
    <!-- Première ligne : Plages -->
    <div class="ligne" id="tete-table">
      <div class="cell header sticky">Étudiants</div>
      {# <div class="cell header" periode-id="X">Plage X</div> #}
    </div>
    {# ... #}

    <hr class="hidden" id="separator">

    {% for etud in etudiants %}
    <div class="ligne" data-etudid="{{etud.etudid}}">
      <div class="cell etudinfo sticky" id="head-{{etud.etudid}}">
          <img src="../../api/etudiant/etudid/{{etud.etudid}}/photo?size=small" alt="{{etud.nomprenom}}" class="pdp">
          <span>{{ etud.nomprenom }}</span>
      </div>
      {# <div class="cell" periode-id="X">Assiduité Plage 1</div> #}

    </div>
    {% endfor %}



</div>


{% include "assiduites/widgets/alert.j2" %}
{% endblock app_content %}
