import { NextResponse } from "next/server";
import { z } from "zod";
import { getCustomerAuthFromRequest, requireCustomerFeature } from "@open-mercato/core/modules/customer_accounts/lib/customerAuth";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { CustomerUser, CustomerUserRole, CustomerRole } from "@open-mercato/core/modules/customer_accounts/data/entities";
import { assignRolesSchema } from "@open-mercato/core/modules/customer_accounts/data/validators";
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
const metadata = { requireAuth: false };
async function PUT(req, { params }) {
  const auth = await getCustomerAuthFromRequest(req);
  if (!auth) {
    return NextResponse.json({ ok: false, error: "Authentication required" }, { status: 401 });
  }
  const container = await createRequestContainer();
  const customerRbacService = container.resolve("customerRbacService");
  try {
    await requireCustomerFeature(auth, ["portal.users.roles.manage"], customerRbacService);
  } catch (response) {
    return response;
  }
  if (!auth.customerEntityId) {
    return NextResponse.json({ ok: false, error: "No company association" }, { status: 403 });
  }
  let body;
  try {
    body = await req.json();
  } catch {
    return NextResponse.json({ ok: false, error: "Invalid request body" }, { status: 400 });
  }
  const parsed = assignRolesSchema.safeParse(body);
  if (!parsed.success) {
    return NextResponse.json({ ok: false, error: "Validation failed" }, { status: 400 });
  }
  const em = container.resolve("em");
  const targetUser = await findOneWithDecryption(em, CustomerUser, {
    id: params.id,
    customerEntityId: auth.customerEntityId,
    tenantId: auth.tenantId,
    deletedAt: null
  }, void 0, { tenantId: auth.tenantId, organizationId: auth.orgId });
  if (!targetUser) {
    return NextResponse.json({ ok: false, error: "User not found" }, { status: 404 });
  }
  const requestedRoleIds = parsed.data.roleIds;
  const fetchedRoles = requestedRoleIds.length > 0 ? await findWithDecryption(
    em,
    CustomerRole,
    { id: { $in: requestedRoleIds }, tenantId: auth.tenantId, deletedAt: null },
    void 0,
    { tenantId: auth.tenantId, organizationId: auth.orgId }
  ) : [];
  const fetchedRolesById = new Map(fetchedRoles.map((role) => [role.id, role]));
  const validatedRoles = [];
  for (const roleId of requestedRoleIds) {
    const role = fetchedRolesById.get(roleId);
    if (!role || !role.customerAssignable) {
      return NextResponse.json({ ok: false, error: "Role not found or not assignable" }, { status: 400 });
    }
    validatedRoles.push(role);
  }
  await em.transactional(async (tx) => {
    await tx.nativeDelete(CustomerUserRole, { user: targetUser.id });
    for (const role of validatedRoles) {
      const userRole = tx.create(CustomerUserRole, {
        user: targetUser,
        role,
        createdAt: /* @__PURE__ */ new Date()
      });
      tx.persist(userRole);
    }
  });
  await customerRbacService.invalidateUserCache(targetUser.id);
  return NextResponse.json({ ok: true });
}
const successSchema = z.object({ ok: z.literal(true) });
const errorSchema = z.object({ ok: z.literal(false), error: z.string() });
const methodDoc = {
  summary: "Update portal user roles",
  description: "Assigns new roles to a company portal user.",
  tags: ["Customer Portal"],
  requestBody: { schema: assignRolesSchema },
  responses: [{ status: 200, description: "Roles updated", schema: successSchema }],
  errors: [
    { status: 400, description: "Validation failed", schema: errorSchema },
    { status: 401, description: "Not authenticated", schema: errorSchema },
    { status: 403, description: "Insufficient permissions", schema: errorSchema },
    { status: 404, description: "User not found", schema: errorSchema }
  ]
};
const openApi = {
  summary: "Update portal user roles",
  pathParams: z.object({ id: z.string().uuid() }),
  methods: { PUT: methodDoc }
};
export {
  PUT,
  metadata,
  openApi
};
//# sourceMappingURL=roles.js.map
