import {
  membershipListByUserOperation
} from "./chunk-V6AO5T57.mjs";
import {
  ForbiddenError,
  NotFoundError,
  ValidationError
} from "./chunk-FYHBHHWK.mjs";
import {
  getDynamoControlService
} from "./chunk-EUIP2U5F.mjs";

// src/data/operations/fhir-reference.ts
function idFromReference(reference, prefix) {
  if (!reference || !reference.startsWith(prefix)) {
    return void 0;
  }
  const id = reference.slice(prefix.length);
  return id.length > 0 ? id : void 0;
}

// src/data/operations/control/user/user-find-by-sub-operation.ts
async function findUserBySubOperation(params) {
  const { cognitoSub, tableName } = params;
  const service = getDynamoControlService(tableName);
  const indexResult = await service.entities.user.query.gsi2({ cognitoSub }).go({ limit: 1, attributes: ["id"] });
  const indexItem = indexResult.data?.[0];
  if (!indexItem) {
    return void 0;
  }
  const canonical = await service.entities.user.get({ id: indexItem.id, sk: "CURRENT" }).go();
  const row = canonical.data;
  if (!row) {
    return void 0;
  }
  return {
    id: row.id,
    cognitoSub: row.cognitoSub,
    resource: row.resource,
    summary: row.summary,
    vid: row.vid,
    lastUpdated: row.lastUpdated
  };
}

// src/data/operations/control/user/user-resource-helpers.ts
function parseUserResource(resource) {
  try {
    return JSON.parse(resource);
  } catch {
    return void 0;
  }
}

// src/data/operations/control/user/user-admin-set-context-operation.ts
import { extractSummary } from "@openhi/types";

// src/data/operations/control/user/user-get-by-id-operation.ts
async function getUserByIdOperation(params) {
  const { id, tableName } = params;
  const service = getDynamoControlService(tableName);
  const response = await service.entities.user.get({ id, sk: "CURRENT" }).go();
  const item = response.data;
  if (!item) {
    throw new NotFoundError(`User not found: ${id}`);
  }
  const parsedResource = JSON.parse(item.resource);
  return {
    id,
    resource: { resourceType: "User", id, ...parsedResource }
  };
}

// src/data/operations/control/user/user-admin-set-context-operation.ts
var SK = "CURRENT";
async function adminSetUserContextOperation(params) {
  const {
    context,
    targetUserId,
    tenantReference,
    workspaceReference,
    tableName
  } = params;
  const tenantId = idFromReference(tenantReference, "Tenant/");
  if (!tenantId) {
    throw new ValidationError(
      "tenant.reference must be a 'Tenant/<id>' reference."
    );
  }
  const workspaceId = idFromReference(workspaceReference, "Workspace/");
  if (!workspaceId) {
    throw new ValidationError(
      "workspace.reference must be a 'Workspace/<id>' reference."
    );
  }
  const target = await getUserByIdOperation({
    context,
    id: targetUserId,
    tableName
  });
  const projection = await membershipListByUserOperation({
    userId: targetUserId,
    mode: "workspaceInTenant",
    tenantId,
    tableName
  });
  const hasMembership = projection.items.some(
    (row) => row.workspaceId === workspaceId
  );
  if (!hasMembership) {
    throw new ForbiddenError(
      `User is not a member of Workspace/${workspaceId} in Tenant/${tenantId}.`
    );
  }
  const updatedResource = {
    ...target.resource,
    resourceType: "User",
    id: targetUserId,
    currentTenant: { reference: `Tenant/${tenantId}` },
    currentWorkspace: { reference: `Workspace/${workspaceId}` }
  };
  const lastUpdated = (params.now ? params.now() : /* @__PURE__ */ new Date()).toISOString();
  const vid = `${Date.now()}`;
  const summary = JSON.stringify(
    extractSummary(updatedResource)
  );
  const service = getDynamoControlService(tableName);
  await service.entities.user.patch({ id: targetUserId, sk: SK }).set({
    resource: JSON.stringify(updatedResource),
    summary,
    vid,
    lastUpdated
  }).go();
  return {
    id: targetUserId,
    resource: updatedResource,
    meta: { lastUpdated, versionId: vid }
  };
}

// src/data/operations/control/user/user-create-operation.ts
import { extractSummary as extractSummary2 } from "@openhi/types";
import { ulid } from "ulid";
async function createUserOperation(params) {
  const { context, body, tableName } = params;
  const service = getDynamoControlService(tableName);
  const id = body.id ?? ulid();
  const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
  const lastUpdated = context.date ?? (/* @__PURE__ */ new Date()).toISOString();
  const vid = `1`;
  const resource = { resourceType: "User", id, ...parsedResource };
  const summary = JSON.stringify(extractSummary2(resource));
  await service.entities.user.put({
    id,
    resource: JSON.stringify(resource),
    summary,
    vid,
    lastUpdated
  }).go();
  return {
    id,
    resource,
    meta: { lastUpdated, versionId: vid }
  };
}

// src/data/operations/control/user/user-switch-tenant-workspace-operation.ts
import { extractSummary as extractSummary3 } from "@openhi/types";
var SK2 = "CURRENT";
async function switchUserTenantWorkspaceOperation(params) {
  const { cognitoSub, tenantReference, workspaceReference, tableName } = params;
  const tenantId = idFromReference(tenantReference, "Tenant/");
  if (!tenantId) {
    throw new ValidationError(
      "tenant.reference must be a 'Tenant/<id>' reference."
    );
  }
  const workspaceId = idFromReference(workspaceReference, "Workspace/");
  if (!workspaceId) {
    throw new ValidationError(
      "workspace.reference must be a 'Workspace/<id>' reference."
    );
  }
  const user = await findUserBySubOperation({
    // findUserBySubOperation does not read context fields; pass a stub.
    context: {
      tenantId: "",
      workspaceId: "",
      date: "",
      actorId: "",
      actorName: "",
      actorType: "internal-system"
    },
    cognitoSub,
    tableName
  });
  if (!user) {
    throw new NotFoundError(
      "User not yet provisioned for the authenticated Cognito subject."
    );
  }
  const projection = await membershipListByUserOperation({
    userId: user.id,
    mode: "workspaceInTenant",
    tenantId,
    tableName
  });
  const hasMembership = projection.items.some(
    (row) => row.workspaceId === workspaceId
  );
  if (!hasMembership) {
    throw new ForbiddenError(
      `User is not a member of Workspace/${workspaceId} in Tenant/${tenantId}.`
    );
  }
  const existingResource = parseUserResource(user.resource) ?? {};
  const updatedResource = {
    ...existingResource,
    resourceType: "User",
    id: user.id,
    currentTenant: { reference: `Tenant/${tenantId}` },
    currentWorkspace: { reference: `Workspace/${workspaceId}` }
  };
  const lastUpdated = (params.now ? params.now() : /* @__PURE__ */ new Date()).toISOString();
  const vid = `${Date.now()}`;
  const summary = JSON.stringify(
    extractSummary3(updatedResource)
  );
  const service = getDynamoControlService(tableName);
  await service.entities.user.patch({ id: user.id, sk: SK2 }).set({
    resource: JSON.stringify(updatedResource),
    summary,
    vid,
    lastUpdated
  }).go();
  return {
    id: user.id,
    resource: updatedResource,
    meta: { lastUpdated, versionId: vid }
  };
}

// src/data/operations/control/user/user-update-operation.ts
import { extractSummary as extractSummary4 } from "@openhi/types";
async function updateUserOperation(params) {
  const { context, id, body, tableName } = params;
  const service = getDynamoControlService(tableName);
  const existing = await service.entities.user.get({ id, sk: "CURRENT" }).go();
  if (!existing.data) {
    throw new NotFoundError(`User not found: ${id}`);
  }
  const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
  const lastUpdated = context.date ?? (/* @__PURE__ */ new Date()).toISOString();
  const vid = `${Date.now()}`;
  const resource = { resourceType: "User", id, ...parsedResource };
  const summary = JSON.stringify(extractSummary4(resource));
  await service.entities.user.put({
    id,
    resource: JSON.stringify(resource),
    summary,
    vid,
    lastUpdated
  }).go();
  return {
    id,
    resource,
    meta: { lastUpdated, versionId: vid }
  };
}

// src/data/operations/control/user/user-delete-operation.ts
async function deleteUserOperation(params) {
  const { id, tableName } = params;
  const service = getDynamoControlService(tableName);
  await service.entities.user.delete({ id, sk: "CURRENT" }).go();
}

export {
  getUserByIdOperation,
  idFromReference,
  adminSetUserContextOperation,
  createUserOperation,
  deleteUserOperation,
  updateUserOperation,
  findUserBySubOperation,
  parseUserResource,
  switchUserTenantWorkspaceOperation
};
//# sourceMappingURL=chunk-UWVPF6GB.mjs.map