import { resolveGatewayBindHost, resolveGatewayListenHosts } from "../config/gateway-bind.js";
import { resolveGatewayListenPlan } from "./listen.js";
import { GatewayService } from "./service.js";
import { handleSiteShareUpgrade } from "../share/site-share-router.js";
import { createHonoApp } from "./hono/app.js";
import { serve } from "@hono/node-server";
//#region src/gateway/server.ts
var GatewayServer = class {
	server;
	extraServers = [];
	config;
	service;
	constructor(config) {
		this.config = config;
		this.service = new GatewayService({
			configPath: config.configPath,
			enableHotReload: config.enableHotReload,
			deferChannelConnectUntilAfterHttp: true,
			listenBind: config.bind,
			listenCustomBindHost: config.customBindHost,
			listenPort: config.port
		});
	}
	async start() {
		const cfg = this.service.currentConfig;
		const plan = resolveGatewayListenPlan({
			cfg,
			bindOverride: this.config.bind
		});
		let bindHost;
		try {
			bindHost = await resolveGatewayBindHost({
				bindMode: plan.bindMode,
				customBindHost: plan.customBindHost ?? this.config.customBindHost
			});
		} catch (err) {
			bindHost = plan.bindHost;
			if (plan.bindMode === "custom") throw err;
		}
		if (plan.bindMode === "custom") {
			const expected = plan.customBindHost?.trim();
			if (!expected || bindHost !== expected) throw new Error(`gateway bind=custom requested ${expected ?? "(missing)"} but resolved ${bindHost}`);
		}
		const listenHosts = await resolveGatewayListenHosts(bindHost);
		console.log(`[GatewayServer] Starting gateway server on ${bindHost}:${this.config.port}...`);
		await this.service.start();
		this.service.registerGatewayShutdownForRestart(async () => {
			await this.stop();
		});
		const { configureTunnelFromGatewayConfig } = await import("../tunnel/gateway-lifecycle.js");
		await configureTunnelFromGatewayConfig(this.service.currentConfig, { deferWellKnownFetch: true });
		const effectiveToken = this.config.token || this.service.getAuthToken();
		const app = createHonoApp({
			service: this.service,
			token: effectiveToken
		});
		const primaryHost = listenHosts[0] ?? bindHost;
		const attachUpgrade = (server) => {
			server.on("upgrade", (req, socket, head) => {
				try {
					handleSiteShareUpgrade(this.service, req, socket, head);
				} catch (err) {
					console.error("[GatewayServer] site-share upgrade error:", err);
					try {
						socket.destroy();
					} catch {}
				}
			});
		};
		this.server = serve({
			fetch: app.fetch,
			port: this.config.port,
			hostname: primaryHost
		}, () => {
			console.log(`[GatewayServer] Gateway server running at http://${primaryHost}:${this.config.port}`);
			this.service.markHttpListening();
			this.service.onHttpListening().catch((err) => {
				console.error("[GatewayServer] Deferred channel startup failed:", err);
			});
		});
		attachUpgrade(this.server);
		for (const aliasHost of listenHosts.slice(1)) {
			const extra = serve({
				fetch: app.fetch,
				port: this.config.port,
				hostname: aliasHost
			});
			attachUpgrade(extra);
			this.extraServers.push(extra);
		}
	}
	async close(opts) {
		const reason = opts?.reason ?? "gateway stopping";
		console.log(`[GatewayServer] Closing gateway server: ${reason}`);
		await this.stop();
	}
	async stop() {
		console.log("[GatewayServer] Stopping gateway server...");
		const closeServer = async (server) => {
			if (!server) return;
			const forceClose = setTimeout(() => {
				server.closeAllConnections?.();
			}, 2e3);
			await new Promise((resolve) => {
				server.close(() => {
					clearTimeout(forceClose);
					resolve();
				});
			});
		};
		await closeServer(this.server);
		this.server = void 0;
		for (const extra of this.extraServers) await closeServer(extra);
		this.extraServers = [];
		await this.service.stop();
		console.log("[GatewayServer] Gateway server stopped");
	}
	get isRunning() {
		return this.server !== void 0;
	}
	get serviceInstance() {
		return this.service;
	}
};
//#endregion
export { GatewayServer };

//# sourceMappingURL=server.js.map