import { createAsyncThunk } from '@reduxjs/toolkit';

interface DateRangeInput {
  takenDates: Date[] | null;
  checkinDate: Date;
  checkoutDate: Date;
  checkinChanged?: boolean;   // ← Optional: tells if checkin was changed
  checkoutChanged?: boolean;
}

interface DateRangeOutput {
  startDate: string; // ISO strings for Redux serializability
  endDate: string;
}

// Calculate number of full days between two dates
const daysBetween = (a: Date, b: Date): number =>
  Math.floor((b.getTime() - a.getTime()) / (1000 * 60 * 60 * 24));

// Check if a date range is fully available
const isRangeAvailable = (start: Date, days: number, takenSet: Set<string>): boolean => {
  for (let i = 0; i < days; i++) {
    const d = new Date(start);
    d.setDate(start.getDate() + i);
    if (takenSet.has(d.toDateString())) return false;
  }
  return true;
};

export const checkOrFindAvailableDateRange = createAsyncThunk<
  DateRangeOutput,
  DateRangeInput
>(
  'dateRange/checkOrFindAvailableDateRange',
  async ({ takenDates, checkinDate, checkoutDate, checkinChanged, checkoutChanged }) => {
    let start = new Date(checkinDate);
    let end = new Date(checkoutDate);

    // 🛠️ Fix case: If checkout changed, and is now before checkin, force 7-day range from checkin
    if (checkoutChanged && end < start) {
      start = new Date(end);
      end.setDate(start.getDate() + 6); // Set to 7-day range
    }


    const takenSet = new Set(takenDates?.map(d => d.toDateString()));
    const totalDays = daysBetween(start, end);

    // ✅ If range is valid and available
    if (totalDays >= 6 && isRangeAvailable(start, totalDays + 1, takenSet)) {
      return {
        startDate: start.toISOString(),
        endDate: end.toISOString(),
      };
    }

    // ❌ Not valid — find next available 7-day window
    let current = new Date(start);

    while (true) {
      if (isRangeAvailable(current, 7, takenSet)) {
        const nextEnd = new Date(current);
        nextEnd.setDate(current.getDate() + 6);
        return {
          startDate: current.toISOString(),
          endDate: nextEnd.toISOString(),
        };
      }
      current.setDate(current.getDate() + 1);
    }
  }
);

