import { BookingPackageAvailability, BookingPackageRoom } from "@qite/tide-client/build/types";
import { AccommodationContent, RegimeContent, SelectableRoom, SelectableRoomAccommodation } from "../../types";

export const buildSelectableRooms = (
  packageRooms: BookingPackageRoom[],
  accommodations: AccommodationContent[] | undefined,
  regimes: RegimeContent[] | undefined,
  accommodationViews: { [key: string]: string } | undefined
) => {
  return packageRooms.map(x => {
    const selectedOption = x.options.find(x => x.isSelected)!;
    const alternativeOptions = x.options
      .filter(x => x.accommodationCode !== selectedOption.accommodationCode && !x.isLocked)
      .sort((a, b) => a.price - b.price);

    const alternativeAccommodations: SelectableRoomAccommodation[] = [];
    alternativeOptions.forEach(x => {
      const alternativeAccommodation = alternativeAccommodations.find(y => y.code === x.accommodationCode);

      if (alternativeAccommodation) {
        const regime = regimes?.find(y => y.code === x.regimeCode);

        alternativeAccommodation.regimes.push({
          code: x.regimeCode,
          title: regime?.title ?? x.regimeName,
          price: x.price
        });
      } else {
        const accommodation = accommodations?.find(y => y.code === x.accommodationCode);
        const regime = regimes?.find(y => y.code === x.regimeCode);

        alternativeAccommodations.push({
          code: x.accommodationCode,
          regimeCode: x.regimeCode,
          from: x.from,
          to: x.to,
          price: x.price,
          regimes: [{
            code: x.regimeCode,
            title: regime?.title ?? x.regimeName,
            price: x.price
          }],
          title: accommodation?.title ?? x.accommodationName,
          image: accommodation?.imageUrl,
          usps: accommodation?.usps ?? [],
          description: accommodation?.description,
          viewHtml: accommodationViews?.[x.accommodationCode]
        })
      }
    });

    const accommodation = accommodations?.find(y => y.code === selectedOption.accommodationCode);

    return {
      index: x.index,
      selected: {
        code: selectedOption.accommodationCode,
        regimeCode: selectedOption.regimeCode,
        price: selectedOption.price,
        from: selectedOption.from,
        to: selectedOption.to,
        regimes: x.options
          .filter(x => x.accommodationCode === selectedOption.accommodationCode)
          .sort((a, b) => a.price - b.price)
          .map(o => {
            const regime = regimes?.find(y => y.code === o.regimeCode);

            return {
              code: o.regimeCode,
              title: regime?.title ?? o.regimeName,
              price: o.price
            }
          }),
        title: accommodation?.title ?? selectedOption.accommodationName,
        image: accommodation?.imageUrl,
        usps: accommodation?.usps ?? [],
        description: accommodation?.description,
        viewHtml: accommodationViews?.[selectedOption.accommodationCode]
      },
      showAlternatives: false,
      alternatives: alternativeAccommodations
    } as SelectableRoom;
  });
}

export const updatePackageRooms = (rooms: BookingPackageRoom[], index: number, accommodationCode: string, regimeCode: string | null, availabilities: BookingPackageAvailability[]) => {
  const updatedRooms = rooms.map((room) => {
    if (room.index !== index) return room;

    return {
      ...room,
      options: room.options.map((option) => {
        return {
          ...option,
          isSelected:
            option.accommodationCode === accommodationCode &&
            (option.regimeCode === regimeCode || (option.regimeCode === null && regimeCode === '')),
        };
      }),
    };
  });

  const selectedAccommodations = new Map<string, number>();
  updatedRooms.map(x => x.options.find(x => x.isSelected)!).forEach(x => {
    if (selectedAccommodations.has(x.accommodationCode)) {
      selectedAccommodations.set(x.accommodationCode, selectedAccommodations.get(x.accommodationCode)! + 1);
    } else {
      selectedAccommodations.set(x.accommodationCode, 1);
    }
  });

  const accoCounter = availabilities.map(x => ({ code: x.code, count: x.count }));
  return updatedRooms.map(room => {
    const selectedOption = room.options.find(x => x.isSelected)!;

    return {
      ...room,
      options: room.options.map(option => {
        const isCurrentOption = selectedOption.accommodationCode === option.accommodationCode;
        const usedCount = selectedAccommodations.get(option.accommodationCode) ?? 0;
        const availability = availabilities.find(x => x.code === option.accommodationCode);

        if (availability) {
          const accoCount = accoCounter.find(x => x.code === option.accommodationCode)!;

          const roomsLeft = availability.count - usedCount;
          let isOnRequest = isCurrentOption
            ? accoCount.count < 0 && (availability?.onRequestPossible ?? false)
            : roomsLeft < 0 && (availability?.onRequestPossible ?? false);
          if (isCurrentOption) accoCount.count--;

          return {
            ...option,
            isLocked: !option.isSelected && !isOnRequest && roomsLeft < 0 && !availability.isExternal,
            isOnRequest: isOnRequest
          };
        } else {
          return option;
        }
      })
    }
  });
}