import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireRole } from "@/lib/auth";
import { bdSessionLabel, classTemplateFor, templateItemName } from "@/lib/class-templates";
import { subjectTemplateFor } from "@/lib/subject-templates";

/** Apply the standard class + subject set for the institution's type:
    creates missing catalog items and replaces the institution's class
    selections. Year-level classes are stamped with the current session;
    body.style picks word ("One") or digit ("Class 1") naming. Madrasa,
    College and University also select their Bangladesh-perspective subject
    template; school levels keep the level-tagged board subject list. */
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().catch(() => ({}));
    const style: "word" | "digit" = body.style === "digit" ? "digit" : "word";

    const me = await prisma.institution.findUnique({
      where: { id: session.institutionId },
      select: { type: true },
    });
    if (!me) return NextResponse.json({ error: "Institution not found" }, { status: 404 });

    const template = classTemplateFor(me.type, style);
    const bdSession = bdSessionLabel();
    // Madrasa/College/University: select the type's standard subject list
    const subjectTemplate = subjectTemplateFor(me.type);

    const result = await prisma.$transaction(async (tx) => {
      const applied: { id: number; name: string; nameBn: string }[] = [];

      for (const item of template) {
        const name = templateItemName(item, bdSession, false);
        const nameBn = templateItemName(item, bdSession, true);

        // find or create the catalog item (global catalog, exact name)
        let catalog = await tx.academicItem.findFirst({
          where: { category: "CLASS", name, institutionId: null },
          select: { id: true, name: true, nameBn: true },
        });
        if (!catalog) {
          catalog = await tx.academicItem.create({
            data: { category: "CLASS", name, nameBn },
            select: { id: true, name: true, nameBn: true },
          });
        }

        await tx.academicSelection.upsert({
          where: {
            institutionId_academicItemId: {
              institutionId: session.institutionId!,
              academicItemId: catalog.id,
            },
          },
          update: {},
          create: { institutionId: session.institutionId!, academicItemId: catalog.id },
        });
        applied.push(catalog);
      }

      if (subjectTemplate) {
        // Madrasa / College / University subject set — find-or-create + select
        for (const sub of subjectTemplate) {
          let catalog = await tx.academicItem.findFirst({
            where: { category: "SUBJECT", name: sub.name, institutionId: null },
            select: { id: true, name: true, nameBn: true },
          });
          if (!catalog) {
            catalog = await tx.academicItem.create({
              data: { category: "SUBJECT", name: sub.name, nameBn: sub.nameBn },
              select: { id: true, name: true, nameBn: true },
            });
          }
          await tx.academicSelection.upsert({
            where: {
              institutionId_academicItemId: {
                institutionId: session.institutionId!,
                academicItemId: catalog.id,
              },
            },
            update: {},
            create: { institutionId: session.institutionId!, academicItemId: catalog.id },
          });
        }
      } else {
        // board syllabus: school levels (primary+high / coaching) span both
        // school levels — select every subject tagged for either
        const boardSubjects = await tx.academicItem.findMany({
          where: { category: "SUBJECT", institutionId: null, isActive: true },
          select: { id: true, levels: true },
        });
        for (const sub of boardSubjects) {
          const levels = Array.isArray(sub.levels) ? (sub.levels as string[]) : null;
          if (!levels || (!levels.includes("PRIMARY") && !levels.includes("HIGH_SCHOOL"))) continue;
          await tx.academicSelection.upsert({
            where: {
              institutionId_academicItemId: {
                institutionId: session.institutionId!,
                academicItemId: sub.id,
              },
            },
            update: {},
            create: { institutionId: session.institutionId!, academicItemId: sub.id },
          });
        }
      }

      // drop class selections that are not part of this template
      const keep = new Set(applied.map((a) => a.id));
      const current = await tx.academicSelection.findMany({
        where: { institutionId: session.institutionId! },
        select: { id: true, academicItemId: true, academicItem: { select: { category: true, institutionId: true } } },
      });
      for (const sel of current) {
        if (
          sel.academicItem.category === "CLASS" &&
          sel.academicItem.institutionId === null && // own custom classes stay untouched
          !keep.has(sel.academicItemId)
        ) {
          await tx.academicSelection.delete({ where: { id: sel.id } });
        }
      }

      return applied;
    });

    return NextResponse.json({
      applied: result,
      session: bdSession,
      subjects: subjectTemplate?.length ?? null,
    });
  } catch {
    return NextResponse.json({ error: "Could not apply template" }, { status: 500 });
  }
}

