import { exportInvoicePdfFromSlug } from '../../woocommerce/invoice/exportInvoicePdf';

interface OrderReceivedConfig {
	restUrl: string;
	nonce: string;
	orderId: number;
	orderKey: string;
}

declare global {
	interface Window {
		__PDFDRAFT_ORDER_RECEIVED__?: OrderReceivedConfig;
	}
}

function getConfig(): OrderReceivedConfig | null {
	const cfg = window.__PDFDRAFT_ORDER_RECEIVED__;
	if ( ! cfg?.restUrl || ! cfg.nonce || ! cfg.orderId || ! cfg.orderKey ) {
		return null;
	}
	return cfg;
}

// ---- Overlay ----------------------------------------------------------------

function showOverlay(): HTMLElement {
	const overlay = document.createElement( 'div' );
	overlay.id        = 'pdfdraft-generating-overlay';
	overlay.className = 'PDFDraft-Generating-Overlay';
	overlay.setAttribute( 'role', 'status' );
	overlay.setAttribute( 'aria-live', 'polite' );
	overlay.innerHTML = `
		<div class="PDFDraft-Generating-Overlay__Inner">
			<svg class="PDFDraft-Generating-Overlay__Spinner" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
				<path d="M21 12a9 9 0 11-6.219-8.56"/>
			</svg>
			<p class="PDFDraft-Generating-Overlay__Message">Generating your invoice&hellip;</p>
			<p class="PDFDraft-Generating-Overlay__Sub">Please wait and do not close this page.</p>
		</div>
	`;
	document.body.appendChild( overlay );
	return overlay;
}

function hideOverlay( overlay: HTMLElement ): void {
	overlay.remove();
}

// ---- beforeunload guard -----------------------------------------------------

function beforeUnloadHandler( e: BeforeUnloadEvent ): string {
	const msg = 'Your invoice is being generated. If you leave now it may not be attached to your order.';
	e.preventDefault();
	e.returnValue = msg;
	return msg;
}

function addBeforeUnloadGuard(): void {
	window.addEventListener( 'beforeunload', beforeUnloadHandler );
}

function removeBeforeUnloadGuard(): void {
	window.removeEventListener( 'beforeunload', beforeUnloadHandler );
}

// ---- API calls --------------------------------------------------------------

async function fetchContext( cfg: OrderReceivedConfig ) {
	const { restUrl, nonce, orderId, orderKey } = cfg;
	const res = await fetch(
		`${ restUrl }/orders/${ orderId }/invoice-context/checkout?order_key=${ encodeURIComponent( orderKey ) }`,
		{ credentials: 'include', headers: { 'X-WP-Nonce': nonce } },
	);
	if ( ! res.ok ) {
		throw new Error( `Context fetch failed: ${ res.status }` );
	}
	return res.json() as Promise<{
		designSlug: string;
		mergeTags: Record<string, unknown>;
		emailPending: boolean;
		isGenerated: boolean;
		uploadToken: string;
	}>;
}

async function uploadPdf( cfg: OrderReceivedConfig, blob: Blob, uploadToken: string ): Promise<void> {
	const { restUrl, nonce, orderId, orderKey } = cfg;
	const bytes = new Uint8Array( await blob.arrayBuffer() );
	let binary = '';
	for ( let i = 0; i < bytes.length; i++ ) binary += String.fromCharCode( bytes[ i ]! );

	const res = await fetch( `${ restUrl }/orders/${ orderId }/invoice/checkout`, {
		method:      'POST',
		credentials: 'include',
		headers:     { 'X-WP-Nonce': nonce, 'Content-Type': 'application/json' },
		body:        JSON.stringify( { pdf: btoa( binary ), order_key: orderKey, upload_token: uploadToken } ),
	} );
	if ( ! res.ok ) {
		throw new Error( `Upload failed: ${ res.status }` );
	}
}

async function sendEmail( cfg: OrderReceivedConfig ): Promise<void> {
	const { restUrl, nonce, orderId, orderKey } = cfg;
	const res = await fetch( `${ restUrl }/orders/${ orderId }/send-invoice-email`, {
		method:      'POST',
		credentials: 'include',
		headers:     { 'X-WP-Nonce': nonce, 'Content-Type': 'application/json' },
		body:        JSON.stringify( { order_key: orderKey } ),
	} );
	if ( ! res.ok ) {
		throw new Error( `Send email failed: ${ res.status }` );
	}
}

// ---- Main -------------------------------------------------------------------

async function run(): Promise<void> {
	const cfg = getConfig();
	if ( ! cfg ) return;

	let ctx: Awaited<ReturnType<typeof fetchContext>>;
	try {
		ctx = await fetchContext( cfg );
	} catch {
		return;
	}

	if ( ! ctx.emailPending || ! ctx.designSlug || ctx.isGenerated || ! ctx.uploadToken ) return;

	// Generation is needed — lock the page.
	const overlay = showOverlay();
	addBeforeUnloadGuard();

	const designEndpoint = `${ cfg.restUrl }/orders/${ cfg.orderId }/invoice-design?order_key=${ encodeURIComponent( cfg.orderKey ) }`;

	try {
		const { blob } = await exportInvoicePdfFromSlug(
			ctx.designSlug,
			ctx.mergeTags,
			cfg.orderId,
			cfg.nonce,
			designEndpoint,
		);
		await uploadPdf( cfg, blob, ctx.uploadToken );
		await sendEmail( cfg );
	} catch {
		// generation or upload failed — cron fallback will send email without PDF
	} finally {
		removeBeforeUnloadGuard();
		hideOverlay( overlay );
	}
}

run();
