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 { Organization } from "@open-mercato/core/modules/directory/data/entities";
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
const BUILTIN_DICTIONARY_ROUTE_KINDS = [
  "statuses",
  "sources",
  "lifecycle-stages",
  "address-types",
  "activity-types",
  "deal-statuses",
  "pipeline-stages",
  "job-titles",
  "industries",
  "temperature",
  "renewal-quarters",
  "person-company-roles",
  "interaction-statuses"
];
const dictionaryCustomKindSchema = z.string().trim().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Invalid dictionary kind");
const dictionaryKindSchema = z.union([
  z.enum(BUILTIN_DICTIONARY_ROUTE_KINDS),
  dictionaryCustomKindSchema
]);
const KIND_MAP = {
  statuses: "status",
  sources: "source",
  "lifecycle-stages": "lifecycle_stage",
  "address-types": "address_type",
  "activity-types": "activity_type",
  "deal-statuses": "deal_status",
  "pipeline-stages": "pipeline_stage",
  "job-titles": "job_title",
  industries: "industry",
  temperature: "temperature",
  "renewal-quarters": "renewal_quarter",
  "person-company-roles": "person_company_role",
  "interaction-statuses": "interaction_status"
};
const paramsSchema = z.object({
  kind: dictionaryKindSchema
});
function resolveDictionaryActorId(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 mapDictionaryKind(kind) {
  const parsed = paramsSchema.parse({ kind });
  const mappedKind = Object.prototype.hasOwnProperty.call(KIND_MAP, parsed.kind) ? KIND_MAP[parsed.kind] : parsed.kind;
  return {
    kind: parsed.kind,
    mappedKind
  };
}
async function resolveDictionaryRouteContext(req, options) {
  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,
    selectedId: options?.selectedId
  });
  const em = container.resolve("em");
  const tenantId = scope?.tenantId ?? auth.tenantId;
  const organizationId = scope?.selectedId ?? auth.orgId ?? null;
  const normalizeId = (value) => {
    if (typeof value !== "string") return null;
    const trimmed = value.trim();
    return trimmed.length > 0 ? trimmed : null;
  };
  const candidateIds = /* @__PURE__ */ new Set();
  const pushCandidate = (value) => {
    const normalized = normalizeId(value);
    if (normalized) candidateIds.add(normalized);
  };
  pushCandidate(organizationId);
  pushCandidate(auth.orgId ?? null);
  if (Array.isArray(scope?.filterIds)) {
    for (const id of scope.filterIds) pushCandidate(id);
  }
  if (Array.isArray(scope?.allowedIds)) {
    for (const id of scope.allowedIds) pushCandidate(id);
  }
  let cache;
  try {
    cache = container.resolve("cache");
  } catch {
  }
  const readableOrganizationIds = /* @__PURE__ */ new Set();
  try {
    const shouldLoadAll = candidateIds.size === 0;
    const organizations = await em.find(
      Organization,
      {
        tenant: tenantId,
        deletedAt: null,
        ...shouldLoadAll ? {} : { id: { $in: Array.from(candidateIds) } }
      },
      { fields: ["id", "ancestorIds"] }
    );
    for (const organization of organizations) {
      const id = normalizeId(organization.id);
      if (id) readableOrganizationIds.add(id);
      if (Array.isArray(organization.ancestorIds)) {
        for (const ancestorId of organization.ancestorIds) {
          const normalized = normalizeId(ancestorId);
          if (normalized) readableOrganizationIds.add(normalized);
        }
      }
    }
    if (!shouldLoadAll && readableOrganizationIds.size === 0) {
      for (const id of candidateIds) readableOrganizationIds.add(id);
    }
  } catch (err) {
    logger.warn("Failed to resolve ancestor organizations", { component: "dictionaries.context", err });
    for (const id of candidateIds) readableOrganizationIds.add(id);
  }
  const commandContext = {
    container,
    auth,
    organizationScope: scope,
    selectedOrganizationId: organizationId,
    organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),
    request: req
  };
  return {
    auth,
    translate,
    em,
    organizationId,
    tenantId,
    readableOrganizationIds: Array.from(readableOrganizationIds),
    cache,
    container,
    ctx: commandContext
  };
}
export {
  BUILTIN_DICTIONARY_ROUTE_KINDS,
  dictionaryKindSchema,
  mapDictionaryKind,
  paramsSchema,
  resolveDictionaryActorId,
  resolveDictionaryRouteContext
};
//# sourceMappingURL=context.js.map
