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

/** Results (point table) of one competition — with student identity. */
export async function GET(req: Request) {
  const session = await requireAnyRole(["INSTITUTION_ADMIN", "TEACHER", "STUDENT", "PARENT"]);
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  const competitionId = Number(new URL(req.url).searchParams.get("competitionId"));
  if (!competitionId) return NextResponse.json({ error: "Missing competition" }, { status: 400 });

  const competition = await prisma.competition.findFirst({
    where: { id: competitionId, institutionId: session.institutionId },
    select: { id: true, name: true, status: true },
  });
  if (!competition) return NextResponse.json({ error: "Not found" }, { status: 404 });

  const results = await prisma.competitionResult.findMany({
    where: { competitionId },
    orderBy: [{ rank: "asc" }, { points: "desc" }],
    include: {
      student: { select: { id: true, roll: true, name: true, nameBn: true } },
    },
  });

  return NextResponse.json({
    competition,
    results: results.map((r) => ({
      id: r.id,
      studentId: r.studentId,
      roll: r.student.roll,
      name: r.student.name,
      nameBn: r.student.nameBn,
      rank: r.rank,
      points: r.points,
      remarks: r.remarks,
      publishedAt: r.publishedAt,
    })),
  });
}

/** Replace the point table: { competitionId, results: [{studentId, rank, points, remarks}] }. */
export async function PUT(req: Request) {
  const session = await requireAnyRole(["INSTITUTION_ADMIN", "TEACHER"]);
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const competitionId = Number(body.competitionId);
    const rows: { studentId: number; rank: number; points: number; remarks?: string }[] =
      Array.isArray(body.results) ? body.results : [];
    if (!competitionId) return NextResponse.json({ error: "Missing competition" }, { status: 400 });

    const competition = await prisma.competition.findFirst({
      where: { id: competitionId, institutionId: session.institutionId },
      select: { id: true },
    });
    if (!competition) return NextResponse.json({ error: "Not found" }, { status: 404 });

    // students must belong to this institution
    const studentIds = [...new Set(rows.map((r) => Number(r.studentId)).filter(Boolean))];
    const valid = await prisma.student.findMany({
      where: { id: { in: studentIds }, institutionId: session.institutionId },
      select: { id: true },
    });
    const validIds = new Set(valid.map((s) => s.id));

    const previous = await prisma.competitionResult.findMany({
      where: { competitionId },
      select: { studentId: true, publishedAt: true },
    });
    const publishedBefore = new Map(previous.map((p) => [p.studentId, p.publishedAt]));

    await prisma.$transaction([
      prisma.competitionResult.deleteMany({ where: { competitionId } }),
      ...rows
        .filter((r) => validIds.has(Number(r.studentId)))
        .map((r) =>
          prisma.competitionResult.create({
            data: {
              competitionId,
              studentId: Number(r.studentId),
              rank: Math.max(1, Math.round(Number(r.rank) || 1)),
              points: Math.max(0, Math.round(Number(r.points) || 0)),
              remarks: r.remarks ? String(r.remarks).slice(0, 200) : null,
              // keep published entries published when re-saved
              publishedAt: publishedBefore.get(Number(r.studentId)) ?? null,
            },
          })
        ),
    ]);
    return NextResponse.json({ ok: true });
  } catch {
    return NextResponse.json({ error: "Could not save results" }, { status: 500 });
  }
}

/** Publish / unpublish: { competitionId, publish }. */
export async function PATCH(req: Request) {
  const session = await requireAnyRole(["INSTITUTION_ADMIN", "TEACHER"]);
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const competitionId = Number(body.competitionId);
    if (!competitionId) return NextResponse.json({ error: "Missing competition" }, { status: 400 });

    const competition = await prisma.competition.findFirst({
      where: { id: competitionId, institutionId: session.institutionId },
      select: { id: true },
    });
    if (!competition) return NextResponse.json({ error: "Not found" }, { status: 404 });

    await prisma.competitionResult.updateMany({
      where: { competitionId },
      data: { publishedAt: body.publish ? new Date() : null },
    });
    return NextResponse.json({ ok: true });
  } catch {
    return NextResponse.json({ error: "Could not publish" }, { status: 500 });
  }
}
