"use strict";
require("./index-Br7AzmuA.cjs");
const dayjs = require("dayjs");
const index = require("./i18n-HHdcQbuJ.cjs");
const async = require("async");
const index_js = require("react-awesome-query-builder/lib/index.js");
const ooo = require("./ooo-peCOvX-J.cjs");
const membership = require("./membership-tWJEReqw.cjs");
const reactAwesomeQueryBuilder = require("react-awesome-query-builder");
const jsonLogic = require("json-logic-js");
const getLuckyUser = require("./getLuckyUser-1CHObXQ9.cjs");
const credential = require("./credential-xoMnaX4v.cjs");
const getOrgIdFromMemberOrTeamId = require("./getOrgIdFromMemberOrTeamId-JRmNtANe.cjs");
const utils = require("./utils-rQyGQqTb.cjs");
const ioctopus = require("@evyweb/ioctopus");
const user = require("./user-xjV81VA_.cjs");
function isEventTypeLoggingEnabled({
  eventTypeId,
  usernameOrTeamName
}) {
  const usernameOrTeamnamesList = usernameOrTeamName instanceof Array ? usernameOrTeamName : [usernameOrTeamName];
  const bookingLoggingEventIds = process.env.BOOKING_LOGGING_EVENT_IDS || "";
  const isEnabled = bookingLoggingEventIds.split(",").some((id) => {
    if (Number(id.trim()) === eventTypeId) {
      return true;
    }
  });
  if (isEnabled) {
    return true;
  }
  const bookingLoggingUsername = process.env.BOOKING_LOGGING_USER_OR_TEAM_NAME || "";
  return bookingLoggingUsername.split(",").some((u) => {
    return usernameOrTeamnamesList.some((foundUsername) => foundUsername === u.trim());
  });
}
class PrismaAttributeToUserRepository {
  static async createManySkipDuplicates(data) {
    return await index.prisma.attributeToUser.createMany({ data, skipDuplicates: true });
  }
  static async deleteMany(where) {
    if (Object.keys(where).length === 0) {
      throw new Error("Empty where clause provided to deleteMany. Potential data loss risk.");
    }
    return await index.prisma.attributeToUser.deleteMany({ where });
  }
  static async findManyIncludeAttribute(where) {
    return await index.prisma.attributeToUser.findMany({
      where,
      include: {
        attributeOption: {
          select: {
            attribute: true,
            value: true,
            slug: true
          }
        }
      }
    });
  }
  static async findManyByOrgMembershipIds({ orgMembershipIds }) {
    if (!orgMembershipIds.length) {
      return [];
    }
    const attributesAssignedToTeamMembers = await index.prisma.attributeToUser.findMany({
      where: {
        memberId: {
          in: orgMembershipIds
        }
      }
    });
    return attributesAssignedToTeamMembers;
  }
}
function _prepareAssignmentData({
  assignmentsForTheTeam,
  attributesOfTheOrg
}) {
  const teamMembersThatHaveOptionAssigned = assignmentsForTheTeam.reduce((acc, attributeToUser) => {
    const userId = attributeToUser.userId;
    const attributeOption = attributeToUser.attributeOption;
    const attribute = attributeToUser.attribute;
    if (!acc[userId]) {
      acc[userId] = { userId, attributes: {} };
    }
    const attributes = acc[userId].attributes;
    const currentAttributeOptionValue = attributes[attribute.id]?.attributeOption;
    const newAttributeOptionValue = {
      isGroup: attributeOption.isGroup,
      value: attributeOption.value,
      contains: tranformContains({ contains: attributeOption.contains, attribute })
    };
    if (currentAttributeOptionValue instanceof Array) {
      attributes[attribute.id].attributeOption = [...currentAttributeOptionValue, newAttributeOptionValue];
    } else if (currentAttributeOptionValue) {
      attributes[attribute.id].attributeOption = [
        currentAttributeOptionValue,
        {
          isGroup: attributeOption.isGroup,
          value: attributeOption.value,
          contains: tranformContains({ contains: attributeOption.contains, attribute })
        }
      ];
    } else {
      attributes[attribute.id] = {
        type: attribute.type,
        attributeOption: newAttributeOptionValue
      };
    }
    return acc;
  }, {});
  return Object.values(teamMembersThatHaveOptionAssigned);
  function tranformContains({
    contains,
    attribute
  }) {
    return contains.map((optionId) => {
      const allOptions = attributesOfTheOrg.find((_attribute) => _attribute.id === attribute.id)?.options;
      const option = allOptions?.find((option2) => option2.id === optionId);
      if (!option) {
        console.error(
          `Enriching "contains" for attribute ${attribute.name}: Option with id ${optionId} not found. Looked up in ${JSON.stringify(allOptions)}`
        );
        return null;
      }
      return {
        id: option.id,
        value: option.value,
        slug: option.slug
      };
    }).filter((option) => option !== null);
  }
}
function _getAttributeFromAttributeOption({
  allAttributesOfTheOrg,
  attributeOptionId
}) {
  return allAttributesOfTheOrg.find(
    (attribute) => attribute.options.some((option) => option.id === attributeOptionId)
  );
}
function _getAttributeOptionFromAttributeOption({
  allAttributesOfTheOrg,
  attributeOptionId
}) {
  const matchingOption = allAttributesOfTheOrg.reduce((found, attribute) => {
    if (found)
      return found;
    return attribute.options.find((option) => option.id === attributeOptionId) || null;
  }, null);
  return matchingOption;
}
async function _getOrgMembershipToUserIdForTeam({ orgId, teamId }) {
  const { orgMemberships, teamMemberships } = await membership.MembershipRepository.findMembershipsForBothOrgAndTeam({
    orgId,
    teamId
  });
  const orgMembershipsByUserId = new Map(orgMemberships.map((m) => [m.userId, m]));
  const orgMembershipToUserIdForTeamMembers = /* @__PURE__ */ new Map();
  teamMemberships.forEach((teamMembership) => {
    const orgMembership = orgMembershipsByUserId.get(teamMembership.userId);
    if (!orgMembership) {
      console.error(
        `Org membership not found for userId ${teamMembership.userId} in the organization's memberships`
      );
      return;
    }
    orgMembershipToUserIdForTeamMembers.set(orgMembership.id, orgMembership.userId);
  });
  return orgMembershipToUserIdForTeamMembers;
}
async function _queryAllData({ orgId, teamId }) {
  const attributeRepo = new ooo.PrismaAttributeRepository(index.prisma);
  const [orgMembershipToUserIdForTeamMembers, attributesOfTheOrg] = await Promise.all([
    _getOrgMembershipToUserIdForTeam({ orgId, teamId }),
    attributeRepo.findManyByOrgId({ orgId })
  ]);
  const orgMembershipIds = Array.from(orgMembershipToUserIdForTeamMembers.keys());
  const attributesToUsersForTeam = await PrismaAttributeToUserRepository.findManyByOrgMembershipIds({
    orgMembershipIds
  });
  return {
    attributesOfTheOrg,
    attributesToUsersForTeam,
    orgMembershipToUserIdForTeamMembers
  };
}
async function getAttributesAssignedToMembersOfTeam({ teamId, userId }) {
  const log2 = index.logger.getSubLogger({ prefix: ["getAttributeToUserWithMembershipAndAttributes"] });
  const whereClauseForAttributesAssignedToMembersOfTeam = {
    options: {
      some: {
        assignedUsers: {
          some: {
            member: {
              userId,
              user: {
                teams: {
                  some: {
                    teamId
                  }
                }
              }
            }
          }
        }
      }
    }
  };
  log2.debug(
    index.safeStringify({
      teamId,
      whereClauseForAttributesAssignedToMembersOfTeam
    })
  );
  const assignedAttributeOptions = await index.prisma.attribute.findMany({
    where: whereClauseForAttributesAssignedToMembersOfTeam,
    select: {
      id: true,
      name: true,
      type: true,
      isWeightsEnabled: true,
      options: {
        select: {
          id: true,
          value: true,
          slug: true,
          contains: true,
          isGroup: true
        }
      },
      slug: true
    }
  });
  return assignedAttributeOptions;
}
function _buildAssignmentsForTeam({
  attributesToUsersForTeam,
  orgMembershipToUserIdForTeamMembers,
  attributesOfTheOrg
}) {
  return attributesToUsersForTeam.map((attributeToUser) => {
    const orgMembershipId = attributeToUser.memberId;
    const userId = orgMembershipToUserIdForTeamMembers.get(orgMembershipId);
    if (!userId) {
      console.error(`No org membership found for membership id ${orgMembershipId}`);
      return null;
    }
    const attribute = _getAttributeFromAttributeOption({
      allAttributesOfTheOrg: attributesOfTheOrg,
      attributeOptionId: attributeToUser.attributeOptionId
    });
    const attributeOption = _getAttributeOptionFromAttributeOption({
      allAttributesOfTheOrg: attributesOfTheOrg,
      attributeOptionId: attributeToUser.attributeOptionId
    });
    if (!attributeOption || !attribute) {
      console.error(
        `Attribute option with id ${attributeToUser.attributeOptionId} not found in the organization's attributes`
      );
      return null;
    }
    return {
      ...attributeToUser,
      userId,
      attribute,
      attributeOption
    };
  }).filter((assignment) => assignment !== null);
}
async function getAttributesAssignmentData({ orgId, teamId }) {
  const { attributesOfTheOrg, attributesToUsersForTeam, orgMembershipToUserIdForTeamMembers } = await _queryAllData({
    orgId,
    teamId
  });
  const assignmentsForTheTeam = _buildAssignmentsForTeam({
    attributesToUsersForTeam,
    orgMembershipToUserIdForTeamMembers,
    attributesOfTheOrg
  });
  const attributesAssignedToTeamMembersWithOptions = _prepareAssignmentData({
    attributesOfTheOrg,
    assignmentsForTheTeam
  });
  return {
    attributesOfTheOrg,
    attributesAssignedToTeamMembersWithOptions
  };
}
async function getUsersAttributes({ userId, teamId }) {
  return await getAttributesAssignedToMembersOfTeam({ teamId, userId });
}
function isRerouting({
  rescheduleUid,
  routedTeamMemberIds
}) {
  return !!rescheduleUid && !!routedTeamMemberIds?.length;
}
function shouldIgnoreContactOwner({
  skipContactOwner,
  rescheduleUid,
  routedTeamMemberIds
}) {
  return skipContactOwner || isRerouting({ rescheduleUid, routedTeamMemberIds });
}
const attributeRepositoryModule = ioctopus.createModule();
attributeRepositoryModule.bind(utils.DI_TOKENS.ATTRIBUTE_REPOSITORY).toClass(ooo.PrismaAttributeRepository, [utils.DI_TOKENS.PRISMA_CLIENT]);
const hostRepositoryModule = ioctopus.createModule();
hostRepositoryModule.bind(utils.DI_TOKENS.HOST_REPOSITORY).toClass(ooo.HostRepository, [utils.DI_TOKENS.PRISMA_CLIENT]);
const luckyUserServiceModule = ioctopus.createModule();
luckyUserServiceModule.bind(utils.DI_TOKENS.LUCKY_USER_SERVICE).toClass(getLuckyUser.LuckyUserService, {
  bookingRepository: utils.DI_TOKENS.BOOKING_REPOSITORY,
  hostRepository: utils.DI_TOKENS.HOST_REPOSITORY,
  oooRepository: utils.DI_TOKENS.OOO_REPOSITORY,
  userRepository: utils.DI_TOKENS.USER_REPOSITORY,
  attributeRepository: utils.DI_TOKENS.ATTRIBUTE_REPOSITORY
});
const oooRepositoryModule = ioctopus.createModule();
oooRepositoryModule.bind(utils.DI_TOKENS.OOO_REPOSITORY).toClass(ooo.PrismaOOORepository, [utils.DI_TOKENS.PRISMA_CLIENT]);
const userRepositoryModule = ioctopus.createModule();
userRepositoryModule.bind(utils.DI_TOKENS.USER_REPOSITORY).toClass(user.UserRepository, [utils.DI_TOKENS.PRISMA_CLIENT]);
const container = ioctopus.createContainer();
container.load(utils.DI_TOKENS.PRISMA_MODULE, utils.prismaModule);
container.load(utils.DI_TOKENS.BOOKING_REPOSITORY_MODULE, utils.bookingRepositoryModule);
container.load(utils.DI_TOKENS.HOST_REPOSITORY_MODULE, hostRepositoryModule);
container.load(utils.DI_TOKENS.OOO_REPOSITORY_MODULE, oooRepositoryModule);
container.load(utils.DI_TOKENS.USER_REPOSITORY_MODULE, userRepositoryModule);
container.load(utils.DI_TOKENS.ATTRIBUTE_REPOSITORY_MODULE, attributeRepositoryModule);
container.load(utils.DI_TOKENS.LUCKY_USER_SERVICE_MODULE, luckyUserServiceModule);
function getLuckyUserService() {
  return container.get(utils.DI_TOKENS.LUCKY_USER_SERVICE);
}
function checkForConflicts({
  busy,
  time,
  eventLength,
  currentSeats
}) {
  if (!Array.isArray(busy) || busy.length < 1) {
    return false;
  }
  if (currentSeats?.some((booking) => booking.startTime.toISOString() === time.toISOString())) {
    return false;
  }
  const slotStart = time.valueOf();
  const slotEnd = slotStart + eventLength * 60 * 1e3;
  const sortedBusyTimes = busy.map((busyTime) => ({
    start: dayjs.utc(busyTime.start).valueOf(),
    end: dayjs.utc(busyTime.end).valueOf()
  })).sort((a, b) => a.start - b.start);
  for (const busyTime of sortedBusyTimes) {
    if (busyTime.start >= slotEnd) {
      break;
    }
    if (busyTime.end <= slotStart) {
      continue;
    }
    return true;
  }
  return false;
}
class FilterHostsService {
  constructor(dependencies) {
    this.dependencies = dependencies;
  }
  async filterHostsBySameRoundRobinHost({
    hosts,
    rescheduleUid,
    rescheduleWithSameRoundRobinHost,
    routedTeamMemberIds
  }) {
    if (!rescheduleUid || !rescheduleWithSameRoundRobinHost || isRerouting({ rescheduleUid, routedTeamMemberIds })) {
      return hosts;
    }
    const originalRescheduledBooking = await this.dependencies.bookingRepo.findOriginalRescheduledBookingUserId({
      rescheduleUid
    });
    if (!originalRescheduledBooking) {
      return hosts;
    }
    const attendeeEmails = originalRescheduledBooking.attendees?.map((attendee) => attendee.email) || [];
    return hosts.filter((host) => {
      const isOrganizer = host.user.id === originalRescheduledBooking.userId;
      const isAttendee = attendeeEmails.includes(host.user.email);
      return isOrganizer || isAttendee;
    });
  }
}
function normalize(input) {
  if (typeof input === "string") {
    return input.toLowerCase();
  }
  if (input instanceof Array) {
    return input.map((item) => {
      if (typeof item === "string") {
        return item.toLowerCase();
      }
      return item;
    });
  }
  return input;
}
jsonLogic.add_operation("==", function(a, b) {
  return normalize(a) == normalize(b);
});
jsonLogic.add_operation("===", function(a, b) {
  return normalize(a) === normalize(b);
});
jsonLogic.add_operation("!==", function(a, b) {
  return normalize(a) !== normalize(b);
});
jsonLogic.add_operation("!=", function(a, b) {
  return normalize(a) != normalize(b);
});
jsonLogic.add_operation("in", function(a, b) {
  const first = normalize(a);
  const second = normalize(b);
  if (!second)
    return false;
  return second.indexOf(first) !== -1;
});
jsonLogic.add_operation("starts_with", function(a, b) {
  if (typeof a !== "string" || typeof b !== "string")
    return false;
  const first = normalize(a);
  const second = normalize(b);
  if (!second)
    return false;
  return first.startsWith(second);
});
var RaqbLogicResult = /* @__PURE__ */ ((RaqbLogicResult2) => {
  RaqbLogicResult2["MATCH"] = "MATCH";
  RaqbLogicResult2["NO_MATCH"] = "NO_MATCH";
  RaqbLogicResult2["LOGIC_NOT_FOUND_SO_MATCHED"] = "LOGIC_NOT_FOUND_SO_MATCHED";
  return RaqbLogicResult2;
})(RaqbLogicResult || {});
const evaluateRaqbLogic = ({
  queryValue,
  queryBuilderConfig,
  data,
  beStrictWithEmptyLogic = false
}, config = {
  logLevel: 1
}) => {
  const state = {
    tree: reactAwesomeQueryBuilder.Utils.checkTree(reactAwesomeQueryBuilder.Utils.loadTree(queryValue), queryBuilderConfig),
    config: queryBuilderConfig
  };
  const jsonLogicQuery = reactAwesomeQueryBuilder.Utils.jsonLogicFormat(state.tree, state.config);
  const logic = jsonLogicQuery.logic;
  if (!logic) {
    if (beStrictWithEmptyLogic && queryValue.children1 && Object.keys(queryValue.children1).length > 0) {
      throw new Error("Couldn't build the logic from the query value");
    }
    console.log(
      "No logic found",
      index.safeStringify({ queryValue, queryBuilderConfigFields: queryBuilderConfig.fields })
    );
    return "LOGIC_NOT_FOUND_SO_MATCHED";
  }
  if (config.logLevel >= 1) {
    console.log("Checking logic with data", index.safeStringify({ logic, data }));
  }
  return !!jsonLogic.apply(logic, data) ? "MATCH" : "NO_MATCH";
};
const {
  getAttributesData: getAttributes,
  getAttributesQueryBuilderConfigHavingListofLabels,
  getAttributesQueryValue
} = getLuckyUser.acrossQueryValueCompatiblity;
async function asyncPerf(fn) {
  const start = performance.now();
  const result = await fn();
  const end = performance.now();
  return [result, end - start];
}
function perf(fn) {
  const start = performance.now();
  const result = fn();
  const end = performance.now();
  return [result, end - start];
}
function getErrorsFromImmutableTree(tree) {
  const validatedQueryValue = index_js.Utils.getTree(tree);
  if (!getLuckyUser.raqbQueryValueUtils.isQueryValueARuleGroup(validatedQueryValue)) {
    return [];
  }
  if (!validatedQueryValue.children1) {
    return [];
  }
  const errors = [];
  Object.values(validatedQueryValue.children1).map((rule) => {
    if (rule.type !== "rule") {
      return;
    }
    const valueError = rule.properties.valueError;
    if (valueError) {
      errors.push(valueError.filter(Boolean));
    }
  });
  return errors;
}
function getJsonLogic({
  attributesQueryValue,
  attributesQueryBuilderConfig
}) {
  const state = {
    tree: index_js.Utils.checkTree(
      index_js.Utils.loadTree(attributesQueryValue),
      // We know that attributesQueryBuilderConfig is a Config because getAttributesQueryBuilderConfigHavingListofLabels returns a Config. So, asserting it.
      attributesQueryBuilderConfig
    ),
    config: attributesQueryBuilderConfig
  };
  const jsonLogicQuery = index_js.Utils.jsonLogicFormat(state.tree, state.config);
  const logic = jsonLogicQuery.logic;
  const warnings = getErrorsFromImmutableTree(state.tree).flat();
  if (!logic) {
    if (attributesQueryValue.children1 && Object.keys(attributesQueryValue.children1).length > 0) {
      return { logic, warnings: ["There is some error building the logic, please check the routes."] };
    }
  }
  return { logic, warnings };
}
function buildTroubleshooterData({ type, data }) {
  return {
    troubleshooter: {
      type,
      data
    }
  };
}
async function getLogicResultForAllMembers({
  teamMembersWithAttributeOptionValuePerAttribute,
  attributeJsonLogic,
  attributesQueryValue
}, config = {}) {
  const { concurrency = 2 } = config;
  const teamMembersMatchingAttributeLogicMap = /* @__PURE__ */ new Map();
  const attributesDataPerUser = /* @__PURE__ */ new Map();
  await async.mapLimit(
    teamMembersWithAttributeOptionValuePerAttribute,
    concurrency,
    async (member) => {
      const attributesData = getAttributes({
        attributesData: member.attributes,
        attributesQueryValue
      });
      attributesDataPerUser.set(member.userId, attributesData);
      const result = !!jsonLogic.apply(attributeJsonLogic, attributesData) ? RaqbLogicResult.MATCH : RaqbLogicResult.NO_MATCH;
      if (result !== RaqbLogicResult.MATCH) {
        return;
      }
      teamMembersMatchingAttributeLogicMap.set(member.userId, result);
    }
  );
  return {
    teamMembersMatchingAttributeLogicMap,
    attributesDataPerUser
  };
}
async function runAttributeLogic(data, options) {
  const {
    attributesQueryValue: _attributesQueryValue,
    attributesData: { attributesOfTheOrg, teamMembersWithAttributeOptionValuePerAttribute },
    dynamicFieldValueOperands
  } = data;
  const { concurrency, enablePerf, enableTroubleshooter } = options;
  const attributesQueryValue = getAttributesQueryValue({
    attributesQueryValue: _attributesQueryValue ?? null,
    attributes: attributesOfTheOrg,
    dynamicFieldValueOperands
  });
  if (!attributesQueryValue || getLuckyUser.raqbQueryValueUtils.isQueryValueEmpty(attributesQueryValue)) {
    return {
      logicBuildingWarnings: null,
      teamMembersMatchingAttributeLogic: null,
      timeTaken: null,
      ...buildTroubleshooterData({
        type: "matches-all-members-because-of-empty-query-value",
        data: { attributesQueryValue }
      })
    };
  }
  const [attributesQueryBuilderConfig, ttgetAttributesQueryBuilderConfigHavingListofLabels] = pf(
    () => getAttributesQueryBuilderConfigHavingListofLabels({
      dynamicFieldValueOperands,
      attributes: attributesOfTheOrg
    })
  );
  const { logic, warnings: logicBuildingWarnings } = getJsonLogic({
    attributesQueryValue,
    attributesQueryBuilderConfig
  });
  if (!logic) {
    return {
      teamMembersMatchingAttributeLogic: null,
      logicBuildingWarnings: null,
      timeTaken: {
        ttgetAttributesQueryBuilderConfigHavingListofLabels
      },
      ...buildTroubleshooterData({
        type: "no-logic-found",
        data: {
          attributesQueryValue,
          attributesQueryBuilderConfig,
          teamMembersWithAttributeOptionValuePerAttribute
        }
      })
    };
  }
  const [
    { teamMembersMatchingAttributeLogicMap, attributesDataPerUser },
    ttTeamMembersMatchingAttributeLogic
  ] = await aPf(
    async () => getLogicResultForAllMembers(
      {
        teamMembersWithAttributeOptionValuePerAttribute,
        attributeJsonLogic: logic,
        attributesQueryValue
      },
      {
        concurrency,
        enableTroubleshooter
      }
    )
  );
  const teamMembersMatchingAttributeLogic = Array.from(teamMembersMatchingAttributeLogicMap).map((item) => ({
    userId: item[0],
    result: item[1]
  }));
  return {
    teamMembersMatchingAttributeLogic,
    logicBuildingWarnings,
    timeTaken: {
      ttgetAttributesQueryBuilderConfigHavingListofLabels,
      ttTeamMembersMatchingAttributeLogic
    },
    ...buildTroubleshooterData({
      type: "match-results-ready",
      data: {
        attributesDataPerUser,
        attributesQueryValue,
        attributesQueryBuilderConfig,
        logic,
        attributesOfTheOrg
      }
    })
  };
  function pf(fn) {
    if (!enablePerf) {
      return [fn(), null];
    }
    return perf(fn);
  }
  async function aPf(fn) {
    if (!enablePerf) {
      return [await fn(), null];
    }
    return asyncPerf(fn);
  }
}
async function runMainAttributeLogic(data, options) {
  const { teamMembersMatchingAttributeLogic, ...rest } = await runAttributeLogic(data, options);
  return {
    teamMembersMatchingMainAttributeLogic: teamMembersMatchingAttributeLogic,
    ...rest
  };
}
async function runFallbackAttributeLogic(data, options) {
  const { teamMembersMatchingAttributeLogic, ...rest } = await runAttributeLogic(data, options);
  return {
    teamMembersMatchingFallbackLogic: teamMembersMatchingAttributeLogic,
    ...rest
  };
}
async function getAttributesForLogic({ teamId, orgId }) {
  const [result, ttAttributes] = await asyncPerf(async () => {
    return getAttributesAssignmentData({ teamId, orgId });
  });
  return {
    attributesOfTheOrg: result.attributesOfTheOrg,
    teamMembersWithAttributeOptionValuePerAttribute: result.attributesAssignedToTeamMembersWithOptions,
    timeTaken: ttAttributes
  };
}
async function findTeamMembersMatchingAttributeLogic(data, options = {}) {
  const { enablePerf = false, concurrency = 2, enableTroubleshooter = false } = options;
  const considerFallback = "fallbackAttributesQueryValue" in data;
  const {
    teamId,
    orgId,
    attributesQueryValue,
    fallbackAttributesQueryValue,
    dynamicFieldValueOperands,
    isPreview
  } = data;
  const {
    attributesOfTheOrg,
    teamMembersWithAttributeOptionValuePerAttribute,
    timeTaken: ttGetAttributesForLogic
  } = await getAttributesForLogic({
    teamId,
    orgId
  });
  const runAttributeLogicOptions = {
    concurrency,
    enablePerf,
    isPreview: !!isPreview,
    enableTroubleshooter
  };
  const runAttributeLogicData = {
    // Change it as per the main/fallback query
    attributesData: {
      attributesOfTheOrg,
      teamMembersWithAttributeOptionValuePerAttribute
    },
    dynamicFieldValueOperands
  };
  const {
    teamMembersMatchingMainAttributeLogic,
    timeTaken: teamMembersMatchingMainAttributeLogicTimeTaken,
    troubleshooter,
    logicBuildingWarnings: mainAttributeLogicBuildingWarnings
  } = await runMainAttributeLogic(
    {
      ...runAttributeLogicData,
      attributesQueryValue
    },
    runAttributeLogicOptions
  );
  if (!teamMembersMatchingMainAttributeLogic) {
    return {
      teamMembersMatchingAttributeLogic: null,
      checkedFallback: false,
      mainAttributeLogicBuildingWarnings,
      fallbackAttributeLogicBuildingWarnings: [],
      timeTaken: {
        ...teamMembersMatchingMainAttributeLogicTimeTaken,
        ttGetAttributesForLogic
      },
      ...enableTroubleshooter ? buildTroubleshooterData({
        ...troubleshooter
      }) : null
    };
  }
  const noMatchingMembersFound = !teamMembersMatchingMainAttributeLogic.length;
  if (noMatchingMembersFound && considerFallback) {
    const {
      teamMembersMatchingFallbackLogic,
      timeTaken: teamMembersMatchingFallbackLogicTimeTaken,
      troubleshooter: troubleshooter2,
      logicBuildingWarnings: fallbackAttributeLogicBuildingWarnings
    } = await runFallbackAttributeLogic(
      {
        ...runAttributeLogicData,
        attributesQueryValue: fallbackAttributesQueryValue ?? null
      },
      runAttributeLogicOptions
    );
    return {
      teamMembersMatchingAttributeLogic: teamMembersMatchingFallbackLogic,
      checkedFallback: true,
      fallbackAttributeLogicBuildingWarnings,
      mainAttributeLogicBuildingWarnings,
      timeTaken: {
        ...teamMembersMatchingFallbackLogicTimeTaken,
        ttGetAttributesForLogic
      },
      ...enableTroubleshooter ? buildTroubleshooterData({
        ...troubleshooter2,
        type: "match-results-ready-with-fallback"
        /* MATCH_RESULTS_READY_WITH_FALLBACK */
      }) : null
    };
  }
  return {
    teamMembersMatchingAttributeLogic: teamMembersMatchingMainAttributeLogic,
    checkedFallback: false,
    mainAttributeLogicBuildingWarnings,
    fallbackAttributeLogicBuildingWarnings: [],
    timeTaken: {
      ...teamMembersMatchingMainAttributeLogicTimeTaken,
      ttGetAttributesForLogic
    },
    ...enableTroubleshooter ? buildTroubleshooterData({
      ...troubleshooter,
      type: "match-results-ready",
      data: {
        ...troubleshooter.data,
        attributesOfTheOrg
      }
    }) : null
  };
}
const log$1 = index.logger.getSubLogger({ prefix: ["[getRoutedUsers]"] });
const getRoutedUsersWithContactOwnerAndFixedUsers = ({
  routedTeamMemberIds,
  users,
  contactOwnerEmail
}) => {
  if (!routedTeamMemberIds || !routedTeamMemberIds.length) {
    return users;
  }
  log$1.debug(
    "filtering users as per routedTeamMemberIds",
    index.safeStringify({ routedTeamMemberIds, contactOwnerEmail })
  );
  return users.filter(
    (user2) => routedTeamMemberIds.includes(user2.id) || user2.isFixed || user2.email === contactOwnerEmail
  );
};
async function findMatchingTeamMembersIdsForEventRRSegment(eventType) {
  if (!eventType) {
    return null;
  }
  const isSegmentationDisabled = !eventType.assignAllTeamMembers || !eventType.assignRRMembersUsingSegment;
  if (isSegmentationDisabled) {
    return null;
  }
  if (!eventType.team || !eventType.team.parentId) {
    return null;
  }
  const { teamMembersMatchingAttributeLogic } = await findTeamMembersMatchingAttributeLogic({
    attributesQueryValue: eventType.rrSegmentQueryValue ?? null,
    teamId: eventType.team.id,
    orgId: eventType.team.parentId
  });
  if (!teamMembersMatchingAttributeLogic) {
    return teamMembersMatchingAttributeLogic;
  }
  return teamMembersMatchingAttributeLogic.map((member) => member.userId);
}
function getNormalizedHosts({
  eventType
}) {
  if (eventType.hosts?.length && eventType.schedulingType) {
    return {
      hosts: eventType.hosts.map((host) => ({
        isFixed: host.isFixed,
        user: host.user,
        priority: host.priority,
        weight: host.weight,
        createdAt: host.createdAt,
        groupId: host.groupId
      })),
      fallbackHosts: null
    };
  } else {
    return {
      hosts: null,
      fallbackHosts: eventType.users.map((user2) => {
        return {
          isFixed: !eventType.schedulingType || eventType.schedulingType === index.SchedulingType.COLLECTIVE,
          email: user2.email,
          user: user2,
          createdAt: null,
          groupId: null
        };
      })
    };
  }
}
async function getNormalizedHostsWithDelegationCredentials({
  eventType
}) {
  if (eventType.hosts?.length && eventType.schedulingType) {
    const hostsWithoutDelegationCredential = eventType.hosts.map((host) => ({
      isFixed: host.isFixed,
      user: host.user,
      priority: host.priority,
      weight: host.weight,
      createdAt: host.createdAt,
      groupId: host.groupId
    }));
    const firstHost = hostsWithoutDelegationCredential[0];
    const firstUserOrgId = await getOrgIdFromMemberOrTeamId.getOrgIdFromMemberOrTeamId({
      memberId: firstHost?.user?.id ?? null,
      teamId: eventType.teamId
    });
    const hostsEnrichedWithDelegationCredential = await credential.enrichHostsWithDelegationCredentials({
      orgId: firstUserOrgId ?? null,
      hosts: hostsWithoutDelegationCredential ?? null
    });
    return {
      hosts: hostsEnrichedWithDelegationCredential,
      fallbackHosts: null
    };
  } else {
    const hostsWithoutDelegationCredential = eventType.users.map((user2) => {
      return {
        isFixed: !eventType.schedulingType || eventType.schedulingType === index.SchedulingType.COLLECTIVE,
        email: user2.email,
        user: user2,
        createdAt: null
      };
    });
    const firstHost = hostsWithoutDelegationCredential[0];
    const firstUserOrgId = await getOrgIdFromMemberOrTeamId.getOrgIdFromMemberOrTeamId({
      memberId: firstHost?.user?.id ?? null,
      teamId: eventType.teamId
    });
    const hostsEnrichedWithDelegationCredential = await credential.enrichHostsWithDelegationCredentials({
      orgId: firstUserOrgId ?? null,
      hosts: hostsWithoutDelegationCredential ?? null
    });
    return {
      hosts: null,
      fallbackHosts: hostsEnrichedWithDelegationCredential
    };
  }
}
async function findMatchingHostsWithEventSegment({
  eventType,
  hosts
}) {
  const matchingRRTeamMembers = await findMatchingTeamMembersIdsForEventRRSegment({
    ...eventType,
    rrSegmentQueryValue: eventType.rrSegmentQueryValue ?? null
  });
  const segmentedRoundRobinHosts = hosts.filter((host) => {
    if (!matchingRRTeamMembers)
      return true;
    return matchingRRTeamMembers.includes(host.user.id);
  });
  return segmentedRoundRobinHosts;
}
const errorCodes = {
  MAX_LEAD_THRESHOLD_FALSY: "Max lead threshold should be null or > 1, not 0."
};
const log = index.logger.getSubLogger({ name: "filterHostsByLeadThreshold" });
function filterHostsByLeadThresholdWithWeights(perUserData, maxLeadThreshold) {
  const filteredUserIds = [];
  const maxShortfall = Math.max(...Object.values(perUserData.bookingShortfalls));
  for (const userIdStr in perUserData.bookingShortfalls) {
    const shortfall = perUserData.bookingShortfalls[userIdStr];
    if (maxShortfall - shortfall > maxLeadThreshold) {
      log.debug(
        `Host ${userIdStr} has been filtered out because the amount of bookings made him exceed the thresholds. Shortfall: ${shortfall}, Max Shortfall: ${maxShortfall}`
      );
    } else {
      filteredUserIds.push(parseInt(userIdStr, 10));
    }
  }
  return filteredUserIds;
}
function filterHostsByLeadThresholdWithoutWeights(perUserData, maxLeadThreshold) {
  const filteredUserIds = [];
  const bookingsArray = Object.values(perUserData.bookingsCount);
  const minBookings = Math.min(...bookingsArray);
  for (const userIdStr in perUserData.bookingsCount) {
    const bookingsCount = perUserData.bookingsCount[userIdStr];
    if (bookingsCount - minBookings > maxLeadThreshold) {
      log.debug(
        `Host ${userIdStr} has been filtered out because the given data made them exceed the thresholds. BookingsCount: ${bookingsCount}, MinBookings: ${minBookings}`
      );
    } else {
      filteredUserIds.push(parseInt(userIdStr, 10));
      log.debug(
        `Host Allowed ${userIdStr} has been filtered out because the given data made them exceed the thresholds. BookingsCount: ${bookingsCount}, MinBookings: ${minBookings}, MaxLeadThreshold: ${maxLeadThreshold}`
      );
    }
  }
  return filteredUserIds;
}
const filterHostsByLeadThreshold = async ({
  hosts,
  maxLeadThreshold,
  eventType,
  routingFormResponse
}) => {
  if (maxLeadThreshold === 0) {
    throw new Error(errorCodes.MAX_LEAD_THRESHOLD_FALSY);
  }
  if (maxLeadThreshold === null || hosts.length < 1 || eventType.team?.rrTimestampBasis && eventType.team.rrTimestampBasis !== index.RRTimestampBasis.CREATED_AT) {
    return hosts;
  }
  const luckyUserService = getLuckyUserService();
  const orderedLuckyUsers = await luckyUserService.getOrderedListOfLuckyUsers({
    availableUsers: [
      {
        ...hosts[0].user,
        weight: hosts[0].weight ?? null,
        priority: hosts[0].priority ?? null
      },
      ...hosts.slice(1).map((host) => ({
        ...host.user,
        weight: host.weight ?? null,
        priority: host.priority ?? null
      }))
    ],
    eventType,
    allRRHosts: hosts,
    routingFormResponse
  });
  const perUserData = orderedLuckyUsers["perUserData"];
  let filteredUserIds;
  if (eventType.isRRWeightsEnabled) {
    if (perUserData.calibrations === null || perUserData.weights === null || perUserData.bookingShortfalls === null) {
      throw new Error("Calibrations, weights, or booking shortfalls are null");
    }
    filteredUserIds = filterHostsByLeadThresholdWithWeights(
      {
        bookingsCount: perUserData.bookingsCount,
        bookingShortfalls: perUserData.bookingShortfalls,
        calibrations: perUserData.calibrations,
        weights: perUserData.weights
      },
      maxLeadThreshold
    );
  } else {
    filteredUserIds = filterHostsByLeadThresholdWithoutWeights(perUserData, maxLeadThreshold);
  }
  const filteredHosts = hosts.filter((host) => filteredUserIds.includes(host.user.id));
  return filteredHosts;
};
function applyFilterWithFallback(currentValue, newValue) {
  return newValue.length > 0 ? newValue : currentValue;
}
function getFallBackWithContactOwner(fallbackHosts, contactOwner) {
  if (fallbackHosts.find((host) => host.user.id === contactOwner.user.id)) {
    return fallbackHosts;
  }
  return [...fallbackHosts, contactOwner];
}
const isRoundRobinHost = (host) => {
  return host.isFixed === false;
};
const isFixedHost = (host) => {
  return host.isFixed;
};
class QualifiedHostsService {
  constructor(dependencies) {
    this.dependencies = dependencies;
    this.findQualifiedHostsWithDelegationCredentials = index.withReporting(
      this._findQualifiedHostsWithDelegationCredentials.bind(this),
      "findQualifiedHostsWithDelegationCredentials"
    );
  }
  async _findQualifiedHostsWithDelegationCredentials({
    eventType,
    rescheduleUid,
    routedTeamMemberIds,
    contactOwnerEmail,
    routingFormResponse
  }) {
    const { hosts: normalizedHosts, fallbackHosts: fallbackUsers } = await getNormalizedHostsWithDelegationCredentials({
      eventType
    });
    if (!normalizedHosts) {
      const fixedHosts2 = fallbackUsers.filter(isFixedHost);
      const roundRobinHosts2 = fallbackUsers.filter(isRoundRobinHost);
      return { qualifiedRRHosts: roundRobinHosts2, fixedHosts: fixedHosts2 };
    }
    const fixedHosts = normalizedHosts.filter(isFixedHost);
    const roundRobinHosts = normalizedHosts.filter(isRoundRobinHost);
    const hostsAfterRescheduleWithSameRoundRobinHost = applyFilterWithFallback(
      roundRobinHosts,
      await this.dependencies.filterHostsService.filterHostsBySameRoundRobinHost({
        hosts: roundRobinHosts,
        rescheduleUid,
        rescheduleWithSameRoundRobinHost: eventType.rescheduleWithSameRoundRobinHost,
        routedTeamMemberIds
      })
    );
    if (hostsAfterRescheduleWithSameRoundRobinHost.length === 1) {
      return {
        qualifiedRRHosts: hostsAfterRescheduleWithSameRoundRobinHost,
        fixedHosts
      };
    }
    const hostsAfterSegmentMatching = applyFilterWithFallback(
      hostsAfterRescheduleWithSameRoundRobinHost,
      await findMatchingHostsWithEventSegment({
        eventType,
        hosts: hostsAfterRescheduleWithSameRoundRobinHost
      })
    );
    if (hostsAfterSegmentMatching.length === 1) {
      return {
        qualifiedRRHosts: hostsAfterSegmentMatching,
        fixedHosts
      };
    }
    const officalRRHosts = hostsAfterSegmentMatching.length ? hostsAfterSegmentMatching : hostsAfterRescheduleWithSameRoundRobinHost;
    const hostsAfterContactOwnerMatching = applyFilterWithFallback(
      officalRRHosts,
      officalRRHosts.filter((host) => host.user.email === contactOwnerEmail)
    );
    const hostsAfterRoutedTeamMemberIdsMatching = applyFilterWithFallback(
      officalRRHosts,
      officalRRHosts.filter((host) => routedTeamMemberIds.includes(host.user.id))
    );
    if (hostsAfterRoutedTeamMemberIdsMatching.length === 1) {
      if (hostsAfterContactOwnerMatching.length === 1) {
        return {
          qualifiedRRHosts: hostsAfterContactOwnerMatching,
          allFallbackRRHosts: getFallBackWithContactOwner(
            hostsAfterRoutedTeamMemberIdsMatching,
            hostsAfterContactOwnerMatching[0]
          ),
          fixedHosts
        };
      }
      return {
        qualifiedRRHosts: hostsAfterRoutedTeamMemberIdsMatching,
        fixedHosts
      };
    }
    const hostsAfterFairnessMatching = applyFilterWithFallback(
      hostsAfterRoutedTeamMemberIdsMatching,
      await filterHostsByLeadThreshold({
        eventType,
        hosts: hostsAfterRoutedTeamMemberIdsMatching,
        maxLeadThreshold: eventType.maxLeadThreshold ?? null,
        routingFormResponse
      })
    );
    if (hostsAfterContactOwnerMatching.length === 1) {
      return {
        qualifiedRRHosts: hostsAfterContactOwnerMatching,
        allFallbackRRHosts: getFallBackWithContactOwner(
          hostsAfterFairnessMatching,
          hostsAfterContactOwnerMatching[0]
        ),
        fixedHosts
      };
    }
    return {
      qualifiedRRHosts: hostsAfterFairnessMatching,
      // only if fairness filtering is active
      allFallbackRRHosts: hostsAfterFairnessMatching.length !== hostsAfterRoutedTeamMemberIdsMatching.length ? hostsAfterRoutedTeamMemberIdsMatching : void 0,
      fixedHosts
    };
  }
}
class BookingDateInPastError extends Error {
  constructor(message = "Attempting to book a meeting in the past.") {
    super(message);
  }
}
function guardAgainstBookingInThePast(date) {
  if (date >= /* @__PURE__ */ new Date()) {
    return;
  }
  throw new BookingDateInPastError();
}
function calculatePeriodLimits({
  periodType,
  periodDays,
  periodCountCalendarDays,
  periodStartDate,
  periodEndDate,
  /**
   * These dates will be considered in the same utfcOffset as provided
   */
  allDatesWithBookabilityStatusInBookerTz,
  eventUtcOffset,
  bookerUtcOffset,
  /**
   * This is temporary till we find a way to provide allDatesWithBookabilityStatus in handleNewBooking without re-computing availability.
   * It is okay for handleNewBooking to pass it as true as the frontend won't allow selecting a timeslot that is out of bounds of ROLLING_WINDOW
   * But for the booking that happen through API, we absolutely need to check the ROLLING_WINDOW limits.
   */
  _skipRollingWindowCheck
}) {
  const currentTime = dayjs();
  const currentTimeInEventTz = currentTime.utcOffset(eventUtcOffset);
  const currentTimeInBookerTz = currentTime.utcOffset(bookerUtcOffset);
  periodDays = periodDays || 0;
  const log2 = index.logger.getSubLogger({ prefix: ["calculatePeriodLimits"] });
  log2.debug(
    index.safeStringify({
      periodType,
      periodDays,
      periodCountCalendarDays,
      periodStartDate,
      periodEndDate,
      currentTime: currentTimeInEventTz.format()
    })
  );
  switch (periodType) {
    case index.PeriodType.ROLLING: {
      const rollingEndDay = periodCountCalendarDays ? currentTimeInBookerTz.add(periodDays, "days") : currentTimeInBookerTz.businessDaysAdd(periodDays);
      return {
        endOfRollingPeriodEndDayInBookerTz: rollingEndDay.endOf("day"),
        startOfRangeStartDayInEventTz: null,
        endOfRangeEndDayInEventTz: null
      };
    }
    case index.PeriodType.ROLLING_WINDOW: {
      if (_skipRollingWindowCheck) {
        return {
          endOfRollingPeriodEndDayInBookerTz: null,
          startOfRangeStartDayInEventTz: null,
          endOfRangeEndDayInEventTz: null
        };
      }
      if (!allDatesWithBookabilityStatusInBookerTz) {
        throw new Error("`allDatesWithBookabilityStatus` is required");
      }
      const endOfRollingPeriodEndDayInBookerTz = getRollingWindowEndDate({
        startDateInBookerTz: currentTimeInBookerTz,
        daysNeeded: periodDays,
        allDatesWithBookabilityStatusInBookerTz,
        countNonBusinessDays: periodCountCalendarDays
      });
      return {
        endOfRollingPeriodEndDayInBookerTz,
        startOfRangeStartDayInEventTz: null,
        endOfRangeEndDayInEventTz: null
      };
    }
    case index.PeriodType.RANGE: {
      const startOfRangeStartDayInEventTz = dayjs(periodStartDate).utcOffset(eventUtcOffset).startOf("day");
      const endOfRangeEndDayInEventTz = dayjs(periodEndDate).utcOffset(eventUtcOffset).endOf("day");
      return {
        endOfRollingPeriodEndDayInBookerTz: null,
        startOfRangeStartDayInEventTz,
        endOfRangeEndDayInEventTz
      };
    }
  }
  return {
    endOfRollingPeriodEndDayInBookerTz: null,
    startOfRangeStartDayInEventTz: null,
    endOfRangeEndDayInEventTz: null
  };
}
function getRollingWindowEndDate({
  startDateInBookerTz,
  daysNeeded,
  allDatesWithBookabilityStatusInBookerTz,
  countNonBusinessDays
}) {
  const log2 = index.logger.getSubLogger({ prefix: ["getRollingWindowEndDate"] });
  log2.debug("called:", index.safeStringify({ startDay: startDateInBookerTz.format(), daysNeeded }));
  let counter = 1;
  let rollingEndDay;
  const startOfStartDayInEventTz = startDateInBookerTz.startOf("day");
  const maxDaysToCheck = index.ROLLING_WINDOW_PERIOD_MAX_DAYS_TO_CHECK;
  let bookableDaysCount = 0;
  let startOfIterationDay = startOfStartDayInEventTz;
  while (bookableDaysCount < daysNeeded) {
    if (counter > maxDaysToCheck) {
      break;
    }
    const onlyDateOfIterationDay = startOfIterationDay.format("YYYY-MM-DD");
    const isBookable = !!allDatesWithBookabilityStatusInBookerTz[onlyDateOfIterationDay]?.isBookable;
    if (isBookable) {
      bookableDaysCount++;
      rollingEndDay = startOfIterationDay;
    }
    log2.silly(
      `Loop Iteration: ${counter}`,
      index.safeStringify({
        iterationDayBeginning: startOfIterationDay.format(),
        isBookable,
        bookableDaysCount,
        rollingEndDay: rollingEndDay?.format(),
        allDatesWithBookabilityStatusInBookerTz
      })
    );
    startOfIterationDay = countNonBusinessDays ? startOfIterationDay.add(1, "days") : startOfIterationDay.businessDaysAdd(1);
    counter++;
  }
  const endOfLastDayOfWindowInBookerTz = (rollingEndDay ?? startOfIterationDay).endOf("day");
  log2.debug("Returning rollingEndDay", endOfLastDayOfWindowInBookerTz.format());
  return endOfLastDayOfWindowInBookerTz;
}
function isTimeOutOfBounds({
  time,
  minimumBookingNotice
}) {
  const date = dayjs(time);
  guardAgainstBookingInThePast(date.toDate());
  if (minimumBookingNotice) {
    const minimumBookingStartDate = dayjs().add(minimumBookingNotice, "minutes");
    if (date.isBefore(minimumBookingStartDate)) {
      return true;
    }
  }
  return false;
}
function isTimeViolatingFutureLimit({
  time,
  periodLimits
}) {
  const log2 = index.logger.getSubLogger({ prefix: ["isTimeViolatingFutureLimit"] });
  const dateObj = new Date(time);
  if (periodLimits.endOfRollingPeriodEndDayInBookerTz) {
    const isAfterRollingEndDay = dateObj.valueOf() > periodLimits.endOfRollingPeriodEndDayInBookerTz.valueOf();
    if (isAfterRollingEndDay)
      log2.warn(
        "Booking is out of bounds due to rolling period end day.",
        index.safeStringify({
          formattedDate: dateObj.toISOString(),
          isAfterRollingEndDay,
          endOfRollingPeriodEndDayTs: periodLimits.endOfRollingPeriodEndDayInBookerTz.valueOf()
        })
      );
    return isAfterRollingEndDay;
  }
  if (periodLimits.startOfRangeStartDayInEventTz && periodLimits.endOfRangeEndDayInEventTz) {
    const isBeforeRangeStart = dateObj.valueOf() < periodLimits.startOfRangeStartDayInEventTz.valueOf();
    const isAfterRangeEnd = dateObj.valueOf() > periodLimits.endOfRangeEndDayInEventTz.valueOf();
    if (isBeforeRangeStart || isAfterRangeEnd)
      log2.warn(
        "Booking is out of bounds due to range start and end.",
        index.safeStringify({
          formattedDate: dateObj.toISOString(),
          isBeforeRangeStart,
          isAfterRangeEnd,
          startOfRangeStartDayInEventTz: periodLimits.startOfRangeStartDayInEventTz.toDate().toISOString(),
          endOfRangeEndDayInEventTz: periodLimits.endOfRangeEndDayInEventTz.toDate().toISOString()
        })
      );
    return isBeforeRangeStart || isAfterRangeEnd;
  }
  return false;
}
function isOutOfBounds(time, {
  periodType,
  periodDays,
  periodCountCalendarDays,
  periodStartDate,
  periodEndDate,
  eventUtcOffset,
  bookerUtcOffset
}, minimumBookingNotice) {
  const log2 = index.logger.getSubLogger({ prefix: ["isOutOfBounds"] });
  const isOutOfBoundsByTime = isTimeOutOfBounds({ time, minimumBookingNotice });
  const periodLimits = calculatePeriodLimits({
    periodType,
    periodDays,
    periodCountCalendarDays,
    periodStartDate,
    periodEndDate,
    allDatesWithBookabilityStatusInBookerTz: null,
    // Temporary workaround
    _skipRollingWindowCheck: true,
    eventUtcOffset,
    bookerUtcOffset
  });
  const isOutOfBoundsByPeriod = isTimeViolatingFutureLimit({
    time: dayjs.isDayjs(time) ? time.toDate() : time,
    periodLimits
  });
  if (isOutOfBoundsByTime) {
    log2.warn(
      "Booking is out of bounds due to minimum booking notice.",
      index.safeStringify({ minimumBookingNotice })
    );
    return true;
  }
  if (isOutOfBoundsByPeriod) {
    log2.warn("Booking is out of bounds due to period restrictions", index.safeStringify({ periodLimits }));
    return true;
  }
  return false;
}
exports.BookingDateInPastError = BookingDateInPastError;
exports.FilterHostsService = FilterHostsService;
exports.QualifiedHostsService = QualifiedHostsService;
exports.RaqbLogicResult = RaqbLogicResult;
exports.calculatePeriodLimits = calculatePeriodLimits;
exports.checkForConflicts = checkForConflicts;
exports.evaluateRaqbLogic = evaluateRaqbLogic;
exports.findMatchingHostsWithEventSegment = findMatchingHostsWithEventSegment;
exports.findTeamMembersMatchingAttributeLogic = findTeamMembersMatchingAttributeLogic;
exports.getLuckyUserService = getLuckyUserService;
exports.getNormalizedHosts = getNormalizedHosts;
exports.getRoutedUsersWithContactOwnerAndFixedUsers = getRoutedUsersWithContactOwnerAndFixedUsers;
exports.getUsersAttributes = getUsersAttributes;
exports.isEventTypeLoggingEnabled = isEventTypeLoggingEnabled;
exports.isOutOfBounds = isOutOfBounds;
exports.isTimeOutOfBounds = isTimeOutOfBounds;
exports.isTimeViolatingFutureLimit = isTimeViolatingFutureLimit;
exports.oooRepositoryModule = oooRepositoryModule;
exports.shouldIgnoreContactOwner = shouldIgnoreContactOwner;
