import React, { useContext, useEffect, useState } from 'react';

import { StoreProduct } from '@medusajs/types';

import { getAvailableTimeSlotsForDisplay } from '~/lib/services/connected-online.service';

import { BookingContext, Location, TimeSlot } from './booking.context';

export function useBooking() {
  const context = useContext(BookingContext);

  if (!context) {
    throw new Error('useBooking must be used within a BookingProvider.');
  }

  return context;
}

export const BookingProvider: React.FC<{
  children: React.ReactElement;
  category: { products: StoreProduct[] };
  service?: StoreProduct;
}> = ({ children, category, service }) => {
  const [selectedService, setSelectedService] = useState<StoreProduct | null>(
    (service ?? category?.products?.[0]) || null,
  );
  const [selectedLocationId, setSelectedLocationId] = useState<number | null>(
    null,
  );
  const [selectedDate, setSelectedDate] = useState<Date>();
  const [timeSlots, setTimeSlots] = useState<TimeSlot[] | null>(null);
  const [locations, setLocations] = useState<Location[] | null>(null);
  const [isLoadingTimeSlots, setIsLoadingTimeSlots] = useState(false);

  useEffect(() => {
    const metadataServiceIds = selectedService?.metadata?.serviceIds as string;
    if (metadataServiceIds) {
      const json = JSON.parse(metadataServiceIds);
      if (Array.isArray(json)) {
        updateTimeSlots(json);
      }
    }
  }, [selectedService, selectedLocationId]);

  const updateTimeSlots = async (serviceIds: number[]) => {
    setIsLoadingTimeSlots(true);
    try {
      const response = await getAvailableTimeSlotsForDisplay(
        serviceIds,
        selectedLocationId,
      );
      setTimeSlots(response.timeSlots);
      setLocations(response.locations);
    } catch (error) {
      setTimeSlots(null);
    } finally {
      setIsLoadingTimeSlots(false);
    }
  };

  return (
    <BookingContext.Provider
      value={{
        timeSlots,
        locations,
        selectedService,
        selectedLocationId,
        setSelectedLocationId,
        selectedDate,
        isLoadingTimeSlots,
        setSelectedService,
        updateTimeSlots,
        setSelectedDate,
      }}
    >
      {children}
    </BookingContext.Provider>
  );
};
