import { getTailnetIPv4Sync } from "../infra/tailscale.js";
import { isLoopbackHost } from "../gateway/host.js";
import { existsSync } from "node:fs";
import net from "node:net";
//#region src/config/gateway-bind.ts
function resolveGatewayBindMode(cfg, bindOverride) {
	if (bindOverride) return bindOverride;
	return cfg.gateway?.bind ?? defaultGatewayBindMode();
}
function resolveGatewayCustomBindHost(cfg, override) {
	const fromOverride = override?.trim();
	if (fromOverride) return fromOverride;
	return cfg.gateway?.customBindHost?.trim() || void 0;
}
let containerEnvironmentCache;
function isContainerEnvironment() {
	if (containerEnvironmentCache !== void 0) return containerEnvironmentCache;
	if (process.env.XOPC_CONTAINER === "1" || process.env.KUBERNETES_SERVICE_HOST) {
		containerEnvironmentCache = true;
		return true;
	}
	try {
		if (existsSync("/.dockerenv")) {
			containerEnvironmentCache = true;
			return true;
		}
	} catch {}
	containerEnvironmentCache = false;
	return false;
}
/** Reset cached container detection (tests). */
function resetContainerEnvironmentCacheForTest() {
	containerEnvironmentCache = void 0;
}
function defaultGatewayBindMode() {
	return isContainerEnvironment() ? "auto" : "loopback";
}
/** Resolve primary Tailscale tailnet IPv4 (100.x) when available. */
function pickPrimaryTailnetIPv4() {
	return getTailnetIPv4Sync();
}
function isValidIPv4(host) {
	const parts = host.trim().split(".");
	if (parts.length !== 4) return false;
	return parts.every((part) => {
		if (!/^\d+$/.test(part)) return false;
		const n = Number(part);
		return Number.isInteger(n) && n >= 0 && n <= 255;
	});
}
function resolveGatewayBindHostSync(params) {
	const { bindMode, customBindHost } = params;
	if (bindMode === "loopback") return "127.0.0.1";
	if (bindMode === "lan") return "0.0.0.0";
	if (bindMode === "auto") return isContainerEnvironment() ? "0.0.0.0" : "127.0.0.1";
	if (bindMode === "tailnet") return pickPrimaryTailnetIPv4() ?? "127.0.0.1";
	if (bindMode === "custom") {
		const host = customBindHost?.trim();
		if (!host || !isValidIPv4(host)) throw new Error("gateway.bind=custom requires a valid IPv4 gateway.customBindHost");
		return host;
	}
	return "127.0.0.1";
}
async function canBindToHost(host) {
	return new Promise((resolve) => {
		const testServer = net.createServer();
		testServer.once("error", () => resolve(false));
		testServer.once("listening", () => {
			testServer.close();
			resolve(true);
		});
		testServer.listen(0, host);
	});
}
/**
* Resolve gateway bind host with optional bindability probe (OpenClaw-aligned).
*/
async function resolveGatewayBindHost(params) {
	const mode = params.bindMode;
	if (mode === "loopback") {
		if (await canBindToHost("127.0.0.1")) return "127.0.0.1";
		return "0.0.0.0";
	}
	if (mode === "tailnet") {
		const tailnetIp = pickPrimaryTailnetIPv4();
		if (tailnetIp && await canBindToHost(tailnetIp)) return tailnetIp;
		if (await canBindToHost("127.0.0.1")) return "127.0.0.1";
		return "0.0.0.0";
	}
	if (mode === "lan") return "0.0.0.0";
	if (mode === "custom") {
		const host = params.customBindHost?.trim();
		if (!host) throw new Error("gateway.bind=custom requires gateway.customBindHost");
		if (!isValidIPv4(host)) throw new Error(`gateway.bind=custom requires a valid IPv4 customBindHost (got ${host})`);
		if (await canBindToHost(host)) return host;
		throw new Error(`gateway bind=custom requested ${host} but it is not bindable on this host`);
	}
	if (mode === "auto") {
		if (isContainerEnvironment()) return "0.0.0.0";
		if (await canBindToHost("127.0.0.1")) return "127.0.0.1";
		return "0.0.0.0";
	}
	return "0.0.0.0";
}
async function resolveGatewayListenHosts(bindHost) {
	if (bindHost !== "127.0.0.1") return [bindHost];
	if (await canBindToHost("::1")) return [bindHost, "::1"];
	return [bindHost];
}
function isNetworkAccessibleBindHost(bindHost) {
	return !isLoopbackHost(bindHost);
}
function resolveGatewayEffectiveHost(cfg, overrides) {
	return resolveGatewayBindHostSync({
		bindMode: resolveGatewayBindMode(cfg, overrides?.bind),
		customBindHost: resolveGatewayCustomBindHost(cfg)
	});
}
/** Loopback URL hostname when connecting to the gateway from the same machine. */
function resolveGatewayLocalClientHost(cfg) {
	const bindHost = resolveGatewayEffectiveHost(cfg);
	return bindHost === "0.0.0.0" || bindHost === "::" ? "127.0.0.1" : bindHost;
}
//#endregion
export { canBindToHost, defaultGatewayBindMode, isContainerEnvironment, isNetworkAccessibleBindHost, isValidIPv4, pickPrimaryTailnetIPv4, resetContainerEnvironmentCacheForTest, resolveGatewayBindHost, resolveGatewayBindHostSync, resolveGatewayBindMode, resolveGatewayCustomBindHost, resolveGatewayEffectiveHost, resolveGatewayListenHosts, resolveGatewayLocalClientHost };

//# sourceMappingURL=gateway-bind.js.map