import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireCampusInstitution } from "@/lib/auth";

const DAYS = ["SAT", "SUN", "MON", "TUE", "WED", "THU", "FRI"];

/** Weekly course routine — slots of the institution's offerings.
    Filters: ?programId=&sessionYear= */
export async function GET(req: Request) {
  const session = await requireCampusInstitution();
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const sp = new URL(req.url).searchParams;
  const programId = Number(sp.get("programId"));
  const sessionYear = (sp.get("sessionYear") ?? "").trim();
  const slots = await prisma.cuCourseSlot.findMany({
    where: {
      institutionId: session.institutionId,
      ...(sessionYear ? { offering: { sessionYear } } : {}),
      ...(Number.isFinite(programId) && programId > 0 ? { offering: { course: { programId } } } : {}),
    },
    orderBy: [{ dayOfWeek: "asc" }, { startTime: "asc" }],
    include: {
      offering: {
        select: {
          id: true, sessionYear: true, section: true,
          course: { select: { id: true, code: true, name: true, nameBn: true, credits: true, program: { select: { id: true, name: true, nameBn: true } }, term: { select: { id: true, name: true, nameBn: true } } } },
          staff: { select: { id: true, name: true, nameBn: true } },
        },
      },
    },
  });
  return NextResponse.json({ slots });
}

/** Add a slot: { offeringId, dayOfWeek, startTime, endTime, room?, note? } —
    rejected when the teacher, the room or the same course is already busy
    in an overlapping time on that day. */
export async function POST(req: Request) {
  const session = await requireCampusInstitution();
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const offeringId = Number(body.offeringId);
    const dayOfWeek = String(body.dayOfWeek ?? "");
    const startTime = String(body.startTime ?? "");
    const endTime = String(body.endTime ?? "");
    if (!Number.isFinite(offeringId) || offeringId <= 0 || !DAYS.includes(dayOfWeek) || !/^\d{2}:\d{2}$/.test(startTime) || !/^\d{2}:\d{2}$/.test(endTime)) {
      return NextResponse.json({ error: "Missing or invalid fields" }, { status: 400 });
    }
    if (endTime <= startTime) {
      return NextResponse.json({ error: "END_BEFORE_START" }, { status: 400 });
    }

    const offering = await prisma.cuOffering.findFirst({
      where: { id: offeringId, institutionId: session.institutionId },
      select: { id: true, staffId: true },
    });
    if (!offering) return NextResponse.json({ error: "Invalid offering" }, { status: 400 });

    // clash detection: same institution + day + overlapping time against
    // the same teacher, the same room or the same course offering
    const sameDay = await prisma.cuCourseSlot.findMany({
      where: { institutionId: session.institutionId, dayOfWeek },
      select: { offeringId: true, startTime: true, endTime: true, room: true, offering: { select: { staffId: true, courseId: true } } },
    });
    const room = String(body.room ?? "").trim() || null;
    const overlaps = (aS: string, aE: string, bS: string, bE: string) => aS < bE && bS < aE;
    for (const s of sameDay) {
      if (!overlaps(startTime, endTime, s.startTime, s.endTime)) continue;
      const sameCourse = s.offeringId === offering.id;
      const sameTeacher = offering.staffId !== null && s.offering.staffId === offering.staffId;
      const sameRoom = room !== null && s.room === room;
      if (sameCourse || sameTeacher || sameRoom) {
        return NextResponse.json({ error: sameCourse ? "COURSE_CLASH" : sameTeacher ? "TEACHER_CLASH" : "ROOM_CLASH" }, { status: 409 });
      }
    }

    const slot = await prisma.cuCourseSlot.create({
      data: {
        institutionId: session.institutionId,
        offeringId,
        dayOfWeek,
        startTime,
        endTime,
        room,
        note: String(body.note ?? "").trim() || null,
      },
      include: {
        offering: {
          select: {
            id: true, sessionYear: true, section: true,
            course: { select: { id: true, code: true, name: true, nameBn: true, credits: true, program: { select: { id: true, name: true, nameBn: true } }, term: { select: { id: true, name: true, nameBn: true } } } },
            staff: { select: { id: true, name: true, nameBn: true } },
          },
        },
      },
    });
    return NextResponse.json({ slot });
  } catch {
    return NextResponse.json({ error: "Could not add slot" }, { status: 500 });
  }
}
