import dayjs from "@calcom/dayjs";
import type { TimeRange } from "@calcom/types/schedule";

// By default starts on Sunday (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday)
export function weekdayDates(weekStart = 0, startDate: Date, length = 6) {
  const tmpStartDate = startDate;
  while (tmpStartDate.getDay() !== weekStart) {
    tmpStartDate.setDate(tmpStartDate.getDate() - 1);
  }
  return {
    startDate: tmpStartDate,
    endDate: new Date(tmpStartDate.getTime() + length * 24 * 60 * 60 * 1000),
  };
}
export type GridCellToDateProps = {
  day: dayjs.Dayjs;
  gridCellIdx: number;
  totalGridCells: number;
  selectionLength: number;
  startHour: number;
  timezone: string;
};

export function gridCellToDateTime({
  day,
  gridCellIdx,
  totalGridCells,
  selectionLength,
  startHour,
  timezone,
}: GridCellToDateProps) {
  // endHour - startHour = selectionLength
  const minutesInSelection = (selectionLength + 1) * 60;
  const minutesPerCell = minutesInSelection / totalGridCells;
  const minutesIntoSelection = minutesPerCell * gridCellIdx;

  // Add startHour since we use StartOfDay for day props. This could be improved by changing the getDaysBetweenDates function
  // To handle the startHour+endHour
  const cellDateTime = dayjs(day)
    .tz(timezone)
    .startOf("day")
    .add(minutesIntoSelection, "minutes")
    .add(startHour, "hours");
  return cellDateTime;
}

export function getDaysBetweenDates(dateFrom: Date, dateTo: Date) {
  const dates = []; // this is as dayjs date
  let startDate = dayjs(dateFrom).hour(0).minute(0).second(0).millisecond(0);

  dates.push(startDate);
  const endDate = dayjs(dateTo).hour(0).minute(0).second(0).millisecond(0);

  while (startDate.isBefore(endDate)) {
    dates.push(startDate.add(1, "day"));
    startDate = startDate.add(1, "day");
  }

  return dates.slice(0, 7);
}

export function getHoursToDisplay(startHour: number, endHour: number, timezone?: string) {
  const dates = []; // this is as dayjs date
  let startDate = dayjs("1970-01-01").tz(timezone).hour(startHour);
  dates.push(startDate);
  const endDate = dayjs("1970-01-01").tz(timezone).hour(endHour);
  while (startDate.isBefore(endDate)) {
    dates.push(startDate.add(1, "hour"));
    startDate = startDate.add(1, "hour");
  }
  return dates;
}

export function mergeOverlappingDateRanges(dateRanges: TimeRange[]) {
  //Sort the date ranges by start date
  dateRanges.sort((a, b) => {
    return a.start.getTime() - b.start.getTime();
  });
  //Create a new array to hold the merged date ranges
  const mergedDateRanges = [];
  //Loop through the date ranges
  for (let i = 0; i < dateRanges.length; i++) {
    //If the merged date ranges array is empty, add the first date range
    if (mergedDateRanges.length === 0) {
      mergedDateRanges.push(dateRanges[i]);
    } else {
      //Get the last date range in the merged date ranges array
      const lastMergedDateRange = mergedDateRanges[mergedDateRanges.length - 1];
      //Get the current date range
      const currentDateRange = dateRanges[i];
      //If the last merged date range overlaps with the current date range, merge them
      if (lastMergedDateRange.end.getTime() >= currentDateRange.start.getTime()) {
        lastMergedDateRange.end = currentDateRange.end;
      } else {
        //Otherwise, add the current date range to the merged date ranges array
        mergedDateRanges.push(currentDateRange);
      }
    }
  }
  return mergedDateRanges;
}

export function calculateHourSizeInPx(
  gridElementRef: HTMLOListElement | null,
  startHour: number,
  endHour: number
) {
  // Gap added at bottom to give calendar some breathing room.
  // I guess we could come up with a better way to do this in the future.
  const gapOnBottom = 50;
  // In case the calendar has for example a header above it. We take a look at the
  // distance the grid is rendered from the top, and subtract that from the height.
  const offsetFromTop = gridElementRef?.getBoundingClientRect().top ?? 65;
  return (window.innerHeight - offsetFromTop - gapOnBottom) / (endHour - startHour);
}
