import { prisma } from "../constants";
import { ScheduleController } from "../controllers/ScheduleController";

const scheduleIncludes = {
  status: true,
  type: true,
  scheduleSpan: true,
} as const;

export const schedules = {
  async fetch(identifier: string | number): Promise<ScheduleController> {
    const isNumeric =
      typeof identifier === "number" || /^\d+$/.test(String(identifier));

    const schedule = await prisma.schedule.findFirst({
      where: isNumeric
        ? { id: Number(identifier) }
        : { uid: String(identifier) },
      include: scheduleIncludes,
    });

    if (!schedule) throw new Error("Unknown schedule.");

    return new ScheduleController(schedule);
  },

  async count() {
    return await prisma.schedule.count();
  },

  async fetchPages(page: number, rpp: number) {
    page = page.valueOf();
    rpp = rpp.valueOf();

    const skip = (page > 1 ? page : 0) * rpp;
    const take = rpp ?? 30;

    const data = await prisma.schedule.findMany({
      skip,
      take,
      include: scheduleIncludes,
      orderBy: { startDate: "desc" },
    });

    return data.map((s) => new ScheduleController(s));
  },

  async search(query: string, page: number, rpp: number) {
    page = page.valueOf();
    rpp = rpp.valueOf();

    const skip = (page > 1 ? page : 0) * rpp;
    const take = rpp ?? 30;

    const numericQuery = parseInt(query, 10);

    const data = await prisma.schedule.findMany({
      where: {
        OR: [
          { name: { contains: query, mode: "insensitive" } },
          { description: { contains: query, mode: "insensitive" } },
          { uid: { contains: query, mode: "insensitive" } },
          ...(!isNaN(numericQuery) ? [{ id: numericQuery }] : []),
        ],
      },
      skip,
      take,
      include: scheduleIncludes,
      orderBy: { startDate: "desc" },
    });

    return data.map((s) => new ScheduleController(s));
  },

  async fetchByMemberDateRange(
    memberId: string,
    startDate: Date,
    endDate: Date
  ) {
    const data = await prisma.schedule.findMany({
      where: {
        memberId,
        startDate: { gte: startDate },
        endDate: { lte: endDate },
      },
      include: scheduleIncludes,
      orderBy: { startDate: "asc" },
    });

    return data.map((s) => new ScheduleController(s));
  },
};
