import {
  BookingOptionGroup,
  BookingOptionPax,
  BookingOptionUnit,
  BookingPackage,
  BookingPackageOption,
  BookingPackageRoom,
  ChangedLine,
  PerBookingPackageOption,
  PerPaxPackageOption,
  PerUnitPackageOption
} from '@qite/tide-client/build/types';

export const updatePackageDetails = (packageDetails: BookingPackage, changedLines: ChangedLine[]): BookingPackage => {
  return {
    ...packageDetails,
    options: packageDetails.options.map((opt) => {
      return {
        ...opt,
        rooms: opt.isSelected ? updateRooms(opt.rooms, changedLines) : opt.rooms,
        groups: opt.isSelected ? updateBookingGroups(opt.groups, changedLines) : opt.groups,
        optionUnits: opt.isSelected ? updateOptionUnits(opt.optionUnits, changedLines) : opt.optionUnits,
        optionPax: opt.isSelected ? updateOptionPax(opt.optionPax, changedLines) : opt.optionPax
      } as BookingPackageOption;
    })
  };
};

// ROOMS
const updateRooms = (rooms: BookingPackageRoom[], changedLines: ChangedLine[]) => {
  return rooms.map((room) => ({
    ...room,
    options: room.options.map((option) => ({
      ...option,
      price: changedLines.find((x) => x.entryLineGuid == option.entryLineGuid)?.price ?? option.price
    }))
  }));
};

// PAX
const updateOptionPax = (pax: BookingOptionPax[], changedLines: ChangedLine[]): BookingOptionPax[] => {
  return pax.map((p) => ({
    ...p,
    groups: updatePaxGroups(p.groups, changedLines)
  }));
};

const updatePaxGroups = (groups: BookingOptionGroup<PerPaxPackageOption>[], changedLines: ChangedLine[]): BookingOptionGroup<PerPaxPackageOption>[] => {
  return groups.map((g) => ({
    ...g,
    options: g.options.map((o) => ({
      ...o,
      groups: updatePaxGroups(o.groups, changedLines),
      line: {
        ...o.line,
        price: changedLines.find((cl) => cl.entryLineGuid === o.line.entryLineGuid)?.price ?? o.line.price
      },
      alternatives: o.alternatives.map((a) => ({
        ...a,
        price: changedLines.find((cl) => cl.entryLineGuid === a.entryLineGuid)?.price ?? a.price
      }))
    }))
  }));
};

// UNITS
const updateOptionUnits = (units: BookingOptionUnit[], changedLines: ChangedLine[]): BookingOptionUnit[] => {
  return units.map((u) => ({
    ...u,
    groups: updateUnitGroups(u.groups, changedLines)
  }));
};

const updateUnitGroups = (groups: BookingOptionGroup<PerUnitPackageOption>[], changedLines: ChangedLine[]): BookingOptionGroup<PerUnitPackageOption>[] => {
  return groups.map((g) => ({
    ...g,
    options: g.options.map((o) => ({
      ...o,
      groups: updateUnitGroups(o.groups, changedLines),
      pax: updateOptionPax(o.pax, changedLines),
      line: {
        ...o.line,
        price: changedLines.find((cl) => cl.entryLineGuid === o.line.entryLineGuid)?.price ?? o.line.price
      },
      alternatives: o.alternatives.map((a) => ({
        ...a,
        price: changedLines.find((cl) => cl.entryLineGuid === a.entryLineGuid)?.price ?? a.price
      }))
    }))
  }));
};

// BOOKING
const updateBookingGroups = (
  groups: BookingOptionGroup<PerBookingPackageOption>[],
  changedLines: ChangedLine[]
): BookingOptionGroup<PerBookingPackageOption>[] => {
  return groups.map((g) => ({
    ...g,
    options: g.options.map((o) => ({
      ...o,
      groups: updateBookingGroups(o.groups, changedLines),
      units: updateOptionUnits(o.units, changedLines),
      pax: updateOptionPax(o.pax, changedLines),
      line: {
        ...o.line,
        price: changedLines.find((cl) => cl.entryLineGuid === o.line.entryLineGuid)?.price ?? o.line.price
      },
      alternatives: o.alternatives.map((a) => ({
        ...a,
        price: changedLines.find((cl) => cl.entryLineGuid === a.entryLineGuid)?.price ?? a.price
      }))
    }))
  }));
};
