import { prisma } from "@pmap/database";
import { enrollSchema } from "@pmap/validation";
import { sessionsOverlap } from "@pmap/utilities";
import { fail, ok } from "../_lib";

type LockedSessionRow = {
  id: string;
  capacity: number | null;
  startsAt: Date;
  endsAt: Date;
  published: boolean;
  cancelled: boolean;
  enrollmentOpensAt: Date | null;
  enrollmentClosesAt: Date | null;
};

export async function POST(request: Request) {
  const body = await request.json().catch(() => null);
  const parsed = enrollSchema.safeParse(body);
  if (!parsed.success) return fail(request, "VALIDATION_ERROR", "Invalid enrollment request.", 422, parsed.error.flatten());

  try {
    const enrollment = await prisma.$transaction(async (tx) => {
      const rows = await tx.$queryRaw<LockedSessionRow[]>`
        SELECT id, capacity, startsAt, endsAt, published, cancelled, enrollmentOpensAt, enrollmentClosesAt
        FROM Session
        WHERE id = ${parsed.data.sessionId}
        FOR UPDATE
      `;
      const session = rows[0];
      if (!session) throw new Error("Session not found.");
      if (!session.published || session.cancelled) throw new Error("Session is unavailable.");

      const now = new Date();
      if (session.enrollmentOpensAt && now < session.enrollmentOpensAt) throw new Error("Enrollment is not open yet.");
      if (session.enrollmentClosesAt && now > session.enrollmentClosesAt) throw new Error("Enrollment is closed.");

      const participant = await tx.participantProfile.findUnique({ where: { id: parsed.data.participantId } });
      if (!participant || participant.verificationStatus !== "VERIFIED") throw new Error("Only verified participants can enroll.");

      const existing = await tx.sessionEnrollment.findUnique({
        where: { sessionId_participantId: { sessionId: parsed.data.sessionId, participantId: parsed.data.participantId } }
      });
      if (existing?.status === "ENROLLED") throw new Error("Participant is already enrolled.");

      const activeEnrollments = await tx.sessionEnrollment.findMany({
        where: { participantId: parsed.data.participantId, status: "ENROLLED" },
        include: { session: true }
      });
      const conflicting = activeEnrollments.find((item) => sessionsOverlap(item.session.startsAt, item.session.endsAt, session.startsAt, session.endsAt));
      if (conflicting && !parsed.data.overrideReason) throw new Error("Selected session conflicts with an existing enrollment.");

      const enrolledCount = await tx.sessionEnrollment.count({ where: { sessionId: parsed.data.sessionId, status: "ENROLLED" } });
      if (session.capacity !== null && enrolledCount >= session.capacity) {
        const position = await tx.sessionWaitlist.count({ where: { sessionId: parsed.data.sessionId } }) + 1;
        await tx.sessionWaitlist.upsert({
          where: { sessionId_participantId: { sessionId: parsed.data.sessionId, participantId: parsed.data.participantId } },
          update: { status: "WAITING", position },
          create: { sessionId: parsed.data.sessionId, participantId: parsed.data.participantId, position, status: "WAITING" }
        });
        return { status: "WAITLISTED", position };
      }

      const overrideReason = parsed.data.overrideReason ?? null;
      const created = await tx.sessionEnrollment.upsert({
        where: { sessionId_participantId: { sessionId: parsed.data.sessionId, participantId: parsed.data.participantId } },
        update: { status: "ENROLLED", overrideReason },
        create: { sessionId: parsed.data.sessionId, participantId: parsed.data.participantId, status: "ENROLLED", overrideReason }
      });

      await tx.sessionEnrollmentHistory.create({
        data: {
          sessionId: parsed.data.sessionId,
          participantId: parsed.data.participantId,
          toStatus: "ENROLLED",
          reason: overrideReason
        }
      });

      return { status: created.status, enrollmentId: created.id };
    });

    return ok(request, enrollment);
  } catch (error) {
    return fail(request, "ENROLLMENT_REJECTED", error instanceof Error ? error.message : "Enrollment failed.", 409);
  }
}
