/**
 * Public client env.
 *
 * Prefer runtime-config.js (window.__CONNECTHUB_ENV__) so production Apache can
 * change API/gateway/TURN URLs without relying on Next build-time inlining — which
 * is easy to get wrong in a monorepo (root .env is not auto-loaded by Next).
 */
export type PublicEnv = {
  apiUrl: string;
  gatewayUrl: string;
};

export type IcePublicEnv = {
  stunUrls: string[];
  turnUrls: string[];
  turnUsername?: string;
  turnCredential?: string;
};

declare global {
  interface Window {
    __CONNECTHUB_ENV__?: {
      NEXT_PUBLIC_API_URL?: string;
      NEXT_PUBLIC_GATEWAY_URL?: string;
      NEXT_PUBLIC_STUN_URLS?: string;
      NEXT_PUBLIC_TURN_URL?: string;
      NEXT_PUBLIC_TURN_URLS?: string;
      NEXT_PUBLIC_TURN_USERNAME?: string;
      NEXT_PUBLIC_TURN_CREDENTIAL?: string;
    };
  }
}

/** `location.hostname` is `::1` without brackets; `location.host` may be `[::1]:3000`. */
export function isLocalHostname(hostname: string): boolean {
  const host = hostname.replace(/^\[|\]$/g, "").toLowerCase();
  return host === "localhost" || host === "127.0.0.1" || host === "::1";
}

function fromRuntime(): Record<string, string | undefined> {
  if (typeof window === "undefined") return {};
  // runtime-config.js is generated for production deploys and lives in
  // public/, so `next dev` would otherwise send every local click to the
  // live API. Ignore it on loopback; production hosts still use it.
  if (isLocalHostname(window.location.hostname)) return {};
  const cfg = window.__CONNECTHUB_ENV__;
  if (!cfg) return {};
  return { ...cfg };
}

function splitUrls(raw: string | undefined): string[] {
  if (!raw) return [];
  return raw
    .split(",")
    .map((url) => url.trim())
    .filter(Boolean);
}

export function getPublicEnv(): PublicEnv {
  const runtime = fromRuntime();
  const apiUrl = (
    runtime.NEXT_PUBLIC_API_URL ||
    process.env.NEXT_PUBLIC_API_URL ||
    (typeof window !== "undefined" && isLocalHostname(window.location.hostname) ? "http://127.0.0.1:3001" : "")
  ).replace(/\/$/, "");
  const gatewayUrl = (
    runtime.NEXT_PUBLIC_GATEWAY_URL ||
    process.env.NEXT_PUBLIC_GATEWAY_URL ||
    (typeof window !== "undefined" && isLocalHostname(window.location.hostname) ? "http://localhost:3002" : "")
  ).replace(/\/$/, "");
  return { apiUrl, gatewayUrl };
}

export function getApiUrl(): string {
  return getPublicEnv().apiUrl;
}

export function getGatewayUrl(): string {
  return getPublicEnv().gatewayUrl;
}

/** ICE servers for WebRTC — read at call time so runtime-config TURN applies. */
export function getIcePublicEnv(): IcePublicEnv {
  const runtime = fromRuntime();
  const stunRaw =
    runtime.NEXT_PUBLIC_STUN_URLS ||
    process.env.NEXT_PUBLIC_STUN_URLS ||
    "stun:stun.l.google.com:19302,stun:stun1.l.google.com:19302";
  const turnUrls = [
    ...splitUrls(runtime.NEXT_PUBLIC_TURN_URLS || process.env.NEXT_PUBLIC_TURN_URLS),
    ...splitUrls(runtime.NEXT_PUBLIC_TURN_URL || process.env.NEXT_PUBLIC_TURN_URL),
  ];
  return {
    stunUrls: splitUrls(stunRaw),
    turnUrls,
    turnUsername: runtime.NEXT_PUBLIC_TURN_USERNAME || process.env.NEXT_PUBLIC_TURN_USERNAME || undefined,
    turnCredential: runtime.NEXT_PUBLIC_TURN_CREDENTIAL || process.env.NEXT_PUBLIC_TURN_CREDENTIAL || undefined,
  };
}

export function buildIceServers(): RTCIceServer[] {
  const { stunUrls, turnUrls, turnUsername, turnCredential } = getIcePublicEnv();
  const servers: RTCIceServer[] = stunUrls.map((urls) => ({ urls }));
  const turnReady = Boolean(turnUsername && turnCredential);
  for (const urls of turnUrls) {
    if (!turnReady) continue;
    servers.push({
      urls,
      username: turnUsername,
      credential: turnCredential,
    });
  }
  return servers;
}

/** True only when TURN URLs and credentials are all present. */
export function hasTurnConfigured(): boolean {
  const ice = getIcePublicEnv();
  return ice.turnUrls.length > 0 && Boolean(ice.turnUsername && ice.turnCredential);
}

/** URLs present but username/password missing — common misconfig. */
export function turnCredentialsMissing(): boolean {
  const ice = getIcePublicEnv();
  return ice.turnUrls.length > 0 && !(ice.turnUsername && ice.turnCredential);
}
