import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { sendToNode } from "@/lib/websocket";

export async function GET(req: NextRequest) {
  const { searchParams } = new URL(req.url);
  const nodeId = searchParams.get("nodeId");
  const establishmentId = searchParams.get("establishmentId");

  let where: any = {};
  if (nodeId) where.nodeId = nodeId;
  if (establishmentId) {
    const classes = await prisma.class.findMany({ where: { establishmentId }, select: { id: true } });
    const students = await prisma.student.findMany({ where: { classId: { in: classes.map((c) => c.id) } }, select: { id: true } });
    const nodes = await prisma.node.findMany({ where: { studentId: { in: students.map((s) => s.id) } }, select: { id: true } });
    where.nodeId = { in: nodes.map((n) => n.id) };
  }

  const instances = await prisma.instance.findMany({
    where,
    include: { node: { include: { student: { include: { class: true } } } }, template: true },
    orderBy: { createdAt: "desc" },
  });
  return NextResponse.json(instances);
}

export async function POST(req: NextRequest) {
  const body = await req.json();
  const { nodeId, templateId, port } = body;

  const template = await prisma.template.findUnique({ where: { id: templateId } });
  if (!template) return NextResponse.json({ error: "Template not found" }, { status: 404 });

  const instance = await prisma.instance.create({
    data: { nodeId, templateId, port: port || 8080, status: "stopped" },
  });

  const sent = sendToNode(nodeId, {
    action: "start",
    instanceId: instance.id,
    type: template.type,
    port: instance.port,
    composeConfig: template.composeConfig.replace(/{PORT}/g, String(instance.port)).replace(/{INSTANCE_ID}/g, instance.id),
  });

  if (!sent) {
    await prisma.instance.update({ where: { id: instance.id }, data: { status: "error" } });
  }

  return NextResponse.json(instance, { status: 201 });
}

export async function PATCH(req: NextRequest) {
  const body = await req.json();
  const { id, action } = body;
  const instance = await prisma.instance.findUnique({ where: { id }, include: { template: true } });
  if (!instance) return NextResponse.json({ error: "Not found" }, { status: 404 });

  if (action === "stop") {
    sendToNode(instance.nodeId, { action: "stop", instanceId: instance.id });
    await prisma.instance.update({ where: { id }, data: { status: "stopped" } });
  } else if (action === "start") {
    const sent = sendToNode(instance.nodeId, {
      action: "start",
      instanceId: instance.id,
      type: instance.template.type,
      port: instance.port,
      composeConfig: instance.template.composeConfig.replace(/{PORT}/g, String(instance.port)).replace(/{INSTANCE_ID}/g, instance.id),
    });
    if (!sent) await prisma.instance.update({ where: { id }, data: { status: "error" } });
  } else if (action === "reset") {
    sendToNode(instance.nodeId, { action: "reset", instanceId: instance.id });
  }

  return NextResponse.json({ ok: true });
}

export async function DELETE(req: NextRequest) {
  const { searchParams } = new URL(req.url);
  const id = searchParams.get("id");
  if (!id) return NextResponse.json({ error: "Missing id" }, { status: 400 });
  const instance = await prisma.instance.findUnique({ where: { id } });
  if (instance) sendToNode(instance.nodeId, { action: "stop", instanceId: instance.id });
  await prisma.instance.delete({ where: { id } });
  return NextResponse.json({ ok: true });
}
