"use strict";
const index = require("./i18n-Bs8xJzoY.cjs");
const user = require("./user-7XDeDEMd.cjs");
const eventTypeSelect = {
  id: true,
  teamId: true,
  schedulingType: true,
  userId: true,
  metadata: true,
  description: true,
  interfaceLanguage: true,
  hidden: true,
  slug: true,
  length: true,
  title: true,
  requiresConfirmation: true,
  canSendCalVideoTranscriptionEmails: true,
  requiresConfirmationForFreeEmail: true,
  requiresConfirmationWillBlockSlot: true,
  autoTranslateDescriptionEnabled: true,
  position: true,
  offsetStart: true,
  owner: {
    select: {
      timeZone: true
    }
  },
  profileId: true,
  eventName: true,
  parentId: true,
  timeZone: true,
  periodType: true,
  periodStartDate: true,
  periodEndDate: true,
  periodDays: true,
  periodCountCalendarDays: true,
  lockTimeZoneToggleOnBookingPage: true,
  lockedTimeZone: true,
  requiresBookerEmailVerification: true,
  disableGuests: true,
  disableCancelling: true,
  disableRescheduling: true,
  allowReschedulingCancelledBookings: true,
  hideCalendarNotes: true,
  minimumBookingNotice: true,
  beforeEventBuffer: true,
  afterEventBuffer: true,
  seatsPerTimeSlot: true,
  onlyShowFirstAvailableSlot: true,
  allowReschedulingPastBookings: true,
  hideOrganizerEmail: true,
  showOptimizedSlots: true,
  seatsShowAttendees: true,
  seatsShowAvailabilityCount: true,
  scheduleId: true,
  instantMeetingScheduleId: true,
  price: true,
  currency: true,
  slotInterval: true,
  successRedirectUrl: true,
  isInstantEvent: true,
  instantMeetingExpiryTimeOffsetInSeconds: true,
  instantMeetingParameters: true,
  aiPhoneCallConfig: true,
  assignAllTeamMembers: true,
  isRRWeightsEnabled: true,
  rescheduleWithSameRoundRobinHost: true,
  recurringEvent: true,
  locations: true,
  bookingFields: true,
  useEventTypeDestinationCalendarEmail: true,
  secondaryEmailId: true,
  bookingLimits: true,
  durationLimits: true,
  eventTypeColor: true,
  hideCalendarEventDetails: true,
  rrSegmentQueryValue: true,
  assignRRMembersUsingSegment: true,
  maxLeadThreshold: true,
  useEventLevelSelectedCalendars: true,
  customReplyToEmail: true,
  restrictionScheduleId: true,
  useBookerTimezone: true,
  instantMeetingSchedule: {
    select: {
      id: true,
      name: true
    }
  }
};
const log = index.logger.getSubLogger({ prefix: ["repository/membership"] });
const membershipSelect = {
  id: true,
  teamId: true,
  userId: true,
  accepted: true,
  role: true,
  disableImpersonation: true
};
const teamParentSelect = {
  id: true,
  name: true,
  slug: true,
  logoUrl: true,
  parentId: true,
  metadata: true
};
const userSelect = {
  name: true,
  avatarUrl: true,
  username: true,
  id: true,
  timeZone: true
};
const getWhereForfindAllByUpId = async (upId, where) => {
  const lookupTarget = user.ProfileRepository.getLookupTarget(upId);
  let prismaWhere;
  if (lookupTarget.type === user.LookupTarget.Profile) {
    const profile = await user.ProfileRepository.findById(lookupTarget.id);
    if (!profile) {
      return [];
    }
    prismaWhere = {
      userId: profile.user.id,
      ...where
    };
  } else {
    prismaWhere = {
      userId: lookupTarget.id,
      ...where
    };
  }
  return prismaWhere;
};
class MembershipRepository {
  constructor(prismaClient = index.prisma) {
    this.prismaClient = prismaClient;
  }
  async hasMembership({ userId, teamId }) {
    const membership = await this.prismaClient.membership.findFirst({
      where: {
        userId,
        teamId,
        accepted: true
      },
      select: {
        id: true
      }
    });
    return !!membership;
  }
  async listAcceptedTeamMemberIds({ teamId }) {
    const memberships = await this.prismaClient.membership.findMany({
      where: {
        teamId,
        accepted: true
      },
      select: {
        userId: true
      }
    }) || [];
    const teamMemberIds = memberships.map((membership) => membership.userId);
    return teamMemberIds;
  }
  static async create(data) {
    return await index.prisma.membership.create({
      data: {
        createdAt: /* @__PURE__ */ new Date(),
        ...data
      }
    });
  }
  static async findFirstAcceptedMembershipByUserId(userId) {
    return await index.prisma.membership.findFirst({
      where: {
        accepted: true,
        userId,
        team: {
          slug: {
            not: null
          }
        }
      }
    });
  }
  static async createMany(data) {
    return await index.prisma.membership.createMany({
      data: data.map((item) => ({
        createdAt: /* @__PURE__ */ new Date(),
        ...item
      }))
    });
  }
  /**
   * TODO: Using a specific function for specific tasks so that we don't have to focus on TS magic at the moment. May be try to make it a a generic findAllByProfileId with various options.
   */
  static async findAllByUpIdIncludeTeamWithMembersAndEventTypes({ upId }, { where } = {}) {
    const prismaWhere = await getWhereForfindAllByUpId(upId, where);
    if (Array.isArray(prismaWhere)) {
      return prismaWhere;
    }
    log.debug(
      "findAllByUpIdIncludeTeamWithMembersAndEventTypes",
      index.safeStringify({
        prismaWhere
      })
    );
    return await index.prisma.membership.findMany({
      where: prismaWhere,
      include: {
        team: {
          include: {
            members: {
              select: membershipSelect
            },
            parent: {
              select: teamParentSelect
            },
            eventTypes: {
              select: {
                ...eventTypeSelect,
                hashedLink: true,
                users: { select: userSelect },
                children: {
                  include: {
                    users: { select: userSelect }
                  }
                },
                hosts: {
                  include: {
                    user: { select: userSelect }
                  }
                },
                team: {
                  select: {
                    id: true,
                    members: {
                      select: {
                        user: {
                          select: {
                            timeZone: true
                          }
                        }
                      },
                      take: 1
                    }
                  }
                }
              },
              // As required by getByViewHandler - Make it configurable
              orderBy: [
                {
                  position: "desc"
                },
                {
                  id: "asc"
                }
              ]
            }
          }
        }
      }
    });
  }
  static async findAllByUpIdIncludeMinimalEventTypes({ upId }, { where, skipEventTypes = false } = {}) {
    const prismaWhere = await getWhereForfindAllByUpId(upId, where);
    if (Array.isArray(prismaWhere)) {
      return prismaWhere;
    }
    log.debug(
      "findAllByUpIdIncludeMinimalEventTypes",
      index.safeStringify({
        prismaWhere
      })
    );
    const select = {
      id: true,
      teamId: true,
      userId: true,
      accepted: true,
      role: true,
      disableImpersonation: true,
      team: {
        select: {
          ...teamParentSelect,
          isOrganization: true,
          parent: {
            select: teamParentSelect
          },
          ...!skipEventTypes ? {
            eventTypes: {
              select: {
                ...eventTypeSelect,
                hashedLink: true,
                children: { select: { id: true } }
              },
              orderBy: [
                {
                  position: "desc"
                },
                {
                  id: "asc"
                }
              ]
            }
          } : {}
        }
      }
    };
    return await index.prisma.membership.findMany({
      where: prismaWhere,
      select
    });
  }
  static async findAllByUpIdIncludeTeam({ upId }, { where } = {}) {
    const prismaWhere = await getWhereForfindAllByUpId(upId, where);
    if (Array.isArray(prismaWhere)) {
      return prismaWhere;
    }
    return await index.prisma.membership.findMany({
      where: prismaWhere,
      include: {
        team: {
          include: {
            parent: {
              select: teamParentSelect
            }
          }
        }
      }
    });
  }
  static async findUniqueByUserIdAndTeamId({ userId, teamId }) {
    return await index.prisma.membership.findUnique({
      where: {
        userId_teamId: {
          userId,
          teamId
        }
      }
    });
  }
  static async findByTeamIdForAvailability({ teamId }) {
    const memberships = await index.prisma.membership.findMany({
      where: { teamId },
      include: {
        user: {
          select: {
            credentials: {
              select: index.credentialForCalendarServiceSelect
            },
            // needed for getUserAvailability
            ...index.availabilityUserSelect
          }
        }
      }
    });
    const membershipsWithSelectedCalendars = memberships.map((m) => {
      return {
        ...m,
        user: user.withSelectedCalendars(m.user)
      };
    });
    return membershipsWithSelectedCalendars;
  }
  static async findMembershipsForBothOrgAndTeam({ orgId, teamId }) {
    const memberships = await index.prisma.membership.findMany({
      where: {
        teamId: {
          in: [orgId, teamId]
        }
      }
    });
    const { teamMemberships, orgMemberships } = memberships.reduce(
      (acc, membership) => {
        if (membership.teamId === teamId) {
          acc.teamMemberships.push(membership);
        } else if (membership.teamId === orgId) {
          acc.orgMemberships.push(membership);
        }
        return acc;
      },
      { teamMemberships: [], orgMemberships: [] }
    );
    return {
      teamMemberships,
      orgMemberships
    };
  }
  static async getAdminOrOwnerMembership(userId, teamId) {
    return index.prisma.membership.findFirst({
      where: {
        userId,
        teamId,
        accepted: true,
        role: {
          in: [index.MembershipRole.ADMIN, index.MembershipRole.OWNER]
        }
      },
      select: {
        id: true
      }
    });
  }
  static async findAllAcceptedPublishedTeamMemberships(userId, tx) {
    return (tx ?? index.prisma).membership.findMany({
      where: {
        userId,
        accepted: true,
        team: {
          slug: { not: null }
        }
      },
      select: {
        teamId: true
      }
    });
  }
  /**
   * Get all team IDs that a user is a member of
   */
  static async findUserTeamIds({ userId }) {
    const memberships = await index.prisma.membership.findMany({
      where: {
        userId,
        accepted: true
      },
      select: {
        teamId: true
      }
    });
    return memberships.map((membership) => membership.teamId);
  }
  /**
   * Returns members who joined after the given time
   */
  static async findMembershipsCreatedAfterTimeIncludeUser({
    organizationId,
    time
  }) {
    return index.prisma.membership.findMany({
      where: {
        teamId: organizationId,
        createdAt: { gt: time },
        accepted: true
      },
      include: {
        user: {
          select: {
            email: true,
            name: true,
            id: true
          }
        }
      }
    });
  }
  static async findAllByTeamIds({
    teamIds,
    select
  }) {
    return await index.prisma.membership.findMany({
      where: {
        teamId: { in: teamIds },
        accepted: true
      },
      // this is explicit, and typed in TSelect default typings
      select: select ?? { userId: true }
    });
  }
  static async findAllAcceptedTeamMemberships(userId, where) {
    const teams = await index.prisma.team.findMany({
      where: {
        members: {
          some: {
            userId,
            accepted: true,
            ...where ?? {}
          }
        }
      }
    });
    return teams;
  }
  async findTeamAdminsByTeamId({ teamId }) {
    return await this.prismaClient.membership.findMany({
      where: {
        team: {
          id: teamId,
          parentId: {
            not: null
          }
        },
        role: {
          in: ["ADMIN", "OWNER"]
        }
      },
      select: {
        user: {
          select: {
            email: true,
            locale: true
          }
        }
      }
    });
  }
}
exports.MembershipRepository = MembershipRepository;
exports.eventTypeSelect = eventTypeSelect;
