import { NextResponse } from "next/server";
import { z } from "zod";
import { sql } from "kysely";
import { resolveTranslationsRouteContext, requireTranslationFeatures, resolveTranslationsActorId } from "@open-mercato/core/modules/translations/api/context";
import { translationBodySchema, entityTypeParamSchema, entityIdParamSchema } from "@open-mercato/core/modules/translations/data/validators";
import { isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import {
  runCrudMutationGuardAfterSuccess,
  validateCrudMutationGuard
} from "@open-mercato/shared/lib/crud/mutation-guard";
import { serializeOperationMetadata } from "@open-mercato/shared/lib/commands/operationMetadata";
import { enforceCommandOptimisticLockWithGuards } from "@open-mercato/shared/lib/crud/optimistic-lock-command";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("translations").child({ component: "entity-translations" });
const TRANSLATION_RESOURCE_KIND = "translations.translation";
async function loadTranslationRowVersion(db, entityType, entityId, tenantId, organizationId) {
  const row = await db.selectFrom("entity_translations").select(["id", "updated_at"]).where("entity_type", "=", entityType).where("entity_id", "=", entityId).where(sql`tenant_id is not distinct from ${tenantId}`).where(sql`organization_id is not distinct from ${organizationId}`).executeTakeFirst();
  if (!row) return null;
  return { id: row.id, updatedAt: row.updated_at ?? null };
}
const paramsSchema = z.object({
  entityType: entityTypeParamSchema,
  entityId: entityIdParamSchema
});
const metadata = {
  GET: { requireAuth: true, requireFeatures: ["translations.view"] },
  PUT: { requireAuth: true, requireFeatures: ["translations.manage"] },
  DELETE: { requireAuth: true, requireFeatures: ["translations.manage"] }
};
async function GET(req, ctx) {
  try {
    const context = await resolveTranslationsRouteContext(req);
    await requireTranslationFeatures(context, ["translations.view"]);
    const { entityType, entityId } = paramsSchema.parse({
      entityType: ctx.params?.entityType,
      entityId: ctx.params?.entityId
    });
    const row = await context.db.selectFrom("entity_translations").selectAll().where("entity_type", "=", entityType).where("entity_id", "=", entityId).where(sql`tenant_id is not distinct from ${context.tenantId}`).where(sql`organization_id is not distinct from ${context.organizationId}`).executeTakeFirst();
    if (!row) {
      return NextResponse.json({ error: "Not found" }, { status: 404 });
    }
    return NextResponse.json({
      entityType: row.entity_type,
      entityId: row.entity_id,
      translations: row.translations,
      createdAt: row.created_at,
      updatedAt: row.updated_at
    });
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    if (err instanceof z.ZodError) {
      return NextResponse.json({ error: "Invalid parameters", details: err.issues }, { status: 400 });
    }
    logger.error("Failed to load translations", { err });
    return NextResponse.json({ error: "Internal server error" }, { status: 500 });
  }
}
async function PUT(req, ctx) {
  try {
    const context = await resolveTranslationsRouteContext(req);
    await requireTranslationFeatures(context, ["translations.manage"]);
    const { entityType, entityId } = paramsSchema.parse({
      entityType: ctx.params?.entityType,
      entityId: ctx.params?.entityId
    });
    const rawText = await req.text();
    let rawBody = {};
    if (rawText.trim().length > 0) {
      try {
        rawBody = JSON.parse(rawText);
      } catch {
        return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
      }
    }
    const translations = translationBodySchema.parse(rawBody);
    const guardUserId = resolveTranslationsActorId(context.auth);
    const guardResult = await validateCrudMutationGuard(context.container, {
      tenantId: context.tenantId,
      organizationId: context.organizationId,
      userId: guardUserId,
      resourceKind: "translations.translation",
      resourceId: `${entityType}:${entityId}`,
      operation: "update",
      requestMethod: req.method,
      requestHeaders: req.headers,
      mutationPayload: { entityType, entityId, translations }
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const existingVersion = await loadTranslationRowVersion(
      context.db,
      entityType,
      entityId,
      context.tenantId,
      context.organizationId
    );
    if (existingVersion) {
      await enforceCommandOptimisticLockWithGuards(context.container, {
        resourceKind: TRANSLATION_RESOURCE_KIND,
        resourceId: existingVersion.id,
        current: existingVersion.updatedAt,
        request: req
      });
    }
    const commandBus = context.container.resolve("commandBus");
    const { result, logEntry } = await commandBus.execute("translations.translation.save", {
      input: {
        entityType,
        entityId,
        translations,
        organizationId: context.organizationId,
        tenantId: context.tenantId
      },
      ctx: context.commandCtx
    });
    if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(context.container, {
        tenantId: context.tenantId,
        organizationId: context.organizationId,
        userId: guardUserId,
        resourceKind: "translations.translation",
        resourceId: `${entityType}:${entityId}`,
        operation: "update",
        requestMethod: req.method,
        requestHeaders: req.headers,
        metadata: guardResult.metadata ?? null
      });
    }
    const row = await context.db.selectFrom("entity_translations").selectAll().where("id", "=", result.rowId).executeTakeFirst();
    const response = NextResponse.json({
      entityType: row.entity_type,
      entityId: row.entity_id,
      translations: row.translations,
      createdAt: row.created_at,
      updatedAt: row.updated_at
    });
    if (logEntry?.undoToken && logEntry?.id && logEntry?.commandId) {
      response.headers.set(
        "x-om-operation",
        serializeOperationMetadata({
          id: logEntry.id,
          undoToken: logEntry.undoToken,
          commandId: logEntry.commandId,
          actionLabel: logEntry.actionLabel ?? null,
          resourceKind: logEntry.resourceKind ?? "translations.translation",
          resourceId: logEntry.resourceId ?? result.rowId,
          executedAt: logEntry.createdAt instanceof Date ? logEntry.createdAt.toISOString() : typeof logEntry.createdAt === "string" ? logEntry.createdAt : (/* @__PURE__ */ new Date()).toISOString()
        })
      );
    }
    return response;
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    if (err instanceof z.ZodError) {
      return NextResponse.json({ error: "Validation failed", details: err.issues }, { status: 400 });
    }
    logger.error("Failed to save translations", { err });
    return NextResponse.json({ error: "Internal server error" }, { status: 500 });
  }
}
async function DELETE(req, ctx) {
  try {
    const context = await resolveTranslationsRouteContext(req);
    await requireTranslationFeatures(context, ["translations.manage"]);
    const { entityType, entityId } = paramsSchema.parse({
      entityType: ctx.params?.entityType,
      entityId: ctx.params?.entityId
    });
    const guardUserId = resolveTranslationsActorId(context.auth);
    const guardResult = await validateCrudMutationGuard(context.container, {
      tenantId: context.tenantId,
      organizationId: context.organizationId,
      userId: guardUserId,
      resourceKind: "translations.translation",
      resourceId: `${entityType}:${entityId}`,
      operation: "delete",
      requestMethod: req.method,
      requestHeaders: req.headers,
      mutationPayload: null
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const existingVersion = await loadTranslationRowVersion(
      context.db,
      entityType,
      entityId,
      context.tenantId,
      context.organizationId
    );
    if (existingVersion) {
      await enforceCommandOptimisticLockWithGuards(context.container, {
        resourceKind: TRANSLATION_RESOURCE_KIND,
        resourceId: existingVersion.id,
        current: existingVersion.updatedAt,
        request: req
      });
    }
    const commandBus = context.container.resolve("commandBus");
    const { logEntry } = await commandBus.execute("translations.translation.delete", {
      input: {
        entityType,
        entityId,
        organizationId: context.organizationId,
        tenantId: context.tenantId
      },
      ctx: context.commandCtx
    });
    if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(context.container, {
        tenantId: context.tenantId,
        organizationId: context.organizationId,
        userId: guardUserId,
        resourceKind: "translations.translation",
        resourceId: `${entityType}:${entityId}`,
        operation: "delete",
        requestMethod: req.method,
        requestHeaders: req.headers,
        metadata: guardResult.metadata ?? null
      });
    }
    const response = new NextResponse(null, { status: 204 });
    if (logEntry?.undoToken && logEntry?.id && logEntry?.commandId) {
      response.headers.set(
        "x-om-operation",
        serializeOperationMetadata({
          id: logEntry.id,
          undoToken: logEntry.undoToken,
          commandId: logEntry.commandId,
          actionLabel: logEntry.actionLabel ?? null,
          resourceKind: logEntry.resourceKind ?? "translations.translation",
          resourceId: logEntry.resourceId ?? null,
          executedAt: logEntry.createdAt instanceof Date ? logEntry.createdAt.toISOString() : typeof logEntry.createdAt === "string" ? logEntry.createdAt : (/* @__PURE__ */ new Date()).toISOString()
        })
      );
    }
    return response;
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    if (err instanceof z.ZodError) {
      return NextResponse.json({ error: "Invalid parameters", details: err.issues }, { status: 400 });
    }
    logger.error("Failed to delete translations", { err });
    return NextResponse.json({ error: "Internal server error" }, { status: 500 });
  }
}
const translationsTag = "Translations";
const getDoc = {
  summary: "Get entity translations",
  description: "Returns the full translation record for a single entity.",
  tags: [translationsTag],
  responses: [
    { status: 200, description: "Translation record found." }
  ],
  errors: [
    { status: 401, description: "Authentication required" },
    { status: 404, description: "No translations found for this entity" }
  ]
};
const putDoc = {
  summary: "Create or update entity translations",
  description: "Full replacement of translations JSONB for an entity.",
  tags: [translationsTag],
  responses: [
    { status: 200, description: "Translations saved." }
  ],
  errors: [
    { status: 400, description: "Validation failed" },
    { status: 401, description: "Authentication required" }
  ]
};
const deleteDoc = {
  summary: "Delete entity translations",
  description: "Removes all translations for an entity.",
  tags: [translationsTag],
  responses: [
    { status: 204, description: "Translations deleted." }
  ],
  errors: [
    { status: 401, description: "Authentication required" }
  ]
};
const openApi = {
  tag: translationsTag,
  summary: "Entity translation resource",
  pathParams: paramsSchema,
  methods: {
    GET: getDoc,
    PUT: putDoc,
    DELETE: deleteDoc
  }
};
export {
  DELETE,
  GET,
  PUT,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
