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

/* Materialize subject-fee assignments for one month into FeeSchedule rows
   (one row per student × subject: title = subject name, month = "YYYY-MM",
   note = "subject-fee", dedicated "Subject Fee" head). Existing rows for
   the same student+month+subject are skipped, so regenerating is safe.
   After generation, the normal collect flow / dashboard / member statement
   handle the money — no special collection path is needed. */
export async function POST(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session?.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  const institutionId = session.institutionId;
  const body = (await req.json().catch(() => ({}))) as { month?: string; classItemId?: number };
  const month = (body.month ?? "").trim();

  const inst = await prisma.institution.findUnique({
    where: { id: institutionId },
    select: { subjectFeeEnabled: true },
  });
  if (!inst?.subjectFeeEnabled) {
    return NextResponse.json({ error: "FEATURE_DISABLED" }, { status: 403 });
  }
  if (!/^\d{4}-(0[1-9]|1[0-2])$/.test(month)) {
    return NextResponse.json({ error: "MONTH_REQUIRED" }, { status: 400 });
  }

  // dedicated fee head for subject fees (auto-created once)
  let head = await prisma.feeHead.findFirst({
    where: { institutionId, name: "Subject Fee" },
    select: { id: true },
  });
  if (!head) {
    head = await prisma.feeHead.create({
      data: { institutionId, name: "Subject Fee", type: "TUITION", defaultAmount: 0 },
      select: { id: true },
    });
  }

  const assignments = await prisma.studentSubjectFee.findMany({
    where: {
      institutionId,
      ...(body.classItemId ? { student: { classItemId: body.classItemId } } : {}),
    },
    select: {
      studentId: true,
      monthlyFee: true,
      subjectItem: { select: { id: true, name: true } },
    },
    orderBy: { studentId: "asc" },
  });
  if (assignments.length === 0) {
    return NextResponse.json({ created: 0, skipped: 0 });
  }

  // which student+subject already have a schedule for this month?
  const studentIds = [...new Set(assignments.map((a) => a.studentId))];
  const existing = await prisma.feeSchedule.findMany({
    where: {
      institutionId,
      month,
      note: "subject-fee",
      studentId: { in: studentIds },
    },
    select: { studentId: true, title: true },
  });
  const done = new Set(existing.map((e) => `${e.studentId}:${e.title}`));

  const dueDate = new Date(`${month}-10T00:00:00Z`);
  let created = 0;
  const rows: {
    institutionId: number;
    feeHeadId: number;
    studentId: number;
    title: string;
    amount: number;
    dueDate: Date;
    month: string;
    note: string;
  }[] = [];
  for (const a of assignments) {
    const key = `${a.studentId}:${a.subjectItem.name}`;
    if (done.has(key)) continue;
    rows.push({
      institutionId,
      feeHeadId: head.id,
      studentId: a.studentId,
      title: a.subjectItem.name,
      amount: Number(a.monthlyFee),
      dueDate,
      month,
      note: "subject-fee",
    });
    created++;
  }
  if (rows.length > 0) {
    await prisma.feeSchedule.createMany({ data: rows });
  }

  return NextResponse.json({ created, skipped: assignments.length - created });
}
