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

export async function GET() {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const schedules = await prisma.feeSchedule.findMany({
    where: { institutionId: session.institutionId },
    orderBy: [{ dueDate: "desc" }, { id: "desc" }],
    take: 200,
    include: {
      feeHead: { select: { name: true, nameBn: true, type: true } },
      student: { select: { id: true, roll: true, name: true } },
      classItem: { select: { name: true, nameBn: true } },
      payments: { select: { amount: true } },
    },
  });

  const result = schedules.map((fs) => {
    const paid = fs.payments.reduce((sum, p) => sum + Number(p.amount), 0);
    const total = Number(fs.amount);
    return {
      id: fs.id,
      title: fs.title,
      headName: fs.feeHead.name,
      headNameBn: fs.feeHead.nameBn,
      headType: fs.feeHead.type,
      student: fs.student,
      className: fs.classItem?.name ?? null,
      classNameBn: fs.classItem?.nameBn ?? null,
      amount: total,
      paid,
      due: Math.max(0, total - paid),
      status: paid >= total ? "PAID" : paid > 0 ? "PARTIAL" : "DUE",
      dueDate: fs.dueDate,
      month: fs.month,
      createdAt: fs.createdAt,
    };
  });

  return NextResponse.json({ schedules: result });
}

/** Assign a fee: to one student or expanded to every student of a class. */
export async function POST(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const feeHeadId = Number(body.feeHeadId);
    const studentId = body.studentId ? Number(body.studentId) : null;
    const classItemId = body.classItemId ? Number(body.classItemId) : null;
    const amount = Number(body.amount);
    const title = String(body.title ?? "").trim();
    const dueDate = body.dueDate ? new Date(body.dueDate) : new Date();
    const month = String(body.month ?? "").trim() || null;
    const note = String(body.note ?? "").trim() || null;

    if (!title || !Number.isFinite(amount) || amount <= 0) {
      return NextResponse.json({ error: "Invalid data" }, { status: 400 });
    }
    if (!studentId && !classItemId) {
      return NextResponse.json({ error: "TARGET_REQUIRED" }, { status: 400 });
    }

    const head = await prisma.feeHead.findFirst({
      where: { id: feeHeadId, institutionId: session.institutionId },
    });
    if (!head) return NextResponse.json({ error: "Fee head not found" }, { status: 404 });

    // Per-student assignment
    if (studentId) {
      const student = await prisma.student.findFirst({
        where: { id: studentId, institutionId: session.institutionId },
      });
      if (!student) return NextResponse.json({ error: "Student not found" }, { status: 404 });
      const created = await prisma.feeSchedule.create({
        data: {
          institutionId: session.institutionId,
          feeHeadId, studentId, amount, title, dueDate, month, note,
        },
      });
      return NextResponse.json({ created: 1, schedule: created });
    }

    // Per-class: expand to every active student in the class
    const students = await prisma.student.findMany({
      where: { institutionId: session.institutionId, classItemId, status: "ACTIVE" },
      select: { id: true },
    });
    if (students.length === 0) {
      return NextResponse.json({ error: "NO_STUDENTS_IN_CLASS" }, { status: 400 });
    }

    await prisma.feeSchedule.createMany({
      data: students.map((s) => ({
        institutionId: session.institutionId!,
        feeHeadId,
        studentId: s.id,
        classItemId,
        amount,
        title,
        dueDate,
        month,
        note,
      })),
    });
    return NextResponse.json({ created: students.length });
  } catch {
    return NextResponse.json({ error: "Could not assign fee" }, { status: 500 });
  }
}
