const path = require('path');
const fs = require('fs');
const { Builder, By, Key, until } = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const { execSync } = require('child_process');

const geckodriverPath = path.resolve(__dirname, "geckodriver");

// State to prevent race conditions
let driver = null;
let timer = null;
let isShuttingDown = false;

// Verify GeckoDriver exists
if (!fs.existsSync(geckodriverPath)) {
	throw new Error(`GeckoDriver not found at ${geckodriverPath}`);
}

function resetTimer() {
	clearTimeout(timer);
	timer = setTimeout(shutdown, 120000); // 2 minutes inactivity timeout
}

async function launch() {
	if (isShuttingDown) {
		console.log("Shutdown in progress, waiting...");
		await new Promise(resolve => setTimeout(resolve, 1000));
		return launch(); // Retry after delay
	}
	resetTimer();
	if (!driver) {
		console.log("Launching Firefox");
		const options = new firefox.Options();
		// Explicitly set headless mode and optimize for server
		options.addArguments('--headless', '--no-sandbox', '--disable-gpu');
		// Limit content processes to reduce resource usage
		options.setPreference('dom.ipc.processCount', 1);

		const service = new firefox.ServiceBuilder(geckodriverPath);
		driver = await new Builder()
			.forBrowser('firefox')
			.setFirefoxService(service)
			.setFirefoxOptions(options)
			.build();
	}
}

async function shutdown() {
	if (driver && !isShuttingDown) {
		isShuttingDown = true;
		console.log("Shutting down Firefox");
		try {
			const d = driver;
			driver = null;
			await d.quit();
			// Explicitly stop the service
			const service = d.service;
			if (service) {
				service.stop();
			}
			console.log("Firefox shutdown complete");
		} catch (error) {
			console.error("Error during shutdown:", error);
			// Forcefully kill lingering processes (Linux/Unix)
			try {
				execSync('pkill -u $USER firefox || true');
				execSync('pkill -u $USER geckodriver || true');
				console.log("Terminated lingering Firefox/GeckoDriver processes");
			} catch (killError) {
				console.error("Error killing processes:", killError);
			}
		} finally {
			isShuttingDown = false;
		}
	}
}

async function url2pdf(url) {
	await launch();
	try {
		console.log(`Navigating to ${url}`);
		await driver.get(url);
		// Add delay to stabilize Marionette communication
		await driver.sleep(3000);
		const pdf = await driver.printPage({ width: 21.0, height: 29.7 });
		resetTimer(); // Reset timer after successful operation
		return pdf;
	} catch (error) {
		console.error("Error in url2pdf:", error);
		await shutdown(); // Force shutdown on error
		throw error;
	}
}

// Periodically clean up orphaned processes (every 5 minutes)
setInterval(() => {
	try {
		const firefoxCount = execSync('pgrep -c firefox || echo 0').toString().trim();
		if (parseInt(firefoxCount) > 0 && !driver) {
			console.log(`Found ${firefoxCount} orphaned Firefox processes, cleaning up...`);
			execSync('pkill -u $USER firefox || true');
			execSync('pkill -u $USER geckodriver || true');
			console.log("Cleaned up orphaned processes");
		}
	} catch (error) {
		console.error("Error checking orphaned processes:", error);
	}
}, 300000);

module.exports = { url2pdf };
