/**
 * /api/graph — Public entity-graph endpoints (read-only).
 *
 * GET /api/graph?op=neighbors&class=people&id=j-edgar-hoover
 *   → top entities co-mentioned with this one
 *
 * GET /api/graph?op=paths&from=PK_A&to=PK_B&max_hops=3
 *   → shortest paths between two entities via shared chunks
 *
 * GET /api/graph?op=co_mention&a=PK_A&b=PK_B
 *   → chunks where both entities appear together
 */
import { NextRequest } from "next/server";
import { findEntity, getNeighbors, findPaths, getCoMentionChunks } from "@/lib/retrieval/graph";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

function json(data: unknown, status = 200) {
  return new Response(JSON.stringify(data), {
    status,
    headers: { "content-type": "application/json" },
  });
}

export async function GET(req: NextRequest) {
  const u = new URL(req.url);
  const op = u.searchParams.get("op") ?? "neighbors";

  try {
    if (op === "neighbors") {
      const cls = u.searchParams.get("class") ?? "";
      const id = u.searchParams.get("id") ?? "";
      if (!cls || !id) return json({ error: "class and id required" }, 400);
      const ent = await findEntity(cls, id);
      if (!ent) return json({ error: "entity_not_found", class: cls, id }, 404);
      const filterClasses = u.searchParams.get("filter_classes")?.split(",").filter(Boolean);
      const limit = Number(u.searchParams.get("limit") ?? 30);
      const neighbors = await getNeighbors(ent.entity_pk, { limit, classes: filterClasses });
      return json({ entity: ent, neighbors });
    }

    if (op === "paths") {
      const from = Number(u.searchParams.get("from"));
      const to = Number(u.searchParams.get("to"));
      const maxHops = Math.min(Number(u.searchParams.get("max_hops") ?? 3), 4);
      if (!from || !to) return json({ error: "from and to required" }, 400);
      const paths = await findPaths(from, to, maxHops);
      return json({ from, to, max_hops: maxHops, paths });
    }

    if (op === "co_mention") {
      const a = Number(u.searchParams.get("a"));
      const b = Number(u.searchParams.get("b"));
      const limit = Math.min(Number(u.searchParams.get("limit") ?? 20), 100);
      if (!a || !b) return json({ error: "a and b required" }, 400);
      const chunks = await getCoMentionChunks(a, b, limit);
      return json({ a, b, count: chunks.length, chunks });
    }

    return json({ error: "unknown_op", op }, 400);
  } catch (e) {
    return json({ error: "graph_unavailable", message: (e as Error).message }, 503);
  }
}
