import { randomUUID } from "node:crypto";
import { data } from "react-router";
import { eq } from "drizzle-orm";
import { getDb } from "~/lib/db";
import { users, routes } from "@trails-cool/db/schema/journal";
import { createRouteToken } from "~/lib/jwt.server";
import { TERMS_VERSION } from "~/lib/legal";

// Only available when the server is started with E2E=true.
// Never enabled in production.
function assertE2EEnabled() {
  if (process.env.E2E !== "true") {
    throw new Response("Not found", { status: 404 });
  }
}

const E2E_USER_USERNAME = "e2e-test-user";
const E2E_USER_EMAIL = "e2e@localhost";

/**
 * POST /api/e2e/seed
 *
 * Idempotently creates the e2e test user and a bare route (no GPX, no geom),
 * then returns a callback-scoped JWT for that route. Used by e2e tests that
 * need to hit the Planner callback endpoint without going through the browser
 * auth flow.
 *
 * Body: none required. Optionally pass { routeName } to label the route.
 */
export async function action({ request }: { request: Request }) {
  assertE2EEnabled();
  if (request.method !== "POST") {
    return data({ error: "Method not allowed" }, { status: 405 });
  }

  const db = getDb();

  // Upsert the e2e test user
  await db
    .insert(users)
    .values({
      id: randomUUID(),
      username: E2E_USER_USERNAME,
      email: E2E_USER_EMAIL,
      displayName: "E2E Test User",
      domain: "localhost",
      termsAcceptedAt: new Date(),
      termsVersion: TERMS_VERSION,
    })
    .onConflictDoNothing({ target: users.username });

  const [user] = await db
    .select({ id: users.id })
    .from(users)
    .where(eq(users.username, E2E_USER_USERNAME));

  if (!user) throw new Error("e2e seed: failed to upsert test user");

  const body = request.headers.get("content-type")?.includes("application/json")
    ? await request.json().catch(() => ({}))
    : {};
  const routeName = (body as { routeName?: string }).routeName ?? "E2E callback test route";
  const visibility = (body as { visibility?: string }).visibility ?? "public";

  const routeId = randomUUID();
  await db.insert(routes).values({
    id: routeId,
    ownerId: user.id,
    name: routeName,
    description: "",
    visibility: visibility as "public" | "unlisted" | "private",
  });

  const token = await createRouteToken(routeId);

  return data({ routeId, token, ownerId: user.id });
}
