import { createLogger } from "../../../utils/logger/index.js";
import { init_logger } from "../../../utils/logger.js";
import { acquireBrowserInstallLock, cancelBrowserInstall } from "../../../browser/install-lock.js";
import { runPlaywrightChromiumInstallWithProgress } from "../../../browser/providers/playwright-install.js";
import { streamSSE } from "hono/streaming";
//#region src/gateway/hono/routes/browser-install.ts
init_logger();
const log = createLogger("GatewayBrowserInstall");
function parseCloakInstallBody(body) {
	const input = body && typeof body === "object" && !Array.isArray(body) ? body : {};
	return {
		cacheDir: typeof input.cacheDir === "string" && input.cacheDir.trim() ? input.cacheDir.trim() : void 0,
		binaryPath: typeof input.binaryPath === "string" && input.binaryPath.trim() ? input.binaryPath.trim() : void 0
	};
}
function isInstallCancelled(err, signal) {
	if (signal?.aborted) return true;
	return err instanceof Error && err.message === "Install cancelled";
}
async function writeInstallProgress(stream, progress) {
	try {
		await stream.writeSSE({
			event: "progress",
			data: JSON.stringify(progress)
		});
	} catch {}
}
function createInstallProgressEmitter(stream) {
	let chain = Promise.resolve();
	return (progress) => {
		chain = chain.then(() => writeInstallProgress(stream, progress));
		return chain;
	};
}
async function runBrowserInstallStream(kind, stream, run) {
	const lock = acquireBrowserInstallLock(kind);
	if (!lock) {
		await stream.writeSSE({
			event: "result",
			data: JSON.stringify({
				ok: false,
				error: "busy",
				message: "An install for this browser type is already in progress."
			})
		});
		return;
	}
	try {
		const emitProgress = createInstallProgressEmitter(stream);
		const payload = await run(lock.signal, emitProgress);
		await emitProgress({
			phase: "ready",
			message: "Install complete",
			percent: 100
		});
		try {
			await stream.writeSSE({
				event: "result",
				data: JSON.stringify({
					ok: true,
					payload
				})
			});
		} catch {
			log.info({ kind }, "Gateway: browser install finished after client disconnected");
		}
	} catch (err) {
		if (isInstallCancelled(err, lock.signal)) {
			log.info({ kind }, "Gateway: browser install cancelled by user");
			try {
				await stream.writeSSE({
					event: "result",
					data: JSON.stringify({
						ok: false,
						error: "cancelled",
						message: "Install cancelled"
					})
				});
			} catch {}
			return;
		}
		const message = err instanceof Error ? err.message : String(err);
		log.warn({
			kind,
			errorMessage: message
		}, "Gateway: streamed browser install failed");
		try {
			await stream.writeSSE({
				event: "result",
				data: JSON.stringify({
					ok: false,
					error: "install-failed",
					message
				})
			});
		} catch {}
	} finally {
		lock.release();
	}
}
function registerInstallCancelRoute(authenticated, deps, kind, path) {
	const { strictRateLimitMiddleware } = deps;
	authenticated.post(path, strictRateLimitMiddleware, (c) => {
		const cancelled = cancelBrowserInstall(kind);
		return c.json({
			ok: true,
			payload: { cancelled }
		});
	});
}
function registerBrowserInstallRoutes(authenticated, deps) {
	const { strictRateLimitMiddleware } = deps;
	registerInstallCancelRoute(authenticated, deps, "playwright", "/api/browser/playwright/install/cancel");
	registerInstallCancelRoute(authenticated, deps, "cloakbrowser", "/api/browser/cloakbrowser/install/cancel");
	authenticated.post("/api/browser/playwright/install/stream", strictRateLimitMiddleware, async (c) => {
		return streamSSE(c, async (stream) => {
			await runBrowserInstallStream("playwright", stream, async (signal, emitProgress) => {
				log.info("Gateway: starting streamed Playwright Chromium install");
				await runPlaywrightChromiumInstallWithProgress({
					signal,
					onProgress: emitProgress
				});
				const { playwrightChromiumDoctor } = await import("../../../browser/providers/playwright-doctor.js");
				const payload = await playwrightChromiumDoctor();
				if (!payload.installed) throw new Error(payload.reason ?? "Chromium not found after install");
				return payload;
			});
		});
	});
	authenticated.post("/api/browser/cloakbrowser/install/stream", strictRateLimitMiddleware, async (c) => {
		let body;
		try {
			body = await c.req.json();
		} catch {
			body = {};
		}
		const { cacheDir, binaryPath } = parseCloakInstallBody(body);
		return streamSSE(c, async (stream) => {
			await runBrowserInstallStream("cloakbrowser", stream, async (signal, emitProgress) => {
				log.info({
					cacheDir,
					binaryPath: binaryPath ? "(custom)" : void 0
				}, "Gateway: starting streamed CloakBrowser install");
				const { installCloakBrowser } = await import("../../../browser/providers/cloakbrowser.js");
				return installCloakBrowser({
					cacheDir,
					binaryPath,
					signal,
					onProgress: emitProgress
				});
			});
		});
	});
}
//#endregion
export { registerBrowserInstallRoutes };

//# sourceMappingURL=browser-install.js.map