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 =
            (option.isOnRequest && availability.count == 99) || // Tide sets count to 99 if an option falls back to on request.
            (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;
        }
      })
    };
  });
};
