import { z } from "zod";

const optionalUrl = z.preprocess((value) => (value === "" ? undefined : value), z.string().url().optional());
const optionalSecret = z.preprocess((value) => (value === "" ? undefined : value), z.string().min(1).optional());
const npmPackageSpec = z.string().min(1).max(214).regex(/^\S+$/, "must not contain whitespace");

const configSchema = z.object({
  NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
  HOST: z.string().min(1).default("0.0.0.0"),
  PORT: z.coerce.number().int().min(1).max(65535).default(4100),
  LOG_LEVEL: z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]).default("info"),
  NODEDC_AGENT_GATEWAY_PUBLIC_URL: z.string().url().default("http://ops-agents.local.nodedc"),
  NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN: z.string().min(1).optional(),
  NODEDC_OPS_CODEX_INSTALL_CHANNEL: z.enum(["tarball", "registry"]).default("tarball"),
  NODEDC_OPS_CODEX_NPM_SPEC: npmPackageSpec.default("@nodedc/ops-codex"),
  NODEDC_AI_WORKSPACE_RUN_TOKEN_TTL_SECONDS: z.coerce.number().int().min(300).max(86_400).default(43_200),
  NODEDC_LAUNCHER_INTERNAL_URL: z.string().url().default("http://launcher.local.nodedc"),
  NODEDC_TASKER_INTERNAL_URL: z.string().url().default("http://task.local.nodedc"),
  NODEDC_ENGINE_INTERNAL_URL: z.string().url().default("http://172.22.0.222:3001"),
  NODEDC_ONTOLOGY_CORE_URL: z.string().url().default("http://172.22.0.222:18104"),
  NODEDC_ONTOLOGY_CORE_ACCESS_TOKEN: optionalSecret,
  NODEDC_INTERNAL_ACCESS_TOKEN: z.string().min(1).optional(),
  DATABASE_URL: optionalUrl,
});

export type AppConfig = z.infer<typeof configSchema>;

export function loadConfig(env: NodeJS.ProcessEnv = process.env): AppConfig {
  const parsed = configSchema.safeParse(env);

  if (!parsed.success) {
    const details = parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
    throw new Error(`Invalid Agent Gateway configuration: ${details}`);
  }

  return parsed.data;
}
