import { json } from "@remix-run/server-runtime";
import { CloseSessionRequestBody, type RetrieveSessionResponseBody } from "@trigger.dev/core/v3";
import { z } from "zod";
import { $replica, prisma } from "~/db.server";
import {
  resolveSessionByIdOrExternalId,
  serializeSessionWithFriendlyRunId,
} from "~/services/realtime/sessions.server";
import { createActionApiRoute } from "~/services/routeBuilders/apiBuilder.server";

const ParamsSchema = z.object({
  session: z.string(),
});

const { action, loader } = createActionApiRoute(
  {
    params: ParamsSchema,
    body: CloseSessionRequestBody,
    maxContentLength: 1024,
    method: "POST",
    allowJWT: true,
    corsStrategy: "all",
    authorization: {
      action: "admin",
      resource: (params) => ({ type: "sessions", id: params.session }),
    },
  },
  async ({ authentication, params, body }) => {
    const existing = await resolveSessionByIdOrExternalId(
      $replica,
      authentication.environment.id,
      params.session
    );

    if (!existing) {
      return json({ error: "Session not found" }, { status: 404 });
    }

    // Idempotent: if already closed, return the current row without clobbering
    // the original closedAt / closedReason.
    if (existing.closedAt) {
      return json<RetrieveSessionResponseBody>(await serializeSessionWithFriendlyRunId(existing));
    }

    // `closedAt: null` on the where clause makes the update conditional at
    // the DB level. Two concurrent closes race through the earlier read,
    // but only one can win this update — the loser hits `count === 0` and
    // falls back to reading the winning row. Closedness is write-once.
    const { count } = await prisma.session.updateMany({
      where: { id: existing.id, closedAt: null },
      data: {
        closedAt: new Date(),
        closedReason: body.reason ?? null,
      },
    });

    if (count === 0) {
      const final = await prisma.session.findFirst({ where: { id: existing.id } });
      if (!final) return json({ error: "Session not found" }, { status: 404 });
      return json<RetrieveSessionResponseBody>(await serializeSessionWithFriendlyRunId(final));
    }

    const updated = await prisma.session.findFirst({ where: { id: existing.id } });
    if (!updated) return json({ error: "Session not found" }, { status: 404 });
    return json<RetrieveSessionResponseBody>(await serializeSessionWithFriendlyRunId(updated));
  }
);

export { action, loader };
