import { isSameDay, startOfDay, endOfDay } from 'date-fns';

/**
 * Calcule la position et les dimensions d'un événement dans le calendrier
 * @param {Object} event - L'événement à positionner
 * @param {Array<Object>} overlappingEvents - Liste des événements qui se chevauchent
 * @returns {Object} Position et dimensions de l'événement (top, height, position, width, left)
 */
export const calculateEventPosition = (event, overlappingEvents) => {
  const start = new Date(event.start);
  const end = new Date(event.end);
  const startHour = start.getHours() + start.getMinutes() / 60;
  const endHour = end.getHours() + end.getMinutes() / 60;
  const duration = endHour - startHour;

  const sortedEvents = overlappingEvents.sort(
    (a, b) => new Date(a.start) - new Date(b.start)
  );
  const index = sortedEvents.findIndex((e) => e.id === event.id);

  return {
    top: `${startHour * 5}rem`,
    height: `${duration * 5}rem`,
    position: 'absolute',
    width: `${95 / overlappingEvents.length}%`,
    left: `${(index * 95) / overlappingEvents.length}%`,
  };
};

/**
 * Récupère tous les événements qui se chevauchent avec l'événement donné
 * @param {Object} event - L'événement de référence
 * @param {Array<Object>} dayEvents - Liste des événements de la journée
 * @returns {Array<Object>} Liste des événements qui se chevauchent
 */
export const getOverlappingEvents = (event, dayEvents) => {
  return dayEvents.filter((otherEvent) => {
    if (event.id === otherEvent.id) return false;
    const eventStart = new Date(event.start);
    const eventEnd = new Date(event.end);
    const otherStart = new Date(otherEvent.start);
    const otherEnd = new Date(otherEvent.end);
    return eventStart < otherEnd && eventEnd > otherStart;
  });
};

/**
 * Filtre les événements pour une date spécifique
 * @param {Date} date - La date pour laquelle filtrer les événements
 * @param {Array<Object>} [events=[]] - Liste des événements à filtrer
 * @returns {Array<Object>} Liste des événements pour la date donnée
 */
export const getEventsForDate = (date, events = []) => {
  return events.filter((event) => {
    const eventDate = new Date(event.start);
    return (
      eventDate.getDate() === date.getDate() &&
      eventDate.getMonth() === date.getMonth() &&
      eventDate.getFullYear() === date.getFullYear()
    );
  });
};

/**
 * Compte le nombre d'événements pour un mois donné
 * @param {Date} month - Le mois pour lequel compter les événements
 * @param {Array<Object>} [events=[]] - Liste des événements à compter
 * @returns {number} Nombre d'événements dans le mois
 */
export const getMonthEventCount = (month, events = []) => {
  return events.filter((event) => {
    const eventDate = new Date(event.start);
    return (
      eventDate.getMonth() === month.getMonth() &&
      eventDate.getFullYear() === month.getFullYear()
    );
  }).length;
};

/**
 * Récupère tous les événements d'une semaine donnée
 * @param {Date} day - Un jour de la semaine
 * @param {Array<Object>} events - Liste des événements à filtrer
 * @returns {Array<Object>} Liste des événements de la semaine
 */
export const getWeekEvents = (day, events) => {
  const start = startOfDay(day);
  const end = endOfDay(day);

  return events?.filter((event) => {
    const eventStart = new Date(event.start);
    const eventEnd = new Date(event.end);

    // Un événement est dans la journée si :
    // - il commence pendant la journée
    // - il finit pendant la journée
    // - il englobe toute la journée
    return (
      (eventStart >= start && eventStart <= end) || // commence dans la journée
      (eventEnd >= start && eventEnd <= end) || // finit dans la journée
      (eventStart <= start && eventEnd >= end)
    ); // englobe la journée
  });
};

/**
 * Filtre les événements en excluant ceux des emplois du temps masqués
 * @param {Array<Object>} events - Liste de tous les événements
 * @param {Array<string|number>} hiddenSchedules - IDs des emplois du temps masqués
 * @returns {Array<Object>} Liste des événements filtrés
 */
export const filterEventsByVisibleSchedules = (events, hiddenSchedules) => {
  return events.filter((event) => !hiddenSchedules.includes(event.planning));
};
