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,
      })),
    })),
  }));
};
