import { NextResponse } from "next/server";
import { CustomerEntity } from "../../../data/entities.js";
import { labelUnassignCommandSchema, labelAssignmentSchema } from "../../../data/validators.js";
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 { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import { serializeOperationMetadata } from "@open-mercato/shared/lib/commands/operationMetadata";
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
import { z } from "zod";
import { resolveLabelActorUserId } from "../auth.js";
import {
  runCrudMutationGuardAfterSuccess,
  validateCrudMutationGuard
} from "@open-mercato/shared/lib/crud/mutation-guard";
import {
  createMissingCustomerLabelTablesError,
  isMissingCustomerLabelTable
} from "../table-errors.js";
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
const metadata = {
  POST: { requireAuth: true }
};
const labelAssignmentRequestSchema = labelAssignmentSchema.extend({
  organizationId: z.string().uuid().optional()
});
function resolveResourceKind(kind) {
  if (kind === "company") return "customers.company";
  return "customers.person";
}
function resolveRequiredFeature(kind) {
  return kind === "company" ? "customers.companies.manage" : "customers.people.manage";
}
async function POST(req) {
  try {
    const { translate } = await resolveTranslations();
    const container = await createRequestContainer();
    const auth = await getAuthFromRequest(req);
    const actorUserId = resolveLabelActorUserId(auth);
    if (!auth || !auth.tenantId || !actorUserId) {
      return NextResponse.json({ error: translate("customers.errors.unauthorized", "Unauthorized") }, { status: 401 });
    }
    const body = labelAssignmentRequestSchema.parse(await readJsonSafe(req, {}));
    const scope = await resolveOrganizationScopeForRequest({
      container,
      auth,
      request: req,
      selectedId: body.organizationId ?? void 0
    });
    const organizationId = scope?.selectedId ?? auth.orgId ?? null;
    if (!organizationId) {
      throw new CrudHttpError(400, { error: translate("customers.errors.organization_required", "Organization context is required") });
    }
    const em = container.resolve("em").fork();
    const targetEntity = await findOneWithDecryption(
      em,
      CustomerEntity,
      {
        id: body.entityId,
        tenantId: auth.tenantId,
        organizationId,
        deletedAt: null
      },
      void 0,
      { tenantId: auth.tenantId, organizationId }
    );
    if (!targetEntity) {
      throw new CrudHttpError(404, { error: translate("customers.errors.entity_not_found", "Entity not found") });
    }
    const entityKind = targetEntity.kind === "person" || targetEntity.kind === "company" ? targetEntity.kind : null;
    const resourceKind = resolveResourceKind(entityKind);
    const rbac = container.resolve("rbacService");
    if (!rbac) {
      throw new CrudHttpError(500, { error: translate("customers.errors.internal", "Internal error") });
    }
    const requiredFeature = resolveRequiredFeature(entityKind);
    const hasFeature = await rbac.userHasAllFeatures(actorUserId, [requiredFeature], {
      tenantId: auth.tenantId,
      organizationId
    });
    if (!hasFeature) {
      throw new CrudHttpError(403, { error: translate("customers.errors.access_denied", "Access denied") });
    }
    const guardResult = await validateCrudMutationGuard(container, {
      tenantId: auth.tenantId,
      organizationId,
      userId: actorUserId,
      resourceKind,
      resourceId: body.entityId,
      operation: "custom",
      requestMethod: req.method,
      requestHeaders: req.headers,
      mutationPayload: body
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const commandInput = labelUnassignCommandSchema.parse({
      labelId: body.labelId,
      entityId: body.entityId,
      tenantId: auth.tenantId,
      organizationId
    });
    const commandBus = container.resolve("commandBus");
    const { result, logEntry } = await commandBus.execute(
      "customers.labels.unassign",
      {
        input: commandInput,
        ctx: {
          container,
          auth,
          organizationScope: scope,
          selectedOrganizationId: organizationId,
          organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),
          request: req
        }
      }
    );
    if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(container, {
        tenantId: auth.tenantId,
        organizationId,
        userId: actorUserId,
        resourceKind,
        resourceId: body.entityId,
        operation: "custom",
        requestMethod: req.method,
        requestHeaders: req.headers,
        metadata: guardResult.metadata ?? null
      });
    }
    const response = NextResponse.json({ id: result.assignmentId });
    if (result.assignmentId && 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 ?? "customers.labelAssignment",
          resourceId: logEntry.resourceId ?? result.assignmentId,
          executedAt: logEntry.createdAt instanceof Date ? logEntry.createdAt.toISOString() : (/* @__PURE__ */ new Date()).toISOString()
        })
      );
    }
    return response;
  } catch (err) {
    if (isMissingCustomerLabelTable(err)) {
      const migrationError = await createMissingCustomerLabelTablesError();
      return NextResponse.json(migrationError.body, { status: migrationError.status });
    }
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    logger.error("customers/labels/unassign.POST", { err });
    return NextResponse.json({ error: "Failed to unassign label" }, { status: 500 });
  }
}
const responseSchema = z.object({ id: z.string().uuid().nullable() });
const errorSchema = z.object({ error: z.string() });
const openApi = {
  tag: "Customers",
  summary: "Unassign label from entity",
  methods: {
    POST: {
      summary: "Unassign label",
      requestBody: { contentType: "application/json", schema: labelAssignmentRequestSchema },
      responses: [
        { status: 200, description: "Unassigned", schema: responseSchema }
      ],
      errors: [
        { status: 404, description: "Label or entity not found", schema: errorSchema }
      ]
    }
  }
};
export {
  POST,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
