import { NextResponse } from "next/server";
import { z } from "zod";

import { getSavedProject, updateSavedProject } from "@/lib/api/saved-projects";
import { getAccessToken } from "@/lib/auth/session";
import { isDevProjectId } from "@/lib/project-ids";

export const dynamic = "force-dynamic";

const patchProjectSchema = z.object({
  scene_data: z.record(z.string(), z.unknown()).optional(),
  name: z.string().min(1).max(120).optional(),
});

interface RouteContext {
  params: { projectId: string };
}

export async function GET(_request: Request, context: RouteContext) {
  const { projectId } = context.params;

  if (isDevProjectId(projectId)) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }

  const token = await getAccessToken();
  if (!token) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const result = await getSavedProject(projectId);
  if (!result.ok || !result.data) {
    return NextResponse.json(
      { error: result.error ?? "Project not found" },
      { status: result.status === 404 ? 404 : result.status }
    );
  }

  const p = result.data;
  return NextResponse.json({
    project: {
      id: p.id,
      name: p.name,
      type: p.type,
      // The studio service owns the normalized scene graph; expose the full
      // payload as scene_data so the editor can hydrate from it.
      scene_data: p,
      status: "draft",
      updated_at: p.last_edit_date,
    },
  });
}

export async function PATCH(request: Request, context: RouteContext) {
  const { projectId } = context.params;

  if (isDevProjectId(projectId)) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }

  const token = await getAccessToken();
  if (!token) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  let body: unknown;
  try {
    body = await request.json();
  } catch {
    return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
  }

  const parsed = patchProjectSchema.safeParse(body);
  if (!parsed.success) {
    return NextResponse.json(
      { error: "Validation failed", details: parsed.error.flatten() },
      { status: 400 }
    );
  }

  if (!parsed.data.scene_data && !parsed.data.name) {
    return NextResponse.json({ error: "Nothing to update" }, { status: 400 });
  }

  // The studio PATCH endpoint updates project metadata (name + edit state).
  // Scene graphs are saved through the dedicated PUT /scenes endpoint, so here
  // we forward name and any edit_state carried in scene_data.
  const update: Record<string, unknown> = {};
  if (parsed.data.name !== undefined) update.name = parsed.data.name;
  if (parsed.data.scene_data !== undefined) {
    const editState = parsed.data.scene_data.edit_state;
    if (typeof editState === "string") update.edit_state = editState;
  }

  const result = await updateSavedProject(projectId, update);
  if (!result.ok || !result.data) {
    return NextResponse.json(
      { error: result.error ?? "Project not found" },
      { status: result.status === 404 ? 404 : result.status }
    );
  }

  const p = result.data;
  return NextResponse.json({
    project: {
      id: p.id,
      name: p.name,
      type: p.type,
      scene_data: p,
      status: "draft",
      updated_at: p.last_edit_date,
    },
  });
}
