/**
 * ADR-0022 platform ceilings (spec `LayeredLimit.platformCeiling`).
 *
 * Platform ceilings are the unbreakable upper bounds; org policy may only
 * configure lower limits (see `LayeredLimit.Valid`). Exact numeric values are
 * `OPEN` per spec and calibrated by capacity testing — this module is the
 * single place to wire them.
 *
 * Seven dimensions are sourced from existing runtime env vars
 * (`HUB_HTTP_BODY_LIMIT_BYTES`, `HUB_MAX_FILES_PER_MESSAGE`, `HUB_MAX_FILE_BYTES`,
 * `HUB_HTTP_REQUESTS_PER_MINUTE`, `HUB_AGENT_MAX_CONCURRENT_RUNS`,
 * `HUB_AGENT_MAX_RUN_SECONDS`, `HUB_AGENT_MAX_TURNS`). The remaining dimensions
 * are sourced from `HUB_CEILING_<DIMENSION>` env vars; until those are set the
 * dimension has no configured ceiling and the policy UI surfaces it as
 * "未配置" (cannot enforce a limit without a ceiling).
 */
import type { CapacityDimension } from "./dimensions.js";

function positiveIntEnv(name: string): number | undefined {
  const raw = process.env[name];
  if (raw === undefined || raw === "") return undefined;
  const n = Number.parseInt(raw, 10);
  return Number.isFinite(n) && n > 0 ? n : undefined;
}

const ENV_BACKED_CEILINGS: Partial<Record<CapacityDimension, string>> = {
  requestBodySize: "HUB_HTTP_BODY_LIMIT_BYTES",
  attachmentCount: "HUB_MAX_FILES_PER_MESSAGE",
  fileSize: "HUB_MAX_FILE_BYTES",
  requestRate: "HUB_HTTP_REQUESTS_PER_MINUTE",
  agentConcurrency: "HUB_AGENT_MAX_CONCURRENT_RUNS",
  runWallTime: "HUB_AGENT_MAX_RUN_SECONDS",
  runTurns: "HUB_AGENT_MAX_TURNS",
};

const CEILING_DIMENSIONS: readonly CapacityDimension[] = [
  "requestRate",
  "requestBodySize",
  "agentConcurrency",
  "admissionQueueLength",
  "admissionQueueWait",
  "fileSize",
  "attachmentCount",
  "archiveExpansion",
  "projectStorage",
  "organizationStorage",
  "memberCount",
  "projectCount",
  "teamCount",
  "folderCount",
  "sessionCount",
  "runWallTime",
  "runTurns",
  "runToolCalls",
  "toolWallTime",
  "runOutputSize",
  "processMemory",
  "processCpu",
  "processCount",
];

function envNameFor(dimension: CapacityDimension): string {
  return ENV_BACKED_CEILINGS[dimension] ?? `HUB_CEILING_${dimension.toUpperCase()}`;
}

/**
 * Returns the configured platform ceilings (only the dimensions currently
 * wired via env). Unconfigured dimensions are absent — callers must surface
 * them, not assume unlimited (spec `LayeredLimit` forbids unlimited ceilings).
 */
export function readPlatformCeilings(): Partial<Record<CapacityDimension, number>> {
  const ceilings: Partial<Record<CapacityDimension, number>> = {};
  for (const dimension of CEILING_DIMENSIONS) {
    const value = positiveIntEnv(envNameFor(dimension));
    if (value !== undefined) ceilings[dimension] = value;
  }
  return ceilings;
}
