class TimeManager {
  static ALLOWED_RANGES = ['today', 'yesterday', 'last2days', 'last7days', 'last30days', 'last90days', 
                          'previous7days', 'previous30days', 'previous90days'];

  constructor(timezone = 'America/New_York', dayStartsAt = 1) {
    this.timezone = timezone;
    this.dayStartsAt = dayStartsAt;
  }

  getDayBounds(date) {
    try {
      const now = new Date();
      const targetDate = new Date(date);
      
      // For today
      if (
        targetDate.getUTCFullYear() === now.getUTCFullYear() &&
        targetDate.getUTCMonth() === now.getUTCMonth() &&
        targetDate.getUTCDate() === now.getUTCDate()
      ) {
        // If current time is before day start (1 AM ET / 6 AM UTC), 
        // use previous day's start until now
        const todayStart = new Date(Date.UTC(
          now.getUTCFullYear(),
          now.getUTCMonth(),
          now.getUTCDate(),
          this.dayStartsAt + 5,
          0,
          0,
          0
        ));
  
        if (now < todayStart) {
          const yesterdayStart = new Date(todayStart);
          yesterdayStart.setUTCDate(yesterdayStart.getUTCDate() - 1);
          return { start: yesterdayStart, end: now };
        }
  
        return { start: todayStart, end: now };
      }
  
      // For past days, use full 24-hour period
      const normalizedDate = new Date(Date.UTC(
        targetDate.getUTCFullYear(),
        targetDate.getUTCMonth(),
        targetDate.getUTCDate()
      ));

      const dayStart = new Date(normalizedDate);
      dayStart.setUTCHours(this.dayStartsAt + 5, 0, 0, 0);

      const dayEnd = new Date(dayStart);
      dayEnd.setUTCDate(dayEnd.getUTCDate() + 1);

      return { start: dayStart, end: dayEnd };
    } catch (error) {
      console.error('Error in getDayBounds:', error);
      throw new Error(`Failed to calculate day bounds: ${error.message}`);
    }
  }

  getDateRange(period) {
    try {
      const now = new Date();
      const todayBounds = this.getDayBounds(now);
      const end = new Date();

      switch (period) {
        case 'today':
          return {
            start: todayBounds.start,
            end
          };
        case 'yesterday': {
          const yesterday = new Date(now);
          yesterday.setDate(yesterday.getDate() - 1);
          return this.getDayBounds(yesterday);
        }
        case 'last2days': {
          const twoDaysAgo = new Date(now);
          twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
          return this.getDayBounds(twoDaysAgo);
        }
        case 'last7days': {
          const start = new Date(now);
          start.setDate(start.getDate() - 6);
          return {
            start: this.getDayBounds(start).start,
            end
          };
        }
        case 'previous7days': {
          const end = new Date(now);
          end.setDate(end.getDate() - 7);
          const start = new Date(end);
          start.setDate(start.getDate() - 6);
          return {
            start: this.getDayBounds(start).start,
            end: this.getDayBounds(end).end
          };
        }
        case 'last30days': {
          const start = new Date(now);
          start.setDate(start.getDate() - 29);
          return {
            start: this.getDayBounds(start).start,
            end
          };
        }
        case 'previous30days': {
          const end = new Date(now);
          end.setDate(end.getDate() - 30);
          const start = new Date(end);
          start.setDate(start.getDate() - 29);
          return {
            start: this.getDayBounds(start).start,
            end: this.getDayBounds(end).end
          };
        }
        case 'last90days': {
          const start = new Date(now);
          start.setDate(start.getDate() - 89);
          return {
            start: this.getDayBounds(start).start,
            end
          };
        }
        case 'previous90days': {
          const end = new Date(now);
          end.setDate(end.getDate() - 90);
          const start = new Date(end);
          start.setDate(start.getDate() - 89);
          return {
            start: this.getDayBounds(start).start,
            end: this.getDayBounds(end).end
          };
        }
        default:
          throw new Error(`Unsupported time period: ${period}`);
      }
    } catch (error) {
      console.error('Error in getDateRange:', error);
      throw error;
    }
  }

  getPreviousPeriod(period) {
    try {
      const now = new Date();
      
      switch (period) {
        case 'today': 
          return 'yesterday';
        case 'yesterday': {
          // Return bounds for 2 days ago
          const twoDaysAgo = new Date(now);
          twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
          return this.getDayBounds(twoDaysAgo);
        }
        case 'last7days': {
          // Return bounds for previous 7 days
          const end = new Date(now);
          end.setDate(end.getDate() - 7);
          const start = new Date(end);
          start.setDate(start.getDate() - 7);
          return {
            start: this.getDayBounds(start).start,
            end: this.getDayBounds(end).end
          };
        }
        case 'last30days': {
          const end = new Date(now);
          end.setDate(end.getDate() - 30);
          const start = new Date(end);
          start.setDate(start.getDate() - 30);
          return {
            start: this.getDayBounds(start).start,
            end: this.getDayBounds(end).end
          };
        }
        case 'last90days': {
          const end = new Date(now);
          end.setDate(end.getDate() - 90);
          const start = new Date(end);
          start.setDate(start.getDate() - 90);
          return {
            start: this.getDayBounds(start).start,
            end: this.getDayBounds(end).end
          };
        }
        default:
          throw new Error(`Unsupported time period: ${period}`);
      }
    } catch (error) {
      console.error('Error in getPreviousPeriod:', error);
      throw error;
    }
  }

  getCurrentBusinessDayEnd() {
    try {
      const now = new Date();
      const todayBounds = this.getDayBounds(now);
      
      // If current time is before day start (1 AM ET / 6 AM UTC),
      // then we're still in yesterday's business day
      const todayStart = new Date(Date.UTC(
        now.getUTCFullYear(),
        now.getUTCMonth(),
        now.getUTCDate(),
        this.dayStartsAt + 5,
        0,
        0,
        0
      ));

      if (now < todayStart) {
        const yesterdayBounds = this.getDayBounds(new Date(now.getTime() - 24 * 60 * 60 * 1000));
        return yesterdayBounds.end;
      }

      // Return the earlier of current time or today's end
      return now < todayBounds.end ? now : todayBounds.end;
    } catch (error) {
      console.error('Error in getCurrentBusinessDayEnd:', error);
      return new Date();
    }
  }

  isValidTimeRange(timeRange) {
    return TimeManager.ALLOWED_RANGES.includes(timeRange);
  }

  isToday(date) {
    const now = new Date();
    const targetDate = new Date(date);
    return (
      targetDate.getUTCFullYear() === now.getUTCFullYear() &&
      targetDate.getUTCMonth() === now.getUTCMonth() &&
      targetDate.getUTCDate() === now.getUTCDate()
    );
  }

  formatDate(date) {
    try {
      return date.toLocaleString('en-US', {
        timeZone: this.timezone,
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      });
    } catch (error) {
      console.error('Error formatting date:', error);
      return date.toISOString();
    }
  }
}

export const createTimeManager = (timezone, dayStartsAt) => new TimeManager(timezone, dayStartsAt); 