import { p as prisma, c as credentialForCalendarServiceSelect } from "./user--mpkKOwW.js";
import { b as buildCredentialPayloadForPrisma } from "./buildCredentialPayloadForCalendar-tb2TDUWC.js";
const ensureUserLevelWhere = {
  eventTypeId: null
};
class SelectedCalendarRepository {
  static async findConflicting(data) {
    return await SelectedCalendarRepository.findFirst({
      where: {
        userId: data.userId,
        integration: data.integration,
        externalId: data.externalId,
        eventTypeId: data.eventTypeId || null
      }
    });
  }
  static async findById(id) {
    return await prisma.selectedCalendar.findUnique({ where: { id } });
  }
  static async create(data) {
    const conflictingCalendar = await SelectedCalendarRepository.findConflicting(data);
    if (conflictingCalendar) {
      throw new Error(
        `Selected calendar already exists for userId: ${data.userId}, integration: ${data.integration}, externalId: ${data.externalId}, eventTypeId: ${data.eventTypeId}`
      );
    }
    return await prisma.selectedCalendar.create({
      data: {
        ...data
      }
    });
  }
  static async upsert(data) {
    const credentialPayload = buildCredentialPayloadForPrisma({
      credentialId: data.credentialId,
      delegationCredentialId: data.delegationCredentialId
    });
    const newData = {
      ...data,
      ...credentialPayload
    };
    const conflictingCalendar = await SelectedCalendarRepository.findConflicting(newData);
    if (conflictingCalendar) {
      return await prisma.selectedCalendar.update({
        where: {
          id: conflictingCalendar.id
        },
        data: newData
      });
    }
    return await prisma.selectedCalendar.create({
      data: newData
    });
  }
  static async delete({ where }) {
    const calendarsToDelete = await SelectedCalendarRepository.findMany({ where });
    if (calendarsToDelete.length === 0) {
      throw new Error("SelectedCalendar not found");
    }
    if (calendarsToDelete.length > 1) {
      throw new Error("Multiple SelectedCalendar records found to delete. deleteMany should be used instead");
    }
    return await prisma.selectedCalendar.delete({
      where: {
        id: calendarsToDelete[0].id
      }
    });
  }
  static async deleteById({ id }) {
    return await prisma.selectedCalendar.delete({
      where: {
        id
      }
    });
  }
  static async createIfNotExists(data) {
    const conflictingCalendar = await SelectedCalendarRepository.findConflicting(data);
    if (conflictingCalendar)
      return conflictingCalendar;
    return await prisma.selectedCalendar.create({
      data
    });
  }
  /** Retrieve calendars that need to be watched */
  static async getNextBatchToWatch(limit = 100) {
    const oneDayInMS = 24 * 60 * 60 * 1e3;
    const tomorrowTimestamp = String((/* @__PURE__ */ new Date()).getTime() + oneDayInMS);
    const nextBatch = await prisma.selectedCalendar.findMany({
      take: limit,
      where: {
        user: {
          teams: {
            some: {
              team: {
                features: {
                  some: {
                    featureId: "calendar-cache"
                  }
                }
              }
            }
          }
        },
        // RN we only support google calendar subscriptions for now
        integration: "google_calendar",
        AND: [
          {
            OR: [
              // Either is a calendar that has not errored
              { error: null },
              // Or is a calendar that has errored but has not reached max attempts
              {
                error: { not: null },
                watchAttempts: {
                  lt: {
                    // Using ts-ignore instead of ts-expect-error because I am seeing conflicting errors in CI. In one case ts-expect-error fails with `Unused '@ts-expect-error' directive.`
                    // Removing ts-expect-error fails in another case that _ref isn't defined
                    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                    // @ts-ignore
                    _ref: "maxAttempts",
                    _container: "SelectedCalendar"
                  }
                }
              }
            ]
          },
          {
            OR: [
              // Either is a calendar pending to be watched
              { googleChannelExpiration: null },
              // Or is a calendar that is about to expire
              { googleChannelExpiration: { lt: tomorrowTimestamp } }
            ]
          }
        ]
      }
    });
    return nextBatch;
  }
  /**
   * Retrieve calendars that are being watched but shouldn't be anymore
   * e.g. when a user disables calendar cache for the organization
   */
  static async getNextBatchToUnwatch(limit = 100) {
    const where = {
      // RN we only support google calendar subscriptions for now
      integration: "google_calendar",
      googleChannelExpiration: { not: null },
      AND: [
        {
          OR: [
            // Either is a calendar that has not errored during unwatch
            { error: null },
            // Or is a calendar that has errored during unwatch but has not reached max attempts
            {
              error: { not: null },
              unwatchAttempts: {
                lt: {
                  // Using ts-ignore instead of ts-expect-error because I am seeing conflicting errors in CI. In one case ts-expect-error fails with `Unused '@ts-expect-error' directive.`
                  // Removing ts-expect-error fails in another case that _ref isn't defined
                  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                  // @ts-ignore
                  _ref: "maxAttempts",
                  _container: "SelectedCalendar"
                }
              }
            }
          ]
        },
        {
          user: {
            teams: {
              every: {
                team: {
                  features: {
                    none: {
                      featureId: "calendar-cache"
                    }
                  }
                }
              }
            }
          }
        }
      ]
    };
    const nextBatch = await prisma.selectedCalendar.findMany({
      take: limit,
      where
    });
    return nextBatch;
  }
  static async findMany({ where, select, orderBy }) {
    return await prisma.selectedCalendar.findMany({ where, select, orderBy });
  }
  static async findUniqueOrThrow({ where }) {
    const calendars = await prisma.selectedCalendar.findMany({ where });
    if (calendars.length === 0) {
      throw new Error("SelectedCalendar not found");
    }
    return calendars[0];
  }
  static async findFirstByGoogleChannelId(googleChannelId) {
    return await prisma.selectedCalendar.findFirst({
      where: {
        googleChannelId
      },
      select: {
        credential: {
          select: {
            ...credentialForCalendarServiceSelect,
            selectedCalendars: {
              orderBy: {
                externalId: "asc"
              }
            }
          }
        }
      }
    });
  }
  static async findFirst({ where }) {
    return await prisma.selectedCalendar.findFirst({
      where
    });
  }
  static async findFirstOrThrow({ where }) {
    const calendar = await SelectedCalendarRepository.findFirst({ where });
    if (!calendar) {
      throw new Error("SelectedCalendar not found");
    }
    return calendar;
  }
  static async update(args) {
    const calendarsToUpdate = await SelectedCalendarRepository.findMany({ where: args.where });
    if (calendarsToUpdate.length === 0) {
      throw new Error("SelectedCalendar not found");
    }
    if (calendarsToUpdate.length > 1) {
      throw new Error("Multiple SelectedCalendar records found to update. updateMany should be used instead");
    }
    const calendarToUpdate = calendarsToUpdate[0];
    return await prisma.selectedCalendar.update({
      where: {
        id: calendarToUpdate.id
      },
      data: args.data
    });
  }
  /**
   * Following methods ensure that they operate on user level calendars only
   */
  static async findUserLevelUniqueOrThrow({ where }) {
    const calendars = await SelectedCalendarRepository.findUniqueOrThrow({
      where: {
        ...where,
        ...ensureUserLevelWhere
      }
    });
    if (!calendars) {
      throw new Error("SelectedCalendar not found");
    }
    return calendars;
  }
  static async findManyUserLevel(args) {
    return SelectedCalendarRepository.findMany({
      ...args,
      where: {
        ...args.where,
        ...ensureUserLevelWhere
      }
    });
  }
  static async updateUserLevel(args) {
    return SelectedCalendarRepository.update({
      where: {
        ...args.where,
        ...ensureUserLevelWhere
      },
      data: args.data
    });
  }
  static async deleteUserLevel({ where }) {
    return await SelectedCalendarRepository.delete({
      where: {
        ...where,
        ...ensureUserLevelWhere
      }
    });
  }
  static async upsertManyForEventTypeIds({
    data,
    eventTypeIds
  }) {
    const userId = data.userId;
    return await Promise.all(
      eventTypeIds.map(
        (eventTypeId) => SelectedCalendarRepository.upsert({
          ...data,
          eventTypeId,
          userId,
          integration: data.integration,
          externalId: data.externalId,
          credentialId: data.credentialId
        })
      )
    );
  }
  static async updateById(id, data) {
    return await prisma.selectedCalendar.update({
      where: { id },
      data
    });
  }
  static async updateManyByCredentialId(credentialId, data) {
    return await prisma.selectedCalendar.updateMany({
      where: { credentialId },
      data
    });
  }
  static async setErrorInWatching({ id, error }) {
    await SelectedCalendarRepository.updateById(id, {
      error,
      lastErrorAt: /* @__PURE__ */ new Date(),
      watchAttempts: { increment: 1 }
    });
  }
  static async setErrorInUnwatching({ id, error }) {
    await SelectedCalendarRepository.updateById(id, {
      error,
      lastErrorAt: /* @__PURE__ */ new Date(),
      unwatchAttempts: { increment: 1 }
    });
  }
  static async removeWatchingError({ id }) {
    await SelectedCalendarRepository.updateById(id, {
      error: null,
      lastErrorAt: null,
      watchAttempts: 0
    });
  }
  static async removeUnwatchingError({ id }) {
    await SelectedCalendarRepository.updateById(id, {
      error: null,
      lastErrorAt: null,
      unwatchAttempts: 0
    });
  }
}
export {
  SelectedCalendarRepository as S
};
