import { Event, CalendarDay } from './types';

/**
 * Get the month name for display
 */
export const getMonthName = (date: Date, short: boolean = false): string => {
  const monthNames = [
    'January', 'February', 'March', 'April', 'May', 'June',
    'July', 'August', 'September', 'October', 'November', 'December'
  ];
  
  if (short) {
    return monthNames[date.getMonth()].slice(0, 3);
  }
  
  return monthNames[date.getMonth()];
};

/**
 * Get day names for calendar header
 */
export const getDayNames = (short: boolean = false): string[] => {
  if (short) {
    return ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
  }
  return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
};

/**
 * Check if two dates are on the same day
 */
export const isSameDay = (date1: Date, date2: Date): boolean => {
  return date1.toDateString() === date2.toDateString();
};

/**
 * Check if a date is today
 */
export const isToday = (date: Date): boolean => {
  return isSameDay(date, new Date());
};

/**
 * Generate calendar days grid for a given month
 */
export const generateCalendarDays = (currentDate: Date, events: Event[]): CalendarDay[] => {
  const year = currentDate.getFullYear();
  const month = currentDate.getMonth();
  
  // Get first day of month and number of days
  const firstDay = new Date(year, month, 1);
  const lastDay = new Date(year, month + 1, 0);
  const daysInMonth = lastDay.getDate();
  const startingDayOfWeek = firstDay.getDay();
  
  // Calculate previous month days to show
  const prevMonth = new Date(year, month - 1, 0);
  const daysInPrevMonth = prevMonth.getDate();
  
  const calendarDays: CalendarDay[] = [];
  
  // Calculate total cells needed
  const totalCells = Math.ceil((daysInMonth + startingDayOfWeek) / 7) * 7;
  
  for (let i = 0; i < totalCells; i++) {
    let dayNumber: number;
    let isCurrentMonth: boolean;
    let currentDayDate: Date;
    
    if (i < startingDayOfWeek) {
      // Previous month days
      dayNumber = daysInPrevMonth - (startingDayOfWeek - i - 1);
      isCurrentMonth = false;
      currentDayDate = new Date(year, month - 1, dayNumber);
    } else if (i >= startingDayOfWeek + daysInMonth) {
      // Next month days
      dayNumber = i - startingDayOfWeek - daysInMonth + 1;
      isCurrentMonth = false;
      currentDayDate = new Date(year, month + 1, dayNumber);
    } else {
      // Current month days
      dayNumber = i - startingDayOfWeek + 1;
      isCurrentMonth = true;
      currentDayDate = new Date(year, month, dayNumber);
    }
    
    // Get events for this day
    const dayEvents = events.filter(event => {
      const eventDate = new Date(event.start_time);
      return isSameDay(eventDate, currentDayDate);
    });
    
    calendarDays.push({
      day: dayNumber,
      isCurrentMonth,
      isToday: isToday(currentDayDate),
      date: currentDayDate,
      events: dayEvents
    });
  }
  
  return calendarDays;
};

/**
 * Get events for a specific day
 */
export const getEventsForDay = (events: Event[], date: Date): Event[] => {
  return events.filter(event => {
    const eventDate = new Date(event.start_time);
    return isSameDay(eventDate, date);
  });
};

/**
 * Format date for display
 */
export const formatDate = (date: Date, options?: Intl.DateTimeFormatOptions): string => {
  const defaultOptions: Intl.DateTimeFormatOptions = {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  };
  
  return new Intl.DateTimeFormat('en-US', { ...defaultOptions, ...options }).format(date);
};

/**
 * Format time for display
 */
export const formatTime = (date: Date): string => {
  return new Intl.DateTimeFormat('en-US', {
    hour: 'numeric',
    minute: '2-digit',
    hour12: true
  }).format(date);
};

/**
 * Format date and time for display
 */
export const formatDateTime = (dateString: string) => {
  const date = new Date(dateString);
  return {
    date: formatDate(date),
    time: formatTime(date),
    dayOfWeek: date.toLocaleDateString('en-US', { weekday: 'long' })
  };
};

/**
 * Get category color classes
 */
export const getCategoryColor = (category?: string): string => {
  const colors = {
    music: 'from-purple-500 to-pink-500',
    arts: 'from-blue-500 to-cyan-500',
    community: 'from-green-500 to-emerald-500',
    business: 'from-gray-500 to-slate-500',
    food: 'from-orange-500 to-red-500',
    sports: 'from-indigo-500 to-purple-500',
    default: 'from-gray-400 to-gray-500'
  };
  return colors[category as keyof typeof colors] || colors.default;
};

/**
 * Get category icon
 */
export const getCategoryIcon = (category?: string): string => {
  const icons = {
    music: '🎵',
    arts: '🎨',
    community: '🤝',
    business: '💼',
    food: '🍷',
    sports: '⚽',
    default: '📅'
  };
  return icons[category as keyof typeof icons] || icons.default;
};

/**
 * Group events by date
 */
export const groupEventsByDate = (events: Event[]): Record<string, Event[]> => {
  const grouped: Record<string, Event[]> = {};
  
  events.forEach(event => {
    const dateKey = new Date(event.start_time).toDateString();
    if (!grouped[dateKey]) {
      grouped[dateKey] = [];
    }
    grouped[dateKey].push(event);
  });
  
  return grouped;
};

/**
 * Sort events by start time
 */
export const sortEventsByDate = (events: Event[]): Event[] => {
  return events.sort((a, b) => 
    new Date(a.start_time).getTime() - new Date(b.start_time).getTime()
  );
};

/**
 * Filter future events
 */
export const getFutureEvents = (events: Event[]): Event[] => {
  const today = new Date();
  return events.filter(event => new Date(event.start_time) >= today);
};

/**
 * Get relative date text (Today, Tomorrow, etc.)
 */
export const getRelativeDateText = (date: Date): string => {
  const today = new Date();
  const tomorrow = new Date(today);
  tomorrow.setDate(tomorrow.getDate() + 1);
  
  if (isSameDay(date, today)) {
    return 'Today';
  } else if (isSameDay(date, tomorrow)) {
    return 'Tomorrow';
  } else {
    return formatDate(date, { 
      weekday: 'long', 
      year: 'numeric', 
      month: 'long', 
      day: 'numeric' 
    });
  }
};

/**
 * Truncate text with ellipsis
 */
export const truncateText = (text: string, maxLength: number): string => {
  if (text.length <= maxLength) return text;
  return text.substring(0, maxLength) + '...';
};

/**
 * Get CSS variable value
 */
export const getCSSVariable = (variableName: string): string => {
  if (typeof window === 'undefined') return '';
  return getComputedStyle(document.documentElement).getPropertyValue(variableName).trim();
};