import type { WidgetConfig } from './types';

/**
 * Attribution client events (DESIGN decision #23).
 *
 * The plugin's un-delayable bootstrap owns the events contract and exposes
 * `window.aisthetixTrackEvent(eventName, extra)`. The widget emits
 * `aisthetix_tryon_completed` through that single code path so there is ONE
 * implementation of the /api/events POST (headers, idempotency, consent gate).
 *
 * If the bootstrap helper is somehow unavailable (e.g. the widget was loaded
 * without it), we fall back to a direct, fire-and-forget POST that mirrors the
 * bootstrap exactly. Analytics must NEVER break the try-on flow, so everything
 * here is wrapped and best-effort.
 */

declare global {
	interface Window {
		aisthetixTrackEvent?: (
			eventName: string,
			extra?: Record<string, unknown>
		) => void;
	}
}

function makeEventId(): string {
	try {
		if ( window.crypto && 'randomUUID' in window.crypto ) {
			return window.crypto.randomUUID();
		}
	} catch {
		/* fall through */
	}
	return `t${ Date.now().toString( 36 ) }${ Math.random().toString( 36 ).slice( 2, 10 ) }`;
}

/**
 * Emit a try-on completion event. `productId` is the only shaped field for the
 * try-on event (mirrors the Shopify pixel: try-on -> productId only).
 */
export function trackTryOnCompleted( config: WidgetConfig, productId: string ): void {
	try {
		const extra = { productId: productId ? String( productId ) : null };

		if ( typeof window.aisthetixTrackEvent === 'function' ) {
			window.aisthetixTrackEvent( 'aisthetix_tryon_completed', extra );
			return;
		}

		// Fallback: direct POST identical in shape to the bootstrap's sendEvent.
		if ( ! config.analyticsEnabled || ! config.eventsUrl || ! config.publishableKey ) {
			return;
		}
		const payload = {
			eventName: 'aisthetix_tryon_completed',
			eventId: makeEventId(),
			visitorKey: config.visitorKey || null,
			customerId: config.customerId || null,
			url: window.location?.href || null,
			referrer: document.referrer || null,
			...extra,
		};
		fetch( config.eventsUrl, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				'X-Aisthetix-Key': config.publishableKey,
			},
			body: JSON.stringify( payload ),
			keepalive: true,
			credentials: 'omit',
		} ).catch( () => {} );
	} catch {
		/* analytics must never break the try-on */
	}
}

/**
 * Emit the Find My Size attribution anchor. Product analytics is still emitted
 * separately through the stricter CMP-gated envelope, so this event can never
 * duplicate the PostHog completion event.
 */
export function trackSizeCompleted(
	config: WidgetConfig,
	productId: string,
	variantId?: string | null
): void {
	try {
		const extra = {
			productId: productId ? String( productId ) : null,
			variantId: variantId ? String( variantId ) : null,
		};
		if ( typeof window.aisthetixTrackEvent === 'function' ) {
			window.aisthetixTrackEvent( 'aisthetix_size_completed', extra );
			return;
		}
		// Without the bootstrap there is no CMP reader, so fail closed unless the
		// merchant's explicit first-party attribution setting is enabled.
		if ( ! config.analyticsEnabled || ! config.eventsUrl || ! config.publishableKey ) return;
		fetch( config.eventsUrl, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				'X-Aisthetix-Key': config.publishableKey,
			},
			body: JSON.stringify( {
				eventName: 'aisthetix_size_completed',
				eventId: makeEventId(),
				visitorKey: config.visitorKey || null,
				customerId: config.customerId || null,
				url: window.location?.href || null,
				referrer: document.referrer || null,
				...extra,
			} ),
			keepalive: true,
			credentials: 'omit',
		} ).catch( () => {} );
	} catch {
		/* attribution must never break sizing */
	}
}
