import { NextResponse } from "next/server";
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { resolveFeatureCheckContext, resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
import { z } from "zod";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("audit_logs").child({ component: "undo" });
const metadata = {
  POST: { requireAuth: true, requireFeatures: ["audit_logs.undo_self"] }
};
const undoRequestSchema = z.object({
  undoToken: z.string().min(1).describe("Undo token issued by the action log entry")
});
const undoResponseSchema = z.object({
  ok: z.literal(true),
  logId: z.string().describe("Identifier of the action log that was undone")
});
const errorSchema = z.object({
  error: z.string()
});
async function POST(req) {
  const auth = await getAuthFromRequest(req);
  if (!auth) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  const body = await req.json().catch(() => null);
  const undoToken = body?.undoToken?.trim();
  if (!undoToken) return NextResponse.json({ error: "Invalid undo token" }, { status: 400 });
  const container = await createRequestContainer();
  const commandBus = container.resolve("commandBus");
  const logs = container.resolve("actionLogService");
  let rbac = null;
  try {
    rbac = container.resolve("rbacService");
  } catch {
    rbac = null;
  }
  const { organizationId } = await resolveFeatureCheckContext({ container, auth, request: req });
  const canUndoTenant = rbac ? await rbac.userHasAllFeatures(auth.sub, ["audit_logs.undo_tenant"], {
    tenantId: auth.tenantId ?? null,
    organizationId
  }) : false;
  const target = await logs.findByUndoToken(undoToken);
  if (!target || target.executionState !== "done") {
    return NextResponse.json({ error: "Undo token not available" }, { status: 400 });
  }
  if (target.actorUserId && target.actorUserId !== auth.sub && !canUndoTenant) {
    return NextResponse.json({ error: "Undo token not available" }, { status: 400 });
  }
  if (target.tenantId && target.tenantId !== (auth.tenantId ?? null)) {
    return NextResponse.json({ error: "Undo token not available" }, { status: 400 });
  }
  const scopedOrgId = canUndoTenant ? organizationId ?? null : organizationId ?? auth.orgId ?? null;
  const orgScopeMismatch = canUndoTenant ? Boolean(target.organizationId && scopedOrgId && target.organizationId !== scopedOrgId) : Boolean(target.organizationId && target.organizationId !== scopedOrgId);
  if (orgScopeMismatch) {
    return NextResponse.json({ error: "Undo token not available" }, { status: 400 });
  }
  const lookupActorId = canUndoTenant ? target.actorUserId ?? auth.sub : auth.sub;
  const lookupOrgId = target.organizationId ?? null;
  let latest = null;
  if (target.resourceKind || target.resourceId) {
    latest = await logs.latestUndoableForResource({
      actorUserId: lookupActorId,
      tenantId: auth.tenantId ?? null,
      organizationId: lookupOrgId,
      resourceKind: target.resourceKind ?? void 0,
      resourceId: target.resourceId ?? void 0
    });
  }
  if (!latest) {
    latest = await logs.latestUndoableForActor(lookupActorId, {
      tenantId: auth.tenantId ?? null,
      organizationId: lookupOrgId
    });
  }
  if (!latest || latest.id !== target.id) {
    return NextResponse.json({ error: "Undo token not available" }, { status: 400 });
  }
  try {
    const ctx = await createRuntimeContext(container, auth, req);
    await commandBus.undo(undoToken, ctx);
    return NextResponse.json({ ok: true, logId: target.id });
  } catch (err) {
    logger.error("Undo failed", { err });
    return NextResponse.json({ error: "Undo failed" }, { status: 400 });
  }
}
async function createRuntimeContext(container, auth, request) {
  const scope = await resolveOrganizationScopeForRequest({ container, auth, request });
  return {
    container,
    auth,
    organizationScope: scope,
    selectedOrganizationId: scope.selectedId,
    organizationIds: scope.filterIds,
    request
  };
}
const openApi = {
  summary: "Undo a recent action",
  description: "Executes the undo operation for the most recent undoable action belonging to the caller.",
  methods: {
    POST: {
      summary: "Undo action by token",
      description: "Replays the undo handler registered for a command. The provided undo token must match the latest undoable log entry accessible to the caller.",
      requestBody: {
        contentType: "application/json",
        schema: undoRequestSchema
      },
      responses: [
        { status: 200, description: "Undo applied successfully", schema: undoResponseSchema }
      ],
      errors: [
        { status: 400, description: "Invalid or unavailable undo token", schema: errorSchema },
        { status: 401, description: "Authentication required", schema: errorSchema },
        { status: 403, description: "Undo blocked by organization or tenant scope", schema: errorSchema }
      ]
    }
  }
};
export {
  POST,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
