import path from 'node:path';

// One .env at the repo root serves web, game server and Prisma. Production hosts inject env vars.
try {
  process.loadEnvFile(path.resolve(import.meta.dirname, '../../../.env'));
} catch {
  // optional
}

const isProduction = process.env.NODE_ENV === 'production';

function required(name: string, devFallback?: string): string {
  const value = process.env[name];
  if (value && value.length > 0) return value;
  if (!isProduction && devFallback !== undefined) return devFallback;
  throw new Error(`Missing required environment variable ${name}`);
}

export interface ServerConfig {
  isProduction: boolean;
  port: number;
  authSecret: string;
  databaseUrl: string;
  /** Origins allowed to open sockets / call the HTTP API (CORS). */
  webOrigins: string[];
  redisUrl: string | null;
  /** Number of trusted proxies in front of the server (TRUST_PROXY); 0 = ignore X-Forwarded-For. */
  trustProxyHops: number;
  /** Salt for hashing device ids before storing them. */
  deviceSalt: string;
  /** Turn off the background scheduler / purge (tests). */
  enableScheduler: boolean;
  /** Validate every outgoing public view against the strict protocol schema (dev/test safety net). */
  validateOutgoing: boolean;
}

export function loadConfig(overrides: Partial<ServerConfig> = {}): ServerConfig {
  const authSecret = required('AUTH_SECRET', 'dev-only-insecure-secret-change-me-0123456789');
  if (isProduction && authSecret.length < 32) throw new Error('AUTH_SECRET must be at least 32 characters');
  const config: ServerConfig = {
    isProduction,
    port: Number(process.env.GAME_SERVER_PORT ?? process.env.PORT ?? 4000),
    authSecret,
    databaseUrl: required('DATABASE_URL', 'postgresql://pintrush:pintrush@localhost:54329/pintrush'),
    webOrigins: (process.env.WEB_ORIGIN ?? 'http://localhost:3000')
      .split(',')
      .map((s) => s.trim())
      .filter(Boolean),
    redisUrl: process.env.REDIS_URL || null,
    trustProxyHops: parseTrustProxy(process.env.TRUST_PROXY),
    deviceSalt: process.env.DEVICE_SALT ?? process.env.ANALYTICS_SALT ?? authSecret,
    enableScheduler: process.env.DISABLE_SCHEDULER !== '1',
    validateOutgoing: !isProduction,
    ...overrides,
  };
  return config;
}

/** TRUST_PROXY: unset/0/false → 0 hops; 1/true → 1 (one load balancer, e.g. Render/Fly); N → N. */
function parseTrustProxy(raw: string | undefined): number {
  if (!raw || raw === 'false' || raw === '0') return 0;
  if (raw === 'true') return 1;
  const n = Number(raw);
  return Number.isInteger(n) && n > 0 && n < 10 ? n : 1;
}
