//
//  background.js
//  Xpapers Safari Web Extension
//
//  When the toolbar button is clicked, capture the page's rendered HTML and
//  forward it (with the URL) to the native handler. No popup: clicking acts
//  immediately. If the HTML can't be captured or sent, fall back to sending
//  the URL only — the app then behaves as it did before (re-fetches the URL).
//

// Runs in the page; returns the rendered DOM and basic page info.
function capturePage() {
	return {
		url: location.href,
		title: document.title,
		html: document.documentElement.outerHTML
	};
}

function logDiagnostic(message, detail) {
	console.log(`Xpapers: ${message}`, detail || "");
	browser.runtime.sendNativeMessage("application.id", {
		action: "debug",
		message: message,
		detail: JSON.stringify(detail || {})
	}).catch(() => {});
}

function makeTransferID() {
	if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
		return crypto.randomUUID();
	}

	return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
}

async function sendToNativeApp(message) {
	// Safari ignores the application identifier and routes the message to
	// SafariWebExtensionHandler; the string is required by the API.
	await browser.runtime.sendNativeMessage("application.id", message);
}

async function sendCapturedHTML(url, title, html) {
	const transferID = makeTransferID();
	const chunkSize = 200000;
	const chunkCount = Math.ceil(html.length / chunkSize);
	logDiagnostic("sending captured HTML", { url: url, transferID: transferID, htmlLength: html.length, chunkCount: chunkCount });

	await sendToNativeApp({
		action: "importHTMLStart",
		url: url,
		title: title,
		transferID: transferID
	});

	for (let index = 0; index < chunkCount; index += 1) {
		const start = index * chunkSize;
		await sendToNativeApp({
			action: "importHTMLChunk",
			transferID: transferID,
			index: index,
			total: chunkCount,
			html: html.slice(start, start + chunkSize)
		});
	}

	await sendToNativeApp({
		action: "importHTMLEnd",
		url: url,
		title: title,
		transferID: transferID,
		total: chunkCount
	});
	logDiagnostic("finished sending captured HTML", { url: url, transferID: transferID });
}

browser.action.onClicked.addListener(async (tab) => {
	if (!tab || !tab.id || !tab.url) {
		console.error("Xpapers: active tab has no URL");
		return;
	}

	// Try to capture the rendered HTML (already past any CAPTCHA in the browser).
	let captured = null;
	try {
		const results = await browser.scripting.executeScript({
			target: { tabId: tab.id },
			func: capturePage
		});
		captured = results && results[0] && results[0].result;
		logDiagnostic("captured page", {
			url: captured && captured.url,
			title: captured && captured.title,
			htmlLength: captured && captured.html && captured.html.length
		});
	} catch (error) {
		// PDF tabs, internal/restricted pages, etc. — fall back to URL only.
		console.error("Xpapers: HTML capture failed, sending URL only", error);
	}

	const url = (captured && captured.url) || tab.url;

	if (captured && captured.html) {
		try {
			await sendCapturedHTML(url, captured.title, captured.html);
			return;
		} catch (error) {
			console.error("Xpapers: sending HTML failed, retrying with URL only", error);
		}
	}

	try {
		await sendToNativeApp({ action: "import", url: url, fallbackReason: captured && captured.html ? "html-send-failed" : "html-not-captured" });
	} catch (error) {
		console.error("Xpapers: failed to send page to native app", error);
	}
});
