import { w as withReporting } from "./sentryWrapper-E-bvLHb0.js";
import { B as BookingStatus, b as bookingMinimalSelect, R as RRTimestampBasis } from "./index-Cw1zbw54.js";
import { U as UserRepository } from "./user-YNqbx2fx.js";
const buildWhereClauseForActiveBookings = ({
  eventTypeId,
  startDate,
  endDate,
  users,
  virtualQueuesData,
  includeNoShowInRRCalculation = false,
  rrTimestampBasis
}) => ({
  OR: [
    {
      userId: {
        in: users.map((user) => user.id)
      },
      ...!includeNoShowInRRCalculation ? {
        OR: [{ noShowHost: false }, { noShowHost: null }]
      } : {}
    },
    {
      attendees: {
        some: {
          email: {
            in: users.map((user) => user.email)
          }
        }
      }
    }
  ],
  ...!includeNoShowInRRCalculation ? { attendees: { some: { noShow: false } } } : {},
  status: BookingStatus.ACCEPTED,
  eventTypeId,
  ...startDate || endDate ? rrTimestampBasis === RRTimestampBasis.CREATED_AT ? {
    createdAt: {
      ...startDate ? { gte: startDate } : {},
      ...endDate ? { lte: endDate } : {}
    }
  } : {
    startTime: {
      ...startDate ? { gte: startDate } : {},
      ...endDate ? { lte: endDate } : {}
    }
  } : {},
  ...virtualQueuesData ? {
    routedFromRoutingFormReponse: {
      chosenRouteId: virtualQueuesData.chosenRouteId
    }
  } : {}
});
class BookingRepository {
  constructor(prismaClient) {
    this.prismaClient = prismaClient;
    this.findAllExistingBookingsForEventTypeBetween = withReporting(
      this._findAllExistingBookingsForEventTypeBetween.bind(this),
      "findAllExistingBookingsForEventTypeBetween"
    );
  }
  async getBookingAttendees(bookingId) {
    return await this.prismaClient.attendee.findMany({
      where: {
        bookingId
      }
    });
  }
  /** Determines if the user is the organizer, team admin, or org admin that the booking was created under */
  async doesUserIdHaveAccessToBooking({ userId, bookingId }) {
    const booking = await this.prismaClient.booking.findUnique({
      where: {
        id: bookingId
      },
      select: {
        userId: true,
        eventType: {
          select: {
            teamId: true
          }
        }
      }
    });
    if (!booking)
      return false;
    if (userId === booking.userId)
      return true;
    if (!booking.eventType || !booking.eventType.teamId)
      return false;
    const userRepo = new UserRepository(this.prismaClient);
    const isAdminOrUser = await userRepo.isAdminOfTeamOrParentOrg({
      userId,
      teamId: booking.eventType.teamId
    });
    return isAdminOrUser;
  }
  async findFirstBookingByReschedule({ originalBookingUid }) {
    return await this.prismaClient.booking.findFirst({
      where: {
        fromReschedule: originalBookingUid
      },
      select: {
        uid: true
      }
    });
  }
  async findReschedulerByUid({ uid }) {
    return await this.prismaClient.booking.findUnique({
      where: {
        uid
      },
      select: {
        rescheduledBy: true,
        uid: true
      }
    });
  }
  async _findAllExistingBookingsForEventTypeBetween({
    eventTypeId,
    seatedEvent = false,
    startDate,
    endDate,
    userIdAndEmailMap
  }) {
    const sharedQuery = {
      startTime: { lte: endDate },
      endTime: { gte: startDate },
      status: {
        in: [BookingStatus.ACCEPTED]
      }
    };
    const bookingsSelect = {
      id: true,
      uid: true,
      userId: true,
      startTime: true,
      endTime: true,
      title: true,
      attendees: true,
      eventType: {
        select: {
          id: true,
          onlyShowFirstAvailableSlot: true,
          afterEventBuffer: true,
          beforeEventBuffer: true,
          seatsPerTimeSlot: true,
          requiresConfirmationWillBlockSlot: true,
          requiresConfirmation: true,
          allowReschedulingPastBookings: true,
          hideOrganizerEmail: true
        }
      },
      ...seatedEvent && {
        _count: {
          select: {
            seatsReferences: true
          }
        }
      }
    };
    const currentBookingsAllUsersQueryOne = this.prismaClient.booking.findMany({
      where: {
        ...sharedQuery,
        userId: {
          in: Array.from(userIdAndEmailMap.keys())
        }
      },
      select: bookingsSelect
    });
    const currentBookingsAllUsersQueryTwo = this.prismaClient.booking.findMany({
      where: {
        ...sharedQuery,
        attendees: {
          some: {
            email: {
              in: Array.from(userIdAndEmailMap.values())
            }
          }
        }
      },
      select: bookingsSelect
    });
    const currentBookingsAllUsersQueryThree = eventTypeId ? this.prismaClient.booking.findMany({
      where: {
        startTime: { lte: endDate },
        endTime: { gte: startDate },
        eventType: {
          id: eventTypeId,
          requiresConfirmation: true,
          requiresConfirmationWillBlockSlot: true
        },
        status: {
          in: [BookingStatus.PENDING]
        }
      },
      select: bookingsSelect
    }) : [];
    const [resultOne, resultTwo, resultThree] = await Promise.all([
      currentBookingsAllUsersQueryOne,
      currentBookingsAllUsersQueryTwo,
      currentBookingsAllUsersQueryThree
    ]);
    const resultTwoWithOrganizersRemoved = resultTwo.filter((booking) => {
      if (!booking.userId)
        return true;
      const organizerEmail = userIdAndEmailMap.get(booking.userId);
      return !booking.attendees.some((attendee) => attendee.email === organizerEmail);
    });
    return [...resultOne, ...resultTwoWithOrganizersRemoved, ...resultThree];
  }
  async getAllBookingsForRoundRobin({
    users,
    eventTypeId,
    startDate,
    endDate,
    virtualQueuesData,
    includeNoShowInRRCalculation,
    rrTimestampBasis
  }) {
    const allBookings = await this.prismaClient.booking.findMany({
      where: buildWhereClauseForActiveBookings({
        eventTypeId,
        startDate,
        endDate,
        users,
        virtualQueuesData,
        includeNoShowInRRCalculation,
        rrTimestampBasis
      }),
      select: {
        id: true,
        attendees: true,
        userId: true,
        createdAt: true,
        status: true,
        startTime: true,
        routedFromRoutingFormReponse: true
      },
      orderBy: {
        createdAt: "desc"
      }
    });
    let queueBookings = allBookings;
    if (virtualQueuesData) {
      queueBookings = allBookings.filter((booking) => {
        const responses = booking.routedFromRoutingFormReponse;
        const fieldId = virtualQueuesData.fieldOptionData.fieldId;
        const selectedOptionIds = virtualQueuesData.fieldOptionData.selectedOptionIds;
        const response = responses?.response;
        const responseValue = response[fieldId].value;
        if (Array.isArray(responseValue) && Array.isArray(selectedOptionIds)) {
          return responseValue.length === selectedOptionIds.length && responseValue.every((value, index) => value === selectedOptionIds[index]);
        } else {
          return responseValue === selectedOptionIds;
        }
      });
    }
    return queueBookings;
  }
  async findBookingByUid({ bookingUid }) {
    return await this.prismaClient.booking.findUnique({
      where: {
        uid: bookingUid
      },
      select: bookingMinimalSelect
    });
  }
  async findBookingForMeetingPage({ bookingUid }) {
    return await this.prismaClient.booking.findUnique({
      where: {
        uid: bookingUid
      },
      select: {
        ...bookingMinimalSelect,
        uid: true,
        description: true,
        isRecorded: true,
        eventType: {
          select: {
            id: true,
            hideOrganizerEmail: true,
            calVideoSettings: {
              select: {
                disableRecordingForGuests: true,
                disableRecordingForOrganizer: true,
                enableAutomaticTranscription: true,
                enableAutomaticRecordingForOrganizer: true,
                disableTranscriptionForGuests: true,
                disableTranscriptionForOrganizer: true,
                redirectUrlOnExit: true
              }
            }
          }
        },
        user: {
          select: {
            id: true,
            timeZone: true,
            name: true,
            email: true,
            username: true
          }
        },
        references: {
          select: {
            id: true,
            uid: true,
            type: true,
            meetingUrl: true,
            meetingPassword: true
          },
          where: {
            type: "daily_video",
            deleted: null
          },
          orderBy: {
            id: "asc"
          }
        }
      }
    });
  }
  async findBookingForMeetingEndedPage({ bookingUid }) {
    return await this.prismaClient.booking.findUnique({
      where: {
        uid: bookingUid
      },
      select: {
        ...bookingMinimalSelect,
        uid: true,
        user: {
          select: {
            credentials: true
          }
        },
        references: {
          select: {
            uid: true,
            type: true,
            meetingUrl: true
          }
        }
      }
    });
  }
  async findBookingByUidAndUserId({ bookingUid, userId }) {
    return await this.prismaClient.booking.findFirst({
      where: {
        uid: bookingUid,
        OR: [
          { userId },
          {
            eventType: {
              hosts: {
                some: {
                  userId
                }
              }
            }
          },
          {
            eventType: {
              users: {
                some: {
                  id: userId
                }
              }
            }
          },
          {
            eventType: {
              team: {
                members: {
                  some: {
                    userId,
                    accepted: true,
                    role: {
                      in: ["ADMIN", "OWNER"]
                    }
                  }
                }
              }
            }
          },
          {
            eventType: {
              parent: {
                team: {
                  members: {
                    some: {
                      userId,
                      accepted: true,
                      role: {
                        in: ["ADMIN", "OWNER"]
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      }
    });
  }
  async updateLocationById({
    where: { id },
    data: { location, metadata, referencesToCreate }
  }) {
    await this.prismaClient.booking.update({
      where: {
        id
      },
      data: {
        location,
        metadata,
        references: {
          create: referencesToCreate
        }
      }
    });
  }
  async getAllAcceptedTeamBookingsOfUser(params) {
    const { user, teamId, startDate, endDate, excludedUid, shouldReturnCount, includeManagedEvents } = params;
    const baseWhere = {
      status: BookingStatus.ACCEPTED,
      startTime: {
        gte: startDate
      },
      endTime: {
        lte: endDate
      },
      ...excludedUid && {
        uid: {
          not: excludedUid
        }
      }
    };
    const whereCollectiveRoundRobinOwner = {
      ...baseWhere,
      userId: user.id,
      eventType: {
        teamId
      }
    };
    const whereCollectiveRoundRobinBookingsAttendee = {
      ...baseWhere,
      attendees: {
        some: {
          email: user.email
        }
      },
      eventType: {
        teamId
      }
    };
    const whereManagedBookings = {
      ...baseWhere,
      userId: user.id,
      eventType: {
        parent: {
          teamId
        }
      }
    };
    if (shouldReturnCount) {
      const collectiveRoundRobinBookingsOwner2 = await this.prismaClient.booking.count({
        where: whereCollectiveRoundRobinOwner
      });
      const collectiveRoundRobinBookingsAttendee2 = await this.prismaClient.booking.count({
        where: whereCollectiveRoundRobinBookingsAttendee
      });
      let managedBookings2 = 0;
      if (includeManagedEvents) {
        managedBookings2 = await this.prismaClient.booking.count({
          where: whereManagedBookings
        });
      }
      const totalNrOfBooking = collectiveRoundRobinBookingsOwner2 + collectiveRoundRobinBookingsAttendee2 + managedBookings2;
      return totalNrOfBooking;
    }
    const collectiveRoundRobinBookingsOwner = await this.prismaClient.booking.findMany({
      where: whereCollectiveRoundRobinOwner
    });
    const collectiveRoundRobinBookingsAttendee = await this.prismaClient.booking.findMany({
      where: whereCollectiveRoundRobinBookingsAttendee
    });
    let managedBookings = [];
    if (includeManagedEvents) {
      managedBookings = await this.prismaClient.booking.findMany({
        where: whereManagedBookings
      });
    }
    return [
      ...collectiveRoundRobinBookingsOwner,
      ...collectiveRoundRobinBookingsAttendee,
      ...managedBookings
    ];
  }
  async findOriginalRescheduledBooking(uid, seatsEventType) {
    return await this.prismaClient.booking.findFirst({
      where: {
        uid,
        status: {
          in: [BookingStatus.ACCEPTED, BookingStatus.CANCELLED, BookingStatus.PENDING]
        }
      },
      include: {
        attendees: {
          select: {
            name: true,
            email: true,
            locale: true,
            timeZone: true,
            phoneNumber: true,
            ...seatsEventType && { bookingSeat: true, id: true }
          }
        },
        user: {
          select: {
            id: true,
            name: true,
            email: true,
            locale: true,
            timeZone: true,
            destinationCalendar: true,
            credentials: {
              select: {
                id: true,
                userId: true,
                key: true,
                type: true,
                teamId: true,
                appId: true,
                invalid: true,
                user: {
                  select: {
                    email: true
                  }
                }
              }
            }
          }
        },
        destinationCalendar: true,
        payment: true,
        references: true,
        workflowReminders: true
      }
    });
  }
  async getAllAcceptedTeamBookingsOfUsers(params) {
    const { users, teamId, startDate, endDate, excludedUid, shouldReturnCount, includeManagedEvents } = params;
    const baseWhere = {
      status: BookingStatus.ACCEPTED,
      startTime: {
        gte: startDate
      },
      endTime: {
        lte: endDate
      },
      ...excludedUid && {
        uid: {
          not: excludedUid
        }
      }
    };
    const userIds = users.map((user) => user.id);
    const userEmails = users.map((user) => user.email);
    const whereCollectiveRoundRobinOwner = {
      ...baseWhere,
      userId: {
        in: userIds
      },
      eventType: {
        teamId
      }
    };
    const whereCollectiveRoundRobinBookingsAttendee = {
      ...baseWhere,
      attendees: {
        some: {
          email: {
            in: userEmails
          }
        }
      },
      eventType: {
        teamId
      }
    };
    const whereManagedBookings = {
      ...baseWhere,
      userId: {
        in: userIds
      },
      eventType: {
        parent: {
          teamId
        }
      }
    };
    if (shouldReturnCount) {
      const collectiveRoundRobinBookingsOwner2 = await this.prismaClient.booking.count({
        where: whereCollectiveRoundRobinOwner
      });
      const collectiveRoundRobinBookingsAttendee2 = await this.prismaClient.booking.count({
        where: whereCollectiveRoundRobinBookingsAttendee
      });
      let managedBookings2 = 0;
      if (includeManagedEvents) {
        managedBookings2 = await this.prismaClient.booking.count({
          where: whereManagedBookings
        });
      }
      const totalNrOfBooking = collectiveRoundRobinBookingsOwner2 + collectiveRoundRobinBookingsAttendee2 + managedBookings2;
      return totalNrOfBooking;
    }
    const collectiveRoundRobinBookingsOwner = await this.prismaClient.booking.findMany({
      where: whereCollectiveRoundRobinOwner
    });
    const collectiveRoundRobinBookingsAttendee = await this.prismaClient.booking.findMany({
      where: whereCollectiveRoundRobinBookingsAttendee
    });
    let managedBookings = [];
    if (includeManagedEvents) {
      managedBookings = await this.prismaClient.booking.findMany({
        where: whereManagedBookings
      });
    }
    return [
      ...collectiveRoundRobinBookingsOwner,
      ...collectiveRoundRobinBookingsAttendee,
      ...managedBookings
    ];
  }
  async getValidBookingFromEventTypeForAttendee({
    eventTypeId,
    bookerEmail,
    bookerPhoneNumber,
    startTime,
    filterForUnconfirmed
  }) {
    return await this.prismaClient.booking.findFirst({
      where: {
        eventTypeId,
        attendees: {
          some: {
            email: bookerEmail,
            phoneNumber: bookerPhoneNumber
          }
        },
        startTime,
        status: filterForUnconfirmed ? BookingStatus.PENDING : BookingStatus.ACCEPTED
      },
      include: {
        attendees: true,
        references: true,
        user: true
      }
    });
  }
  async countBookingsByEventTypeAndDateRange({
    eventTypeId,
    startDate,
    endDate,
    excludedUid
  }) {
    return await this.prismaClient.booking.count({
      where: {
        status: BookingStatus.ACCEPTED,
        eventTypeId,
        startTime: {
          gte: startDate
        },
        endTime: {
          lte: endDate
        },
        uid: {
          not: excludedUid
        }
      }
    });
  }
}
export {
  BookingRepository as B
};
