// js/utils/DateUtils.js

/**
 * Date and time utility functions
 */
export class DateUtils {
  /**
   * Get start of week for a given date
   * @param {Date} date 
   * @param {number} firstDayOfWeek - 0 = Sunday, 1 = Monday
   * @returns {Date}
   */
  static getWeekStart(date, firstDayOfWeek = 1) {
    const d = new Date(date);
    const day = d.getDay();
    const diff = (day - firstDayOfWeek + 7) % 7;
    d.setDate(d.getDate() - diff);
    d.setHours(0, 0, 0, 0);
    return d;
  }

  /**
   * Get end of week for a given date
   * @param {Date} date 
   * @param {number} firstDayOfWeek 
   * @returns {Date}
   */
  static getWeekEnd(date, firstDayOfWeek = 1) {
    const start = this.getWeekStart(date, firstDayOfWeek);
    const end = new Date(start);
    end.setDate(end.getDate() + 6);
    end.setHours(23, 59, 59, 999);
    return end;
  }

  /**
   * Format date to YYYY-MM-DD
   * @param {Date} date 
   * @returns {string}
   */
  static formatDate(date) {
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
  }

  /**
   * Format time to HH:MM
   * @param {Date} date 
   * @returns {string}
   */
  static formatTime(date) {
    return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
  }

  /**
   * Format time to 12-hour format
   * @param {Date} date 
   * @returns {string}
   */
  static formatTime12(date) {
    const hours = date.getHours();
    const minutes = date.getMinutes();
    const period = hours >= 12 ? 'PM' : 'AM';
    const displayHours = hours % 12 || 12;
    
    return `${displayHours}:${String(minutes).padStart(2, '0')} ${period}`;
  }

  /**
   * Convert minutes since midnight to time string
   * @param {number} minutes 
   * @returns {string}
   */
  static minutesToTime(minutes) {
    const hours = Math.floor(minutes / 60);
    const mins = minutes % 60;
    const period = hours >= 12 ? 'PM' : 'AM';
    const displayHours = hours % 12 || 12;
    
    return `${displayHours}:${String(mins).padStart(2, '0')} ${period}`;
  }

  /**
   * Convert time string to minutes since midnight
   * @param {string} timeStr - Format: "HH:MM" or "HH:MM:SS"
   * @returns {number}
   */
  static timeToMinutes(timeStr) {
    const [time] = timeStr.split('T').pop().split('.');
    const [hours, minutes] = time.split(':').map(Number);
    return hours * 60 + minutes;
  }

  /**
   * Get minutes since start of day
   * @param {Date|string} date 
   * @returns {number}
   */
  static getMinutesSinceMidnight(date) {
    const d = typeof date === 'string' ? new Date(date) : date;
    return d.getHours() * 60 + d.getMinutes();
  }

  /**
   * Calculate duration in minutes between two dates
   * @param {Date|string} start 
   * @param {Date|string} end 
   * @returns {number}
   */
  static getDurationMinutes(start, end) {
    const startDate = typeof start === 'string' ? new Date(start) : start;
    const endDate = typeof end === 'string' ? new Date(end) : end;
    return Math.floor((endDate - startDate) / 60000);
  }

  /**
   * Check if date is today
   * @param {Date} date 
   * @returns {boolean}
   */
  static isToday(date) {
    const today = new Date();
    return date.toDateString() === today.toDateString();
  }

  /**
   * Check if two dates are on the same day
   * @param {Date} date1 
   * @param {Date} date2 
   * @returns {boolean}
   */
  static isSameDay(date1, date2) {
    return date1.toDateString() === date2.toDateString();
  }

  /**
   * Check if event spans multiple days
   * @param {Date|string} start 
   * @param {Date|string} end 
   * @returns {boolean}
   */
  static isMultiDay(start, end) {
    const startDate = typeof start === 'string' ? new Date(start) : start;
    const endDate = typeof end === 'string' ? new Date(end) : end;
    return !this.isSameDay(startDate, endDate);
  }

  /**
   * Get day name
   * @param {Date} date 
   * @param {string} format - 'short' or 'long'
   * @returns {string}
   */
  static getDayName(date, format = 'short') {
    const days = {
      short: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
      long: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
    };
    return days[format][date.getDay()];
  }

  /**
   * Add days to date
   * @param {Date} date 
   * @param {number} days 
   * @returns {Date}
   */
  static addDays(date, days) {
    const result = new Date(date);
    result.setDate(result.getDate() + days);
    return result;
  }

  /**
   * Add minutes to date
   * @param {Date} date 
   * @param {number} minutes 
   * @returns {Date}
   */
  static addMinutes(date, minutes) {
    const result = new Date(date);
    result.setMinutes(result.getMinutes() + minutes);
    return result;
  }

  /**
   * Snap time to nearest interval
   * @param {Date} date 
   * @param {number} intervalMinutes 
   * @returns {Date}
   */
  static snapToInterval(date, intervalMinutes) {
    const minutes = date.getMinutes();
    const snappedMinutes = Math.round(minutes / intervalMinutes) * intervalMinutes;
    const result = new Date(date);
    result.setMinutes(snappedMinutes);
    result.setSeconds(0);
    result.setMilliseconds(0);
    return result;
  }

  /**
   * Get current time in minutes since day start
   * @param {number} dayStartHour 
   * @returns {number}
   */
  static getCurrentTimeMinutes(dayStartHour = 0) {
    const now = new Date();
    const minutesSinceMidnight = now.getHours() * 60 + now.getMinutes();
    return minutesSinceMidnight - (dayStartHour * 60);
  }

  /**
   * Format duration to human readable string
   * @param {number} minutes 
   * @returns {string}
   */
  static formatDuration(minutes) {
    if (minutes < 60) {
      return `${minutes} min`;
    }
    
    const hours = Math.floor(minutes / 60);
    const mins = minutes % 60;
    
    if (mins === 0) {
      return `${hours} hour${hours > 1 ? 's' : ''}`;
    }
    
    return `${hours} hour${hours > 1 ? 's' : ''} ${mins} min`;
  }
}