/**
 * All runtime configuration in one place: env vars are read and validated here
 * once, at import — nothing else in the codebase touches process.env. Docker
 * wires the browser endpoints; everything has a local-dev default.
 */
import path from "node:path";
import { fileURLToPath } from "node:url";
import { z } from "zod";

const EnvSchema = z.object({
  PORT: z.coerce.number().int().positive().default(3000),
  /** LAN-accessible by default; set HOST=127.0.0.1 for local-only. */
  HOST: z.string().min(1).default("0.0.0.0"),
  /** CDP endpoint of the resident headful Chrome (see WALLED-STORES.md). */
  BROWSER_URL: z.string().url().default("http://127.0.0.1:9222"),
  /** noVNC page the UI opens when a challenge must be solved by a human. */
  NOVNC_URL: z.string().url().default("http://127.0.0.1:8080/vnc.html?autoconnect=1"),
  BROWSER_NAV_TIMEOUT_MS: z.coerce.number().int().positive().default(30_000),
  BROWSER_CHALLENGE_CLEAR_MS: z.coerce.number().int().positive().default(12_000),
  /**
   * TEST SWITCH (leave unset normally): comma-separated store ids treated as if
   * they hit a Cloudflare challenge on every fetch — exercises the noVNC solve
   * overlay end-to-end without a real challenge. See BrowserHub.
   */
  BROWSER_FORCE_SOLVE: z.string().default(""),
});

const env = EnvSchema.parse(process.env);

/** src/core/config.ts -> repo root. Stable because this file never moves. */
const rootDir = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));

export const config = {
  port: env.PORT,
  host: env.HOST,
  rootDir,
  publicDir: path.join(rootDir, "public"),
  dbPath: path.join(rootDir, "data", "poc.sqlite"),
  browser: {
    browserURL: env.BROWSER_URL,
    solveUrl: env.NOVNC_URL,
    navTimeoutMs: env.BROWSER_NAV_TIMEOUT_MS,
    challengeClearMs: env.BROWSER_CHALLENGE_CLEAR_MS,
    forceSolve: new Set(
      env.BROWSER_FORCE_SOLVE.split(",")
        .map((s) => s.trim())
        .filter(Boolean),
    ),
  },
} as const;
