// Événement de vérification d'authentification
document.addEventListener('DOMContentLoaded', function () {
  // Vérification de la page sur laquelle nous sommes
  if (window.location.pathname !== '/auth') {
    // Récupération du token JWT du localStorage
    const token = localStorage.getItem('jwtToken');

    // Si pas de token, redirige vers la page d'authentification
    if (!token) {
      window.location.replace('/auth');
    } else {
      // Si un token existe, vérification de sa validité
      fetch('/auth/verifyToken', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer ' + token
        }
      })
      .then(res => res.json())
      .then(data => {
        
        // Si le token n'est pas valide, redirige vers la page d'authentification
        if (!data.valid) {
          localStorage.removeItem('jwtToken');
          window.location.replace('/auth');
        }
      })
      .catch(error => {
        console.error('Error:', error);
      });
    }
  }
});

// Événement du bouton déconnexion
document.addEventListener('DOMContentLoaded', function (event) {
  // Empêche le comportement par défaut du formulaire
  event.preventDefault();

  const logoutBtn = document.getElementById('logoutBtn');

  if (window.location.pathname === '/auth') {
    logoutBtn.style.display = 'none';
  } else {
    logoutBtn.addEventListener('click', function () {
      // Suppression du token JWT du localStorage et redirection
      localStorage.removeItem('jwtToken');
      window.location.replace('/auth');
    });
  }
});

// Événement d'initialisation des Materialize content
document.addEventListener('DOMContentLoaded', function () {
  // Init dropdown
  var sidenav = document.querySelectorAll('.sidenav');
  M.Sidenav.init(sidenav);

  // Init Modal
  var modals = document.querySelectorAll('.modal');
  M.Modal.init(modals);
});

// Événement condition de groupe pour les menus
document.addEventListener('DOMContentLoaded', function () {
  const token = localStorage.getItem('jwtToken');

  if (token) {
    const decoded = jwt_decode(token);
    const userAuthGroupe = decoded.userAuthGroupe;

    const reportingItem = document.getElementById("reportingSidenavSelect");
    const adminItem = document.getElementById("adminSidenavSelect");

    // Cache par défaut
    reportingItem.style.display = 'none';
    adminItem.style.display = 'none';

    if (userAuthGroupe === 'MANAGER' || userAuthGroupe === 'ADMIN') {
      reportingItem.style.display = 'block';
    }

    if (userAuthGroupe === 'ADMIN') {
      adminItem.style.display = 'block';
    }
  }
});

// Fonction pour extraire le numéro de parcours de l'URL
function getNumParcoursFromURL() {
  const urlParams = new URLSearchParams(window.location.search);

  return urlParams.get('numParcours');
}


// Fonction pour extraire le sous-menu de l'URL
function getSubmenuFromURL() {
  const urlParams = new URLSearchParams(window.location.search);

  return urlParams.get('submenu');
}

// Fonction pour vérifier si une valeur est nulle ou non définie
function isNullOrUndefined(value) {
  return value === null || value === undefined;
}

// Fonction pour éviter la duplication du code fetch
async function fetchWithJson(url, method, body = null) {
  const options = {
    method: method,
    headers: { 'Content-Type': 'application/json' },
  };
  if (body) options.body = JSON.stringify(body);

  const response = await fetch(url, options);
  if (!response.ok) throw new Error('Réseau ou erreur serveur');

  return await response.json();
}

// Fonction de load du parcours en session storage
async function loadParcours(numParcours) {
  try {
    const data = await fetchWithJson(`/parcours/read/${numParcours}`, 'GET');

    if (data.valid) {
      sessionStorage.setItem('parcours', JSON.stringify(data.parcours));
    } else {
      sessionStorage.setItem('parcours', null);
      sessionStorage.setItem('admins', JSON.stringify(data.admins));
      console.log("Parcours introuvable");
    }
  } catch (error) {
    console.error("Erreur lors de la récupération des informations parcours :", error);
  }
}

// Fonction générique de toggle
function toggler(btn, div) {
  if (document.getElementById(btn).checked) {
    document.getElementById(div).style.display = 'block';
  } else {
    document.getElementById(div).style.display = 'none';
  }
}

// Fonction de load du parcours en session storage
async function loadContrat(idContrat) {
  try {
    const data = await fetchWithJson(`/contrat/read/id/${idContrat}`, 'GET');

    if (data.valid) {
      sessionStorage.setItem('contrat', JSON.stringify(data.contrat));
    } else {
      sessionStorage.setItem('contrat', null);
      console.log("Contrat introuvable");
    }
  } catch (error) {
    console.error("Erreur lors de la récupération des informations contrat :", error);
  }
}

// ========== Fonctions utilitaires génériques ==========

/**
 * Formatage des dates (ISO vers format français)
 * @param {string} iso - Date au format ISO
 * @param {boolean} withTime - Inclure l'heure (défaut: true)
 * @returns {string} Date formatée (dd/mm/yyyy ou dd/mm/yyyy hh:mm)
 */
function fmtDate(iso, withTime = true) {
  // Si la valeur est null, undefined, ou vide
  if (!iso || (typeof iso === 'string' && iso.trim() === "")) return "NC";
  
  // Convertir en string si ce n'est pas déjà le cas
  const dateStr = String(iso).trim();
  
  // Vérifier les valeurs invalides connues
  if (dateStr === "00/00/0000" || dateStr === "00/00" || dateStr === "null" || dateStr === "undefined") {
    return "NC";
  }
  
  let d;
  
  // Si c'est déjà au format jj/mm/aaaa (format français)
  if (dateStr.includes("/") && dateStr.split("/").length === 3) {
    const parts = dateStr.split("/");
    const day = parseInt(parts[0], 10);
    const month = parseInt(parts[1], 10);
    const year = parseInt(parts[2], 10);
    
    // Vérifier si les valeurs sont valides
    if (isNaN(day) || isNaN(month) || isNaN(year)) {
      return "NC";
    }
    
    // Si le jour ou le mois est 00, considérer comme invalide
    if (day === 0 || month === 0) {
      return "NC";
    }
    
    // Si le mois est invalide
    if (month < 1 || month > 12) {
      return "NC";
    }
    
    // Si l'année est 0000, afficher juste jj/mm (sans l'année)
    if (year === 0) {
      return `${String(day).padStart(2, "0")}/${String(month).padStart(2, "0")}`;
    }
    
    // Si l'année est valide, créer une vraie date et valider
    const monthIndex = month - 1; // Les mois commencent à 0
    d = new Date(year, monthIndex, day);
    // Vérifier si la date est valide (ex: 31/02/2000 serait invalide)
    if (d.getDate() !== day || d.getMonth() !== monthIndex || d.getFullYear() !== year) {
      return "NC";
    }
    
    // Formater la date
    const dd = String(d.getDate()).padStart(2, "0");
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const yyyy = d.getFullYear();
    if (!withTime) return `${dd}/${mm}/${yyyy}`;
    const hh = String(d.getHours()).padStart(2, "0");
    const mi = String(d.getMinutes()).padStart(2, "0");
    return `${dd}/${mm}/${yyyy} ${hh}:${mi}`;
  } 
  // Si c'est au format jj/mm (pour date d'échéance)
  else if (dateStr.includes("/") && dateStr.split("/").length === 2) {
    const parts = dateStr.split("/");
    const day = parseInt(parts[0], 10);
    const month = parseInt(parts[1], 10);
    
    // Pour l'échéance, on retourne juste jj/mm
    if (isNaN(day) || isNaN(month) || day === 0 || month === 0 || month > 12) {
      return "NC";
    }
    return `${String(day).padStart(2, "0")}/${String(month).padStart(2, "0")}`;
  }
  // Sinon, essayer de parser comme date ISO
  else {
    d = new Date(dateStr);
    if (isNaN(d.getTime())) return "NC";
    
    const dd = String(d.getDate()).padStart(2, "0");
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const yyyy = d.getFullYear();
    if (!withTime) return `${dd}/${mm}/${yyyy}`;
    const hh = String(d.getHours()).padStart(2, "0");
    const mi = String(d.getMinutes()).padStart(2, "0");
    return `${dd}/${mm}/${yyyy} ${hh}:${mi}`;
  }
}

/**
 * Crée un élément key-value pour l'affichage de détails
 * @param {string} label - Libellé
 * @param {*} value - Valeur (booléen converti en Oui/Non)
 * @returns {string} HTML formaté
 */
function kv(label, value) {
  const v = (value === true) ? "Oui" : (value === false) ? "Non" : (value ?? "NC");
  return `<div style="display:flex; gap:8px; margin:2px 0;">
            <div style="min-width:220px;"><strong>${label}</strong> :</div>
            <div>${v}</div>
          </div>`;
}

/**
 * Crée une grille à 2 colonnes pour l'affichage de détails
 * @param {string} innerLeft - Contenu colonne gauche
 * @param {string} innerRight - Contenu colonne droite
 * @returns {string} HTML formaté
 */
function gridWrap2cols(innerLeft, innerRight) {
  return `<div style="display:grid;grid-template-columns:repeat(2,minmax(280px,1fr));gap:14px;">${innerLeft}${innerRight}</div>`;
}

/**
 * Fonction debounce pour limiter la fréquence d'exécution d'une fonction
 * Utile pour les recherches en temps réel et éviter les appels API excessifs
 * @param {Function} fn - Fonction à débouncer
 * @param {number} delay - Délai en millisecondes (défaut: 300ms)
 * @returns {Function} Fonction débouncée avec méthode cancel()
 */
function debounce(fn, delay = 300) {
  let t;
  function wrapped(...args) {
    clearTimeout(t);
    t = setTimeout(() => fn(...args), delay);
  }
  wrapped.cancel = () => clearTimeout(t);
  return wrapped;
}

/**
 * Décode un token JWT et retourne le payload
 * @param {string} token - Token JWT à décoder
 * @returns {Object|null} Payload décodé ou null en cas d'erreur
 */
function parseJwt(token) {
  try {
    const base64Url = token.split(".")[1];
    const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
    const jsonPayload = decodeURIComponent(
      atob(base64)
        .split("")
        .map(function (c) {
          return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
        })
        .join("")
    );
    return JSON.parse(jsonPayload);
  } catch (error) {
    console.error("Erreur lors du décodage du token:", error);
    return null;
  }
}

/**
 * Affiche un message d'erreur dans l'élément avec l'ID "error"
 * @param {string} message - Message d'erreur à afficher
 */
function displayError(message) {
  const errorElement = document.getElementById("error");
  if (errorElement) {
    errorElement.textContent = message;
    errorElement.style.display = "block";
  }
}

/**
 * Crée un message formaté avec différents types (info, warn, error, dev)
 * @param {string} type - Type de message : 'info', 'warn', 'error', 'dev'
 * @param {string} title - Titre du message
 * @param {string} description - Description du message (peut contenir du HTML)
 * @returns {string} HTML du message formaté
 */
function createMessageBox(type, title, description) {
  // Protection contre les paramètres invalides
  if (!type || typeof type !== 'string') type = 'info';
  if (!title || typeof title !== 'string') title = 'Message';
  if (!description || typeof description !== 'string') description = '';

  const configs = {
    info: {
      icon: 'fa-info-circle',
      bgColor: '#e3f2fd',
      borderColor: '#2196f3',
      textColor: '#1565c0'
    },
    warn: {
      icon: 'fa-exclamation-triangle',
      bgColor: '#fff3e0',
      borderColor: '#ff9800',
      textColor: '#e65100'
    },
    error: {
      icon: 'fa-times-circle',
      bgColor: '#ffebee',
      borderColor: '#f44336',
      textColor: '#c62828'
    },
    dev: {
      icon: 'fa-tools',
      bgColor: '#fff3cd',
      borderColor: '#ffc107',
      textColor: '#856404'
    }
  };

  const config = configs[type] || configs.info;

  // Échappement basique pour éviter les problèmes (description peut contenir du HTML valide)
  const safeTitle = String(title).replace(/</g, '&lt;').replace(/>/g, '&gt;');
  // Description peut contenir du HTML (comme <br>), donc on ne l'échappe pas complètement
  // mais on s'assure qu'elle est une string
  const safeDescription = String(description);

  return `
    <div style="padding: 20px; text-align: center; background-color: ${config.bgColor}; border: 1px solid ${config.borderColor}; border-radius: 4px; margin: 10px 0; width: 100%; box-sizing: border-box;">
      <p style="color: ${config.textColor}; font-weight: 600; margin: 0 0 10px 0;">
        <i class="fas ${config.icon}" style="margin-right: 8px;"></i>
        ${safeTitle}
      </p>
      <p style="color: ${config.textColor}; margin: 0; font-size: 0.9rem;">
        ${safeDescription}
      </p>
    </div>
  `;
}