// src/utils/dateUtils.ts
import { parseISO, format, isValid, differenceInDays } from 'date-fns';

/**
 * Calculates the current year and a simplified week number.
 *
 * Note: This is a simple calculation where week 1 starts on January 1st.
 * For true ISO 8601 week numbers (where week 1 is the first week with a Thursday),
 * a dedicated library like `date-fns` (`getISOWeek` and `getISOWeekYear`) is recommended.
 *
 * @param date The date to calculate the simple week for. Defaults to the current date.
 * @returns An object containing the year and week number.
 */
export function calculateSimpleWeekAndYear(date: Date = new Date()): { year: number; week: number } {
  const year = date.getFullYear();
  // Use UTC dates to calculate the difference in days.
  // This avoids issues with Daylight Saving Time (DST) where a day might have 23 or 25 hours,
  // which can cause the millisecond-based calculation to be slightly off (e.g., 149.96 days).
  const startOfYear = Date.UTC(year, 0, 1);
  const current = Date.UTC(year, date.getMonth(), date.getDate());
  const msPerDay = 1000 * 60 * 60 * 24;
  const dayOfYear = (current - startOfYear) / msPerDay;
  // Divide by 7, take the floor to get the zero-based week, and add 1 for a one-based week number.
  const week = Math.floor(dayOfYear / 7) + 1;

  return { year, week };
}

export const formatShortDate = (dateString: string | null | undefined): string | null => {
  if (!dateString) return null;
  // Using `parseISO` from date-fns is more reliable than `new Date()` for YYYY-MM-DD strings.
  // It correctly interprets the string as a local date, avoiding timezone-related "off-by-one" errors.
  const date = parseISO(dateString);
  if (isValid(date)) {
    return format(date, 'MMM d');
  }
  return null;
};

export const calculateDaysBetween = (
  startDate: string | Date | null | undefined,
  endDate: string | Date | null | undefined,
): number | null => {
  if (!startDate || !endDate) return null;

  const start = typeof startDate === 'string' ? parseISO(startDate) : startDate;
  const end = typeof endDate === 'string' ? parseISO(endDate) : endDate;

  if (!isValid(start) || !isValid(end)) return null;

  return differenceInDays(end, start);
};

interface DateRangeOptions {
  verbose?: boolean;
}

export const formatDateRange = (
  startDate: string | null | undefined,
  endDate: string | null | undefined,
  options?: DateRangeOptions,
): string | null => {
  if (!options?.verbose) {
    const start = formatShortDate(startDate);
    const end = formatShortDate(endDate);

    if (start && end) {
      return start === end ? start : `${start} - ${end}`;
    }
    return start || end || null;
  }

  // Verbose format logic
  const dateFormat = 'MMMM d, yyyy';
  const formatFn = (dateStr: string | null | undefined) => {
    if (!dateStr) return null;
    const date = parseISO(dateStr);
    return isValid(date) ? format(date, dateFormat) : null;
  };

  const start = formatFn(startDate);
  const end = formatFn(endDate);

  if (start && end) {
    return start === end ? `Valid on ${start}` : `Deals valid from ${start} to ${end}`;
  }
  if (start) return `Deals start ${start}`;
  if (end) return `Deals end ${end}`;
  return null;
};

/**
 * Returns the current date as an ISO 8601 string (YYYY-MM-DD).
 * Useful for getting "today" without the time component.
 */
export const getCurrentDateISOString = (): string => {
  return format(new Date(), 'yyyy-MM-dd');
};

export { calculateSimpleWeekAndYear as getSimpleWeekAndYear };
