const intEnv = (name: string, fallback: number) => {
  const value = process.env[name];
  if (!value) return fallback;
  const parsed = Number.parseInt(value, 10);
  return Number.isFinite(parsed) ? parsed : fallback;
};

const requiredEnv = (name: string) => {
  const value = process.env[name]?.trim();
  if (!value) throw new Error(`${name} is required.`);
  return value;
};

export const env = {
  buildSha: process.env.SPOON_BUILD_SHA?.trim() ?? 'development',
  buildCreatedAt: process.env.SPOON_BUILD_CREATED_AT?.trim() ?? 'unknown',
  convexUrl:
    process.env.NEXT_PUBLIC_CONVEX_URL?.trim() ??
    process.env.CONVEX_SELF_HOSTED_URL?.trim() ??
    'http://localhost:3210',
  workerToken: requiredEnv('SPOON_WORKER_TOKEN'),
  workerId: process.env.SPOON_AGENT_WORKER_ID?.trim() ?? 'local-worker',
  runtime: process.env.SPOON_AGENT_RUNTIME?.trim() ?? 'docker',
  containerRuntime:
    process.env.SPOON_AGENT_CONTAINER_RUNTIME?.trim() ??
    process.env.SPOON_CONTAINER_RUNTIME?.trim() ??
    'docker',
  containerVolumeOptions:
    process.env.SPOON_AGENT_CONTAINER_VOLUME_OPTIONS?.trim(),
  containerAccess:
    process.env.SPOON_AGENT_CONTAINER_ACCESS?.trim() === 'host_port'
      ? 'host_port'
      : 'network',
  jobImage:
    process.env.SPOON_AGENT_JOB_IMAGE?.trim() ?? 'spoon-agent-job:latest',
  // Interactive terminal: image for the persistent shell container (defaults to
  // the job image), the secret shared with the Next app for verifying terminal
  // tokens, and how long an idle terminal container survives before cleanup.
  terminalImage:
    process.env.SPOON_AGENT_TERMINAL_IMAGE?.trim() ??
    process.env.SPOON_AGENT_JOB_IMAGE?.trim() ??
    'spoon-agent-job:latest',
  terminalSecret:
    process.env.SPOON_AGENT_TERMINAL_SECRET?.trim() ??
    process.env.SPOON_AGENT_WORKER_INTERNAL_TOKEN?.trim() ??
    process.env.SPOON_WORKER_TOKEN?.trim() ??
    '',
  terminalIdleMs: intEnv('SPOON_AGENT_TERMINAL_IDLE_MS', 1_800_000),
  // How long a per-user box container survives with no active jobs/terminals.
  boxIdleMs: intEnv('SPOON_AGENT_BOX_IDLE_MS', 1_800_000),
  // Dev-only: exit if the parent dev runner dies, so the worker never orphans
  // and holds port 3921 across restarts. Set by scripts/dev-agent-worker.
  devWatchdog: process.env.SPOON_AGENT_DEV_WATCHDOG === '1',
  workdir: process.env.SPOON_AGENT_WORKDIR?.trim() ?? '.local/agent-work',
  hostWorkdir: process.env.SPOON_AGENT_HOST_WORKDIR?.trim(),
  network: process.env.SPOON_AGENT_NETWORK?.trim(),
  pollMs: intEnv('SPOON_AGENT_POLL_MS', 5_000),
  httpPort: intEnv('SPOON_AGENT_WORKER_HTTP_PORT', 3921),
  internalToken:
    process.env.SPOON_AGENT_WORKER_INTERNAL_TOKEN?.trim() ??
    process.env.SPOON_WORKER_TOKEN?.trim() ??
    '',
  maxConcurrentJobs: intEnv('SPOON_AGENT_MAX_CONCURRENT_JOBS', 1),
  jobTimeoutMs: intEnv('SPOON_AGENT_JOB_TIMEOUT_MS', 1_800_000),
  githubAppId: requiredEnv('GITHUB_APP_ID'),
  githubPrivateKey: requiredEnv('GITHUB_APP_PRIVATE_KEY').replaceAll(
    '\\n',
    '\n',
  ),
};
