import { NextResponse } from "next/server";
import { z } from "zod";
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { CustomerUser, CustomerUserRole, CustomerRole, CustomerUserSession } from "@open-mercato/core/modules/customer_accounts/data/entities";
import { adminUpdateUserSchema } from "@open-mercato/core/modules/customer_accounts/data/validators";
import { emitCustomerAccountsEvent } from "@open-mercato/core/modules/customer_accounts/events";
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
import { isOwnedCompanyEntity } from "@open-mercato/core/modules/customer_accounts/lib/customerEntityOwnership";
import { enforceCommandOptimisticLockWithGuards } from "@open-mercato/shared/lib/crud/optimistic-lock-command";
import { isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
const metadata = {};
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
async function GET(req, { params }) {
  if (!UUID_RE.test(params.id)) {
    return NextResponse.json({ ok: false, error: "Invalid user ID" }, { status: 400 });
  }
  const auth = await getAuthFromRequest(req);
  if (!auth) {
    return NextResponse.json({ ok: false, error: "Authentication required" }, { status: 401 });
  }
  const container = await createRequestContainer();
  const rbacService = container.resolve("rbacService");
  const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ["customer_accounts.view"], { tenantId: auth.tenantId, organizationId: auth.orgId });
  if (!hasAccess) {
    return NextResponse.json({ ok: false, error: "Insufficient permissions" }, { status: 403 });
  }
  const em = container.resolve("em");
  const user = await findOneWithDecryption(
    em,
    CustomerUser,
    { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null },
    void 0,
    { tenantId: auth.tenantId, organizationId: auth.orgId }
  );
  if (!user) {
    return NextResponse.json({ ok: false, error: "User not found" }, { status: 404 });
  }
  const userRoles = await findWithDecryption(
    em,
    CustomerUserRole,
    { user: user.id, deletedAt: null },
    { populate: ["role"] },
    { tenantId: auth.tenantId, organizationId: auth.orgId }
  );
  const roles = userRoles.map((ur) => ({
    id: ur.role.id,
    name: ur.role.name,
    slug: ur.role.slug
  }));
  const activeSessions = await findWithDecryption(
    em,
    CustomerUserSession,
    {
      user: user.id,
      deletedAt: null,
      expiresAt: { $gt: /* @__PURE__ */ new Date() }
    },
    { orderBy: { lastUsedAt: "DESC" } },
    { tenantId: auth.tenantId, organizationId: auth.orgId }
  );
  const sessions = activeSessions.map((session) => ({
    id: session.id,
    ipAddress: session.ipAddress || null,
    userAgent: session.userAgent || null,
    lastUsedAt: session.lastUsedAt || null,
    createdAt: session.createdAt,
    expiresAt: session.expiresAt
  }));
  return NextResponse.json({
    ok: true,
    id: user.id,
    email: user.email,
    displayName: user.displayName,
    emailVerifiedAt: user.emailVerifiedAt || null,
    isActive: user.isActive,
    lockedUntil: user.lockedUntil || null,
    lastLoginAt: user.lastLoginAt || null,
    customerEntityId: user.customerEntityId || null,
    personEntityId: user.personEntityId || null,
    createdAt: user.createdAt,
    updatedAt: user.updatedAt || null,
    roles,
    sessions
  });
}
async function PUT(req, { params }) {
  const auth = await getAuthFromRequest(req);
  if (!auth) {
    return NextResponse.json({ ok: false, error: "Authentication required" }, { status: 401 });
  }
  const container = await createRequestContainer();
  const rbacService = container.resolve("rbacService");
  const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ["customer_accounts.manage"], { tenantId: auth.tenantId, organizationId: auth.orgId });
  if (!hasAccess) {
    return NextResponse.json({ ok: false, error: "Insufficient permissions" }, { status: 403 });
  }
  let body;
  try {
    body = await req.json();
  } catch {
    return NextResponse.json({ ok: false, error: "Invalid request body" }, { status: 400 });
  }
  const parsed = adminUpdateUserSchema.safeParse(body);
  if (!parsed.success) {
    return NextResponse.json({ ok: false, error: "Validation failed", details: parsed.error.flatten().fieldErrors }, { status: 400 });
  }
  const em = container.resolve("em");
  const user = await findOneWithDecryption(
    em,
    CustomerUser,
    { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null },
    void 0,
    { tenantId: auth.tenantId, organizationId: auth.orgId }
  );
  if (!user) {
    return NextResponse.json({ ok: false, error: "User not found" }, { status: 404 });
  }
  try {
    await enforceCommandOptimisticLockWithGuards(container, {
      resourceKind: "customer_accounts.user",
      resourceId: user.id,
      current: user.updatedAt ?? null,
      request: req
    });
  } catch (err) {
    if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status });
    throw err;
  }
  if (parsed.data.customerEntityId) {
    const owned = await isOwnedCompanyEntity(em, parsed.data.customerEntityId, {
      tenantId: auth.tenantId,
      organizationId: auth.orgId
    });
    if (!owned) {
      return NextResponse.json({ ok: false, error: "Company not found" }, { status: 400 });
    }
  }
  const nextUpdatedAt = /* @__PURE__ */ new Date();
  const updates = { updatedAt: nextUpdatedAt };
  if (parsed.data.displayName !== void 0) updates.displayName = parsed.data.displayName;
  if (parsed.data.isActive !== void 0) updates.isActive = parsed.data.isActive;
  if (parsed.data.lockedUntil !== void 0) updates.lockedUntil = parsed.data.lockedUntil ? new Date(parsed.data.lockedUntil) : null;
  if (parsed.data.personEntityId !== void 0) updates.personEntityId = parsed.data.personEntityId;
  if (parsed.data.customerEntityId !== void 0) updates.customerEntityId = parsed.data.customerEntityId;
  await em.nativeUpdate(CustomerUser, {
    id: user.id,
    tenantId: user.tenantId,
    organizationId: user.organizationId
  }, updates);
  let rolesChanged = false;
  if (parsed.data.roleIds !== void 0) {
    const requestedRoleIds = parsed.data.roleIds;
    const validRoles = requestedRoleIds.length > 0 ? await findWithDecryption(
      em,
      CustomerRole,
      {
        id: { $in: requestedRoleIds },
        tenantId: auth.tenantId,
        organizationId: auth.orgId,
        deletedAt: null
      },
      void 0,
      { tenantId: auth.tenantId, organizationId: auth.orgId }
    ) : [];
    if (validRoles.length !== requestedRoleIds.length) {
      const foundIds = new Set(validRoles.map((role) => role.id));
      const missingId = requestedRoleIds.find((roleId) => !foundIds.has(roleId));
      return NextResponse.json({ ok: false, error: `Role ${missingId} not found` }, { status: 400 });
    }
    await em.nativeDelete(CustomerUserRole, { user: user.id });
    for (const role of validRoles) {
      const userRole = em.create(CustomerUserRole, {
        user,
        role,
        createdAt: /* @__PURE__ */ new Date()
      });
      em.persist(userRole);
    }
    await em.flush();
    rolesChanged = true;
  }
  if (rolesChanged) {
    const customerRbacService = container.resolve("customerRbacService");
    await customerRbacService.invalidateUserCache(user.id);
  }
  void emitCustomerAccountsEvent("customer_accounts.user.updated", {
    id: user.id,
    recipientUserId: user.id,
    email: user.email,
    tenantId: user.tenantId,
    organizationId: user.organizationId,
    updatedBy: auth.sub
  }).catch(() => void 0);
  return NextResponse.json({ ok: true, updatedAt: nextUpdatedAt.toISOString() });
}
async function DELETE(req, { params }) {
  const auth = await getAuthFromRequest(req);
  if (!auth) {
    return NextResponse.json({ ok: false, error: "Authentication required" }, { status: 401 });
  }
  const container = await createRequestContainer();
  const rbacService = container.resolve("rbacService");
  const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ["customer_accounts.manage"], { tenantId: auth.tenantId, organizationId: auth.orgId });
  if (!hasAccess) {
    return NextResponse.json({ ok: false, error: "Insufficient permissions" }, { status: 403 });
  }
  const em = container.resolve("em");
  const user = await findOneWithDecryption(
    em,
    CustomerUser,
    { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null },
    void 0,
    { tenantId: auth.tenantId, organizationId: auth.orgId }
  );
  if (!user) {
    return NextResponse.json({ ok: false, error: "User not found" }, { status: 404 });
  }
  try {
    await enforceCommandOptimisticLockWithGuards(container, {
      resourceKind: "customer_accounts.user",
      resourceId: user.id,
      current: user.updatedAt ?? null,
      request: req
    });
  } catch (err) {
    if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status });
    throw err;
  }
  const customerUserService = container.resolve("customerUserService");
  const customerSessionService = container.resolve("customerSessionService");
  await customerUserService.softDelete(user.id, {
    tenantId: user.tenantId,
    organizationId: user.organizationId
  });
  await customerSessionService.revokeAllUserSessions(user.id);
  void emitCustomerAccountsEvent("customer_accounts.user.deleted", {
    id: user.id,
    email: user.email,
    tenantId: user.tenantId,
    organizationId: user.organizationId,
    deletedBy: auth.sub
  }).catch(() => void 0);
  return NextResponse.json({ ok: true });
}
const roleSchema = z.object({ id: z.string().uuid(), name: z.string(), slug: z.string() });
const userDetailSchema = z.object({
  id: z.string().uuid(),
  email: z.string(),
  displayName: z.string(),
  emailVerified: z.boolean(),
  isActive: z.boolean(),
  lockedUntil: z.string().datetime().nullable(),
  lastLoginAt: z.string().datetime().nullable(),
  failedLoginAttempts: z.number(),
  customerEntityId: z.string().uuid().nullable(),
  personEntityId: z.string().uuid().nullable(),
  createdAt: z.string().datetime(),
  updatedAt: z.string().datetime().nullable(),
  roles: z.array(roleSchema),
  activeSessionCount: z.number()
});
const successSchema = z.object({ ok: z.literal(true) });
const errorSchema = z.object({ ok: z.literal(false), error: z.string() });
const getMethodDoc = {
  summary: "Get customer user detail (admin)",
  description: "Returns full customer user details including CRM links, roles, and active session count.",
  tags: ["Customer Accounts Admin"],
  responses: [{
    status: 200,
    description: "User detail",
    schema: z.object({ ok: z.literal(true), user: userDetailSchema })
  }],
  errors: [
    { status: 401, description: "Not authenticated", schema: errorSchema },
    { status: 403, description: "Insufficient permissions", schema: errorSchema },
    { status: 404, description: "User not found", schema: errorSchema }
  ]
};
const putMethodDoc = {
  summary: "Update customer user (admin)",
  description: "Updates a customer user. Staff can update status, lock, CRM links, and roles. Role assignment bypasses customer_assignable check.",
  tags: ["Customer Accounts Admin"],
  requestBody: { schema: adminUpdateUserSchema },
  responses: [{ status: 200, description: "User updated", schema: successSchema }],
  errors: [
    { status: 400, description: "Validation failed or role not found", 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 deleteMethodDoc = {
  summary: "Delete customer user (admin)",
  description: "Soft deletes a customer user and revokes all their active sessions.",
  tags: ["Customer Accounts Admin"],
  responses: [{ status: 200, description: "User deleted", schema: successSchema }],
  errors: [
    { 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: "Customer user detail management (admin)",
  pathParams: z.object({ id: z.string().uuid() }),
  methods: {
    GET: getMethodDoc,
    PUT: putMethodDoc,
    DELETE: deleteMethodDoc
  }
};
export {
  DELETE,
  GET,
  PUT,
  metadata,
  openApi
};
//# sourceMappingURL=%5Bid%5D.js.map
