import { NextResponse } from "next/server";
import { z } from "zod";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
import {
  runCrudMutationGuardAfterSuccess,
  validateCrudMutationGuard
} from "@open-mercato/shared/lib/crud/mutation-guard";
import {
  dictionaryEntrySortModeSchema
} from "@open-mercato/core/modules/dictionaries/lib/entrySort";
import {
  customerDictionarySortModesUpsertSchema
} from "../../../data/validators.js";
import { loadCustomerSettings } from "../../../commands/settings.js";
import { withScopedPayload } from "../../utils.js";
import {
  BUILTIN_DICTIONARY_ROUTE_KINDS,
  dictionaryKindSchema,
  mapDictionaryKind
} from "../../dictionaries/context.js";
import { invalidateDictionaryCache } from "../../dictionaries/cache.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
const metadata = {
  GET: { requireAuth: true, requireFeatures: ["customers.settings.manage"] },
  PATCH: { requireAuth: true, requireFeatures: ["customers.settings.manage"] }
};
const dictionarySortModesPayloadSchema = z.object({
  dictionarySortModes: z.record(dictionaryKindSchema, dictionaryEntrySortModeSchema)
});
const dictionarySortModesResponseSchema = z.object({
  dictionarySortModes: z.record(z.string(), dictionaryEntrySortModeSchema)
});
const dictionarySortModesErrorSchema = z.object({
  error: z.string()
});
async function resolveSettingsContext(req) {
  const container = await createRequestContainer();
  const auth = await getAuthFromRequest(req);
  const { translate } = await resolveTranslations();
  if (!auth || !auth.tenantId) {
    throw new CrudHttpError(401, {
      error: translate("customers.errors.unauthorized", "Unauthorized")
    });
  }
  const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
  const organizationId = scope?.selectedId ?? auth.orgId ?? null;
  if (!organizationId) {
    throw new CrudHttpError(400, {
      error: translate("customers.errors.organization_required", "Organization context is required")
    });
  }
  const ctx = {
    container,
    auth,
    organizationScope: scope,
    selectedOrganizationId: organizationId,
    organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),
    request: req
  };
  let cache;
  try {
    cache = container.resolve("cache");
  } catch {
  }
  return {
    ctx,
    tenantId: auth.tenantId,
    organizationId,
    translate,
    em: container.resolve("em"),
    cache
  };
}
function resolveActorId(ctx) {
  const auth = ctx.auth;
  if (auth && typeof auth.sub === "string" && auth.sub.trim().length > 0) return auth.sub;
  if (auth && typeof auth.userId === "string" && auth.userId.trim().length > 0) return auth.userId;
  if (auth && typeof auth.keyId === "string" && auth.keyId.trim().length > 0) return auth.keyId;
  return "system";
}
function normalizeDictionarySortModes(value) {
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
  const result = {};
  for (const [rawKind, rawMode] of Object.entries(value)) {
    const kind = dictionaryKindSchema.safeParse(rawKind);
    const mode = dictionaryEntrySortModeSchema.safeParse(rawMode);
    if (kind.success && mode.success) {
      result[kind.data] = mode.data;
    }
  }
  return result;
}
async function invalidateCustomerDictionarySortCache(cache, tenantId, organizationId, dictionarySortModes) {
  const routeKinds = /* @__PURE__ */ new Set([
    ...BUILTIN_DICTIONARY_ROUTE_KINDS,
    ...Object.keys(dictionarySortModes)
  ]);
  for (const routeKind of routeKinds) {
    const parsed = dictionaryKindSchema.safeParse(routeKind);
    if (!parsed.success) continue;
    const { mappedKind } = mapDictionaryKind(parsed.data);
    await invalidateDictionaryCache(cache, {
      tenantId,
      mappedKind,
      organizationIds: [organizationId]
    });
  }
}
async function GET(req) {
  try {
    const { em, tenantId, organizationId } = await resolveSettingsContext(req);
    const record = await loadCustomerSettings(em, { tenantId, organizationId });
    return NextResponse.json({
      dictionarySortModes: normalizeDictionarySortModes(record?.dictionarySortModes)
    });
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    const { translate } = await resolveTranslations();
    logger.error("customers.settings.dictionary-sort-modes.get failed", { err });
    return NextResponse.json(
      { error: translate("customers.errors.lookup_failed", "Failed to load settings") },
      { status: 400 }
    );
  }
}
async function PATCH(req) {
  try {
    const { ctx, tenantId, organizationId, translate, cache, em } = await resolveSettingsContext(req);
    const payload = dictionarySortModesPayloadSchema.parse(await readJsonSafe(req, {}));
    const record = await loadCustomerSettings(em, { tenantId, organizationId });
    const dictionarySortModes = {
      ...normalizeDictionarySortModes(record?.dictionarySortModes),
      ...payload.dictionarySortModes
    };
    const scoped = withScopedPayload({ dictionarySortModes }, ctx, translate);
    const input = customerDictionarySortModesUpsertSchema.parse(scoped);
    const userId = resolveActorId(ctx);
    const guardResult = await validateCrudMutationGuard(ctx.container, {
      tenantId,
      organizationId,
      userId,
      resourceKind: "customers.settings",
      resourceId: organizationId,
      operation: "update",
      requestMethod: req.method,
      requestHeaders: req.headers,
      mutationPayload: input
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const commandBus = ctx.container.resolve("commandBus");
    const { result } = await commandBus.execute("customers.settings.save_dictionary_sort_modes", { input, ctx });
    await invalidateCustomerDictionarySortCache(cache, tenantId, organizationId, input.dictionarySortModes);
    if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(ctx.container, {
        tenantId,
        organizationId,
        userId,
        resourceKind: "customers.settings",
        resourceId: organizationId,
        operation: "update",
        requestMethod: req.method,
        requestHeaders: req.headers,
        metadata: guardResult.metadata ?? null
      });
    }
    return NextResponse.json({
      dictionarySortModes: normalizeDictionarySortModes(result?.dictionarySortModes ?? input.dictionarySortModes)
    });
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    const { translate } = await resolveTranslations();
    logger.error("customers.settings.dictionary-sort-modes.patch failed", { err });
    return NextResponse.json(
      { error: translate("customers.errors.save_failed", "Failed to save settings") },
      { status: 400 }
    );
  }
}
const openApi = {
  tag: "Customers",
  summary: "Customer dictionary entry sort modes",
  methods: {
    GET: {
      summary: "Retrieve dictionary sort modes",
      description: "Returns entry sort preferences for customer dictionaries in the selected organization.",
      responses: [
        { status: 200, description: "Current dictionary sort modes", schema: dictionarySortModesResponseSchema },
        { status: 401, description: "Unauthorized", schema: dictionarySortModesErrorSchema },
        { status: 400, description: "Organization context missing", schema: dictionarySortModesErrorSchema }
      ]
    },
    PATCH: {
      summary: "Update dictionary sort modes",
      description: "Updates entry sort preferences for customer dictionaries in the selected organization.",
      requestBody: {
        contentType: "application/json",
        schema: dictionarySortModesPayloadSchema
      },
      responses: [
        { status: 200, description: "Updated dictionary sort modes", schema: dictionarySortModesResponseSchema },
        { status: 401, description: "Unauthorized", schema: dictionarySortModesErrorSchema },
        { status: 400, description: "Invalid payload or organization context", schema: dictionarySortModesErrorSchema }
      ]
    }
  }
};
export {
  GET,
  PATCH,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
