import { createLogger } from "../utils/logger/index.js";
import { init_logger } from "../utils/logger.js";
//#region src/browser/session-lifecycle.ts
init_logger();
const log = createLogger("BrowserLifecycle");
const DEFAULT_TRACING = {
	enabled: false,
	outputDir: "/tmp/xopc-traces",
	screenshots: true,
	snapshots: false
};
/**
* Start Playwright tracing on a browser context for session recording.
* Captures network, actions, and optionally screenshots/snapshots.
*/
async function startTracing(context, options) {
	const opts = {
		...DEFAULT_TRACING,
		...options
	};
	if (!opts.enabled) return;
	try {
		await context.tracing.start({
			screenshots: opts.screenshots ?? true,
			snapshots: opts.snapshots ?? false
		});
		log.info({ outputDir: opts.outputDir }, "Session tracing started");
	} catch (e) {
		const msg = e instanceof Error ? e.message : String(e);
		log.warn({ errorMessage: msg }, `Failed to start tracing: ${msg}`);
	}
}
/**
* Stop tracing and save the trace file.
*
* @returns Path to the saved trace file, or undefined if tracing was not active.
*/
async function stopTracing(context, options) {
	const opts = {
		...DEFAULT_TRACING,
		...options
	};
	if (!opts.enabled) return void 0;
	const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
	const tracePath = `${opts.outputDir}/trace-${timestamp}.zip`;
	try {
		const { mkdir } = await import("node:fs/promises");
		await mkdir(opts.outputDir, { recursive: true });
		await context.tracing.stop({ path: tracePath });
		log.info({ tracePath }, "Session trace saved");
		return tracePath;
	} catch (e) {
		const msg = e instanceof Error ? e.message : String(e);
		log.warn({ errorMessage: msg }, `Failed to save trace: ${msg}`);
		return;
	}
}
/**
* Known bot detection indicators in page content or response headers.
* When detected, we log a warning so the agent/user can adjust strategy.
*/
const BOT_DETECTION_PATTERNS = [
	/captcha/i,
	/recaptcha/i,
	/hcaptcha/i,
	/cloudflare.*challenge/i,
	/please verify you are (a )?human/i,
	/access denied/i,
	/403 forbidden/i,
	/blocked.*bot/i,
	/automated.*browser/i,
	/unusual.*traffic/i,
	/just a moment/i,
	/checking your browser/i,
	/security check/i,
	/verify.*not.*robot/i,
	/turnstile/i,
	/browser.*verification/i
];
/**
* Check a page for signs of bot detection / CAPTCHA challenge.
* Returns indicators found. Non-blocking — for advisory logging only.
*/
async function checkBotDetection(page) {
	const indicators = [];
	try {
		const combined = `${await page.title()}\n${await page.evaluate(() => globalThis.document.body.innerText.slice(0, 2e3)).catch(() => "")}`;
		for (const pattern of BOT_DETECTION_PATTERNS) {
			const match = combined.match(pattern);
			if (match) indicators.push(match[0]);
		}
		if (indicators.length > 0) log.warn({
			url: page.url(),
			indicators
		}, `Bot detection likely: ${indicators.join(", ")}`);
	} catch {}
	return {
		detected: indicators.length > 0,
		indicators
	};
}
/**
* Kill orphan Chromium processes that may have been left behind by crashed sessions.
*
* This is a best-effort cleanup. On macOS/Linux, searches for chromium/chrome
* processes with the `--no-sandbox` flag (which xopc adds to all launches).
*
* @returns Number of processes killed.
*/
async function cleanupOrphanProcesses() {
	const { exec } = await import("node:child_process");
	const { promisify } = await import("node:util");
	const execAsync = promisify(exec);
	let killed = 0;
	try {
		const { stdout } = await execAsync("ps aux | grep -E \"chromium|chrome\" | grep \"no-sandbox\" | grep -v grep").catch(() => ({ stdout: "" }));
		const lines = stdout.trim().split("\n").filter(Boolean);
		for (const line of lines) {
			const parts = line.trim().split(/\s+/);
			const pid = Number(parts[1]);
			if (!pid || pid === process.pid) continue;
			try {
				process.kill(pid, "SIGTERM");
				killed++;
				log.info({ pid }, "Killed orphan browser process");
			} catch {}
		}
		if (killed > 0) log.info({ killed }, `Cleaned up ${killed} orphan browser process(es)`);
	} catch (e) {
		const msg = e instanceof Error ? e.message : String(e);
		log.debug({ errorMessage: msg }, "Orphan cleanup skipped or failed");
	}
	return killed;
}
//#endregion
export { checkBotDetection, cleanupOrphanProcesses, startTracing, stopTracing };

//# sourceMappingURL=session-lifecycle.js.map