export type WorkerEnvironment = Readonly<{
  nodeEnv: 'development' | 'test' | 'production'
  workerId: string
  healthHost: string
  healthPort: number
  pollIntervalMs: number
  shutdownTimeoutMs: number
}>

const KEYS = new Set([
  'NODE_ENV',
  'PDF2HTML_WORKER_ID',
  'PDF2HTML_WORKER_HEALTH_HOST',
  'PDF2HTML_WORKER_HEALTH_PORT',
  'PDF2HTML_WORKER_POLL_INTERVAL_MS',
  'PDF2HTML_WORKER_SHUTDOWN_TIMEOUT_MS',
])

function integer(name: string, value: string | undefined, fallback: number, minimum: number, maximum: number): number {
  if (value === undefined) return fallback
  if (!/^\d+$/.test(value)) throw new Error(`${name} must be an integer`)
  const parsed = Number(value)
  if (!Number.isSafeInteger(parsed) || parsed < minimum || parsed > maximum) {
    throw new Error(`${name} must be between ${minimum} and ${maximum}`)
  }
  return parsed
}

/** Parse an isolated worker environment. Unknown keys are rejected deliberately. */
export function parseWorkerEnvironment(input: Readonly<Record<string, string | undefined>>): WorkerEnvironment {
  const unknown = Object.keys(input).filter((key) => !KEYS.has(key))
  if (unknown.length > 0) throw new Error(`Unknown worker environment variable(s): ${unknown.sort().join(', ')}`)

  const nodeEnv = input.NODE_ENV ?? 'production'
  if (nodeEnv !== 'development' && nodeEnv !== 'test' && nodeEnv !== 'production') {
    throw new Error('NODE_ENV must be development, test, or production')
  }

  const workerId = input.PDF2HTML_WORKER_ID?.trim()
  if (!workerId) throw new Error('PDF2HTML_WORKER_ID is required')

  const healthHost = input.PDF2HTML_WORKER_HEALTH_HOST?.trim() || '127.0.0.1'
  return Object.freeze({
    nodeEnv,
    workerId,
    healthHost,
    healthPort: integer('PDF2HTML_WORKER_HEALTH_PORT', input.PDF2HTML_WORKER_HEALTH_PORT, 3001, 1, 65_535),
    pollIntervalMs: integer('PDF2HTML_WORKER_POLL_INTERVAL_MS', input.PDF2HTML_WORKER_POLL_INTERVAL_MS, 1_000, 10, 60_000),
    shutdownTimeoutMs: integer('PDF2HTML_WORKER_SHUTDOWN_TIMEOUT_MS', input.PDF2HTML_WORKER_SHUTDOWN_TIMEOUT_MS, 30_000, 100, 300_000),
  })
}

/** Select only this package's contract from the ambient process environment. */
export function workerEnvironmentFromProcess(input: NodeJS.ProcessEnv = process.env): WorkerEnvironment {
  const selected: Record<string, string | undefined> = {}
  for (const key of KEYS) selected[key] = input[key]
  return parseWorkerEnvironment(selected)
}
