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

/** Communication panel: threads (students + admission applicants) and messages. */
export async function GET(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const url = new URL(req.url);
  const studentId = url.searchParams.get("studentId");
  const admissionId = url.searchParams.get("admissionId");

  // Load one thread's messages
  if (studentId || admissionId) {
    const where = studentId
      ? { institutionId: session.institutionId, studentId: Number(studentId) }
      : { institutionId: session.institutionId, admissionId: Number(admissionId) };
    const messages = await prisma.message.findMany({
      where,
      orderBy: { createdAt: "asc" },
      take: 200,
    });
    return NextResponse.json({ messages });
  }

  // Load the thread list: latest message per student / per admission
  const [students, admissions, messages] = await Promise.all([
    prisma.student.findMany({
      where: { institutionId: session.institutionId },
      orderBy: { roll: "asc" },
      select: { id: true, roll: true, name: true, nameBn: true, photoUrl: true },
    }),
    prisma.admission.findMany({
      where: { institutionId: session.institutionId },
      orderBy: { createdAt: "desc" },
      select: { id: true, studentName: true, status: true, createdAt: true },
    }),
    prisma.message.findMany({
      where: { institutionId: session.institutionId },
      orderBy: { createdAt: "asc" },
      select: {
        id: true, studentId: true, admissionId: true, sender: true,
        senderName: true, body: true, createdAt: true,
      },
    }),
  ]);

  // group messages per thread (asc order)
  const groups = new Map<string, (typeof messages)[number][]>();
  for (const m of messages) {
    const key = m.studentId ? `s-${m.studentId}` : m.admissionId ? `a-${m.admissionId}` : null;
    if (!key) continue;
    const list = groups.get(key) ?? [];
    list.push(m);
    groups.set(key, list);
  }

  /** unread = messages from the other side that came after the institution's
      last reply (or all of them when the institution never replied) */
  const unreadOf = (list: (typeof messages)[number][]) => {
    let lastReplyIdx = -1;
    for (let i = list.length - 1; i >= 0; i--) {
      if (list[i].sender === "INSTITUTION") {
        lastReplyIdx = i;
        break;
      }
    }
    return list.filter((m, i) => m.sender !== "INSTITUTION" && i > lastReplyIdx).length;
  };

  const threadOf = (key: string) => {
    const list = groups.get(key) ?? [];
    return { lastMessage: list[list.length - 1] ?? null, unread: unreadOf(list), total: list.length };
  };

  const studentThreads = students.map((s) => {
    const t = threadOf(`s-${s.id}`);
    return {
      kind: "STUDENT" as const,
      id: s.id,
      name: s.name,
      nameBn: s.nameBn,
      photoUrl: s.photoUrl,
      subtitle: `Roll ${s.roll}`,
      unread: t.unread,
      total: t.total,
      lastMessage: t.lastMessage,
    };
  });

  const admissionThreads = admissions.map((a) => {
    const t = threadOf(`a-${a.id}`);
    return {
      kind: "ADMISSION" as const,
      id: a.id,
      name: a.studentName,
      nameBn: null as string | null,
      photoUrl: null as string | null,
      subtitle: a.status,
      unread: t.unread,
      total: t.total,
      lastMessage: t.lastMessage,
    };
  });

  const threads = [...studentThreads, ...admissionThreads]
    .filter((t) => t.lastMessage)
    .sort(
      (a, b) =>
        new Date(b.lastMessage!.createdAt).getTime() - new Date(a.lastMessage!.createdAt).getTime()
    );

  // everyone the institution can start a conversation with
  return NextResponse.json({
    threads,
    people: {
      students: studentThreads
        .filter((t) => !t.lastMessage)
        .map((t) => ({ kind: "STUDENT" as const, id: t.id, name: t.name, nameBn: t.nameBn, subtitle: t.subtitle })),
      admissions: admissionThreads
        .filter((t) => !t.lastMessage)
        .map((t) => ({ kind: "ADMISSION" as const, id: t.id, name: t.name, nameBn: null as string | null, subtitle: t.subtitle })),
    },
  });
}

/** Send a message from the institution to a student thread or admission thread. */
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 studentId = body.studentId ? Number(body.studentId) : null;
    const admissionId = body.admissionId ? Number(body.admissionId) : null;
    const text = String(body.body ?? "").trim().slice(0, 2000);

    if (!text || (!studentId && !admissionId)) {
      return NextResponse.json({ error: "Invalid message" }, { status: 400 });
    }

    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 });
    } else if (admissionId) {
      const admission = await prisma.admission.findFirst({
        where: { id: admissionId, institutionId: session.institutionId },
      });
      if (!admission) return NextResponse.json({ error: "Admission not found" }, { status: 404 });
    }

    const message = await prisma.message.create({
      data: {
        institutionId: session.institutionId,
        studentId,
        admissionId,
        sender: "INSTITUTION",
        senderName: session.name,
        body: text,
      },
    });
    return NextResponse.json({ message });
  } catch {
    return NextResponse.json({ error: "Could not send" }, { status: 500 });
  }
}
