/**
 * Remap4me widget. Compiled in-browser by @babel/standalone (presets:
 * react, typescript) - see includes/class-remap4me-shortcode.php. No
 * bundler: this is a single global script, not an ES module.
 */

interface Remap4meConfig {
	clientId: string;
	type: string;
	stage: string;
	lang: string;
	theme: 'light' | 'dark';
	radius: boolean;
	accent_color: string;
}

interface Brand {
	id: number;
	name: string;
	active?: number;
}

interface Model {
	id: number;
	brand_id: number;
	namemodel: string;
	active?: number;
}

interface Generation {
	id: number;
	model_id: number;
	namefueltype: string;
	active?: number;
}

interface EngineVariant {
	id: number;
	model_id: number;
	fueltype_id: number;
	namevariant: string;
	active?: number;
}

interface FilterResponse {
	brands: Brand[];
	models: Model[];
	fueltypes: Generation[];
	variants: EngineVariant[];
}

interface DetailsResponse {
	id: number;
	namevariant: string;
	ecubrand: string;
	ecuversion: string;
	fuel: string;
	car_image: string;
	currency: number | string;
	dynoprint: number | string;
	oridinalpower: number;
	oridinaltorque: number;
	[ key: string ]: unknown;
}

( function () {
	'use strict';

	var React = ( window as any ).React;
	var ReactDOM = ( window as any ).ReactDOM;
	var I18N = ( window as any ).Remap4meI18n || {};

	var useState = React.useState;
	var useEffect = React.useEffect;
	var useCallback = React.useCallback;
	var createElement = React.createElement;

	var API_BASE = 'https://remap4.me/api/';
	// details-new.php sends no CORS headers, so it can't be fetched
	// directly from a third-party site's browser context. Routed through
	// our own REST proxy instead - see class-remap4me-rest.php.
	var restConfig = ( window as any ).Remap4meRestConfig || {};
	var DETAILS_URL = restConfig.detailsUrl || '/wp-json/remap4me/v1/details';

	var OPTION_KEYS = [
		'AutotunerOBD', 'AutotunerBench', 'AutotunerBootmode',
		'DPFOFF', 'EGROFF', 'GPFOFF', 'O2OFF', 'SCRADBLUEOFF',
		'SPEEDLIMITOFF', 'STARTSTOPOFF', 'POPBANGS', 'POPCORN', 'Powergate'
	];

	function translate( lang: string, key: string ): string {
		var dict = I18N[ lang ] || I18N.en || {};
		var fallback = I18N.en || {};
		return dict[ key ] || fallback[ key ] || key;
	}

	function isActive( item: { active?: number } ): boolean {
		return item.active === undefined || item.active === null || Number( item.active ) === 1;
	}

	function fetchFilters( clientId: string, brandId: number, modelId: number, fueltypeId: number ): Promise<FilterResponse> {
		var params = new URLSearchParams( {
			client_id: clientId,
			brand_id: String( brandId ),
			model_id: String( modelId ),
			fueltype_id: String( fueltypeId )
		} );
		var url = API_BASE + '?' + params.toString();

		return fetch( url ).then( function ( res ) {
			if ( ! res.ok ) {
				throw new Error( 'Request failed: ' + res.status );
			}
			return res.json();
		} );
	}

	function fetchDetails( clientId: string, id: number ): Promise<DetailsResponse> {
		var params = new URLSearchParams( { client_id: clientId, id: String( id ) } );
		var url = DETAILS_URL + '?' + params.toString();

		return fetch( url ).then( function ( res ) {
			if ( ! res.ok ) {
				throw new Error( 'Request failed: ' + res.status );
			}
			return res.json();
		} ).then( function ( data ) {
			return Array.isArray( data ) ? data[ 0 ] : data;
		} );
	}

	function Select( props: {
		id: string;
		label: string;
		value: string;
		disabled: boolean;
		placeholder: string;
		options: Array<{ id: number; name: string }>;
		onChange: ( value: string ) => void;
	} ) {
		return createElement(
			'div',
			{ className: 'remap4me-field' },
			createElement( 'label', { htmlFor: props.id }, props.label ),
			createElement(
				'select',
				{
					id: props.id,
					className: 'remap4me-select',
					value: props.value,
					disabled: props.disabled,
					onChange: function ( e: any ) {
						props.onChange( e.target.value );
					}
				},
				createElement( 'option', { value: '' }, props.placeholder ),
				props.options.map( function ( opt ) {
					return createElement( 'option', { key: opt.id, value: String( opt.id ) }, opt.name );
				} )
			)
		);
	}

	function StatTile( props: { label: string; value: string; delta?: string; highlight?: boolean } ) {
		return createElement(
			'div',
			{ className: 'remap4me-stat' + ( props.highlight ? ' remap4me-stat--highlight' : '' ) },
			createElement( 'div', { className: 'remap4me-stat-label' }, props.label ),
			createElement(
				'div',
				{ className: 'remap4me-stat-value' },
				props.value,
				props.delta ? createElement( 'span', { className: 'remap4me-stat-delta' }, props.delta ) : null
			)
		);
	}

	function ResultsPanel( props: { lang: string; stage: string; details: DetailsResponse } ) {
		var t = function ( key: string ) {
			return translate( props.lang, key );
		};
		var details = props.details;
		var stageKey = props.stage || '1';
		var powerKey = 'modificationpower' + ( stageKey === 'eco' ? '_eco' : stageKey );
		var torqueKey = 'modificationtorque' + ( stageKey === 'eco' ? '_eco' : stageKey );
		var priceKey = 'modprice' + ( stageKey === 'eco' ? '_eco' : stageKey );

		var origPower = Number( details.oridinalpower ) || 0;
		var origTorque = Number( details.oridinaltorque ) || 0;
		var tunedPower = Number( details[ powerKey ] ) || 0;
		var tunedTorque = Number( details[ torqueKey ] ) || 0;
		var price = Number( details[ priceKey ] ) || 0;
		var currency = details.currency;

		var badges = OPTION_KEYS.filter( function ( key ) {
			return Number( details[ key ] ) === 1;
		} );

		var hasDyno = details.dynoprint !== undefined && details.dynoprint !== null && details.dynoprint !== 0 && details.dynoprint !== '0' && details.dynoprint !== '';

		return createElement(
			'div',
			{ className: 'remap4me-results' },
			details.car_image ? createElement( 'img', { className: 'remap4me-image', src: details.car_image, alt: details.namevariant || '' } ) : null,
			createElement(
				'div',
				{ className: 'remap4me-results-header' },
				createElement( 'span', { className: 'remap4me-results-title' }, t( 'results_title' ) ),
				details.namevariant ? createElement( 'span', null, '— ' + details.namevariant ) : null
			),
			createElement(
				'div',
				{ className: 'remap4me-meta' },
				details.ecubrand ? createElement( 'span', null, createElement( 'strong', null, t( 'ecubrand' ) + ': ' ), details.ecubrand ) : null,
				details.ecuversion ? createElement( 'span', null, createElement( 'strong', null, t( 'ecuversion' ) + ': ' ), details.ecuversion ) : null,
				details.fuel ? createElement( 'span', null, createElement( 'strong', null, t( 'fuel' ) + ': ' ), details.fuel ) : null
			),
			createElement(
				'div',
				{ className: 'remap4me-stats' },
				createElement( StatTile, { label: t( 'oridinalpower' ), value: origPower + ' ' + t( 'hp' ) } ),
				createElement( StatTile, { label: t( 'oridinaltorque' ), value: origTorque + ' ' + t( 'nm' ) } ),
				createElement( StatTile, {
					label: t( powerKey ) + ' (' + t( 'stage_label' ) + ' ' + stageKey + ')',
					value: ( tunedPower || origPower ) + ' ' + t( 'hp' ),
					delta: tunedPower && tunedPower > origPower ? '+' + ( tunedPower - origPower ) : undefined,
					highlight: true
				} ),
				createElement( StatTile, {
					label: t( torqueKey ) + ' (' + t( 'stage_label' ) + ' ' + stageKey + ')',
					value: ( tunedTorque || origTorque ) + ' ' + t( 'nm' ),
					delta: tunedTorque && tunedTorque > origTorque ? '+' + ( tunedTorque - origTorque ) : undefined,
					highlight: true
				} ),
				price > 0 ? createElement( StatTile, {
					label: t( priceKey ),
					value: price + ( typeof currency === 'string' && currency ? ' ' + currency : '' )
				} ) : null,
				hasDyno ? createElement( StatTile, { label: t( 'dynoprint' ), value: String( details.dynoprint ) } ) : null
			),
			badges.length
				? createElement(
					'div',
					null,
					createElement( 'div', { className: 'remap4me-stat-label', style: { marginBottom: '8px' } }, t( 'options_label' ) ),
					createElement(
						'div',
						{ className: 'remap4me-options' },
						badges.map( function ( key ) {
							return createElement( 'span', { key: key, className: 'remap4me-badge' }, t( key ) );
						} )
					)
				)
				: null
		);
	}

	function Widget( props: { config: Remap4meConfig } ) {
		var config = props.config;
		var lang = config.lang || 'en';
		var t = useCallback( function ( key: string ) {
			return translate( lang, key );
		}, [ lang ] );

		var brandState = useState( [] ) as [ Brand[], ( v: Brand[] ) => void ];
		var brands = brandState[ 0 ], setBrands = brandState[ 1 ];

		var modelState = useState( [] ) as [ Model[], ( v: Model[] ) => void ];
		var models = modelState[ 0 ], setModels = modelState[ 1 ];

		var genState = useState( [] ) as [ Generation[], ( v: Generation[] ) => void ];
		var generations = genState[ 0 ], setGenerations = genState[ 1 ];

		var engineState = useState( [] ) as [ EngineVariant[], ( v: EngineVariant[] ) => void ];
		var engines = engineState[ 0 ], setEngines = engineState[ 1 ];

		var brandIdState = useState( '' );
		var brandId = brandIdState[ 0 ], setBrandId = brandIdState[ 1 ];

		var modelIdState = useState( '' );
		var modelId = modelIdState[ 0 ], setModelId = modelIdState[ 1 ];

		var genIdState = useState( '' );
		var genId = genIdState[ 0 ], setGenId = genIdState[ 1 ];

		var engineIdState = useState( '' );
		var engineId = engineIdState[ 0 ], setEngineId = engineIdState[ 1 ];

		type LoadingStage = 'idle' | 'brands' | 'models' | 'generations' | 'engines' | 'details';
		var loadingState = useState( 'brands' ) as [ LoadingStage, ( v: LoadingStage ) => void ];
		var loading = loadingState[ 0 ], setLoading = loadingState[ 1 ];

		var errorState = useState( null ) as [ string | null, ( v: string | null ) => void ];
		var error = errorState[ 0 ], setError = errorState[ 1 ];

		var detailsState = useState( null ) as [ DetailsResponse | null, ( v: DetailsResponse | null ) => void ];
		var details = detailsState[ 0 ], setDetails = detailsState[ 1 ];

		useEffect( function () {
			var cancelled = false;
			setLoading( 'brands' );
			setError( null );

			fetchFilters( config.clientId, 0, 0, 0 )
				.then( function ( data ) {
					if ( cancelled ) return;
					setBrands( ( data.brands || [] ).filter( isActive ) );
					setLoading( 'idle' );
				} )
				.catch( function () {
					if ( cancelled ) return;
					setError( t( 'error' ) );
					setLoading( 'idle' );
				} );

			return function () {
				cancelled = true;
			};
			// eslint-disable-next-line
		}, [ config.clientId ] );

		var onBrandChange = useCallback( function ( value: string ) {
			setBrandId( value );
			setModelId( '' );
			setGenId( '' );
			setEngineId( '' );
			setModels( [] );
			setGenerations( [] );
			setEngines( [] );
			setDetails( null );
			setError( null );

			if ( ! value ) {
				return;
			}

			setLoading( 'models' );
			fetchFilters( config.clientId, Number( value ), 0, 0 )
				.then( function ( data ) {
					setModels( ( data.models || [] ).filter( isActive ) );
					setLoading( 'idle' );
				} )
				.catch( function () {
					setError( t( 'error' ) );
					setLoading( 'idle' );
				} );
		}, [ config.clientId, t ] );

		var onModelChange = useCallback( function ( value: string ) {
			setModelId( value );
			setGenId( '' );
			setEngineId( '' );
			setGenerations( [] );
			setEngines( [] );
			setDetails( null );
			setError( null );

			if ( ! value ) {
				return;
			}

			setLoading( 'generations' );
			fetchFilters( config.clientId, Number( brandId ), Number( value ), 0 )
				.then( function ( data ) {
					setGenerations( ( data.fueltypes || [] ).filter( isActive ) );
					setLoading( 'idle' );
				} )
				.catch( function () {
					setError( t( 'error' ) );
					setLoading( 'idle' );
				} );
		}, [ config.clientId, brandId, t ] );

		var onGenChange = useCallback( function ( value: string ) {
			setGenId( value );
			setEngineId( '' );
			setEngines( [] );
			setDetails( null );
			setError( null );

			if ( ! value ) {
				return;
			}

			setLoading( 'engines' );
			fetchFilters( config.clientId, Number( brandId ), Number( modelId ), Number( value ) )
				.then( function ( data ) {
					setEngines( ( data.variants || [] ).filter( isActive ) );
					setLoading( 'idle' );
				} )
				.catch( function () {
					setError( t( 'error' ) );
					setLoading( 'idle' );
				} );
		}, [ config.clientId, brandId, modelId, t ] );

		var onEngineChange = useCallback( function ( value: string ) {
			setEngineId( value );
			setDetails( null );
			setError( null );
		}, [] );

		var onFind = useCallback( function () {
			if ( ! engineId ) {
				return;
			}

			setLoading( 'details' );
			setError( null );

			fetchDetails( config.clientId, Number( engineId ) )
				.then( function ( data ) {
					if ( ! data ) {
						throw new Error( 'empty' );
					}
					setDetails( data );
					setLoading( 'idle' );
				} )
				.catch( function () {
					setError( t( 'error' ) );
					setLoading( 'idle' );
				} );
		}, [ config.clientId, engineId, t ] );

		var brandOptions = brands.map( function ( b ) { return { id: b.id, name: b.name }; } );
		var modelOptions = models.map( function ( m ) { return { id: m.id, name: m.namemodel }; } );
		var genOptions = generations.map( function ( g ) { return { id: g.id, name: g.namefueltype }; } );
		var engineOptions = engines.map( function ( e ) { return { id: e.id, name: e.namevariant }; } );

		var isBusy = loading !== 'idle';

		return createElement(
			'div',
			null,
			createElement(
				'div',
				{ className: 'remap4me-form' },
				createElement( Select, {
					id: 'remap4me-brand',
					label: t( 'brands' ),
					value: brandId,
					disabled: isBusy && loading === 'brands',
					placeholder: t( 'select_brand' ),
					options: brandOptions,
					onChange: onBrandChange
				} ),
				createElement( Select, {
					id: 'remap4me-model',
					label: t( 'models' ),
					value: modelId,
					disabled: ! brandId || ( isBusy && loading === 'models' ),
					placeholder: t( 'select_model' ),
					options: modelOptions,
					onChange: onModelChange
				} ),
				createElement( Select, {
					id: 'remap4me-generation',
					label: t( 'fuel_types' ),
					value: genId,
					disabled: ! modelId || ( isBusy && loading === 'generations' ),
					placeholder: t( 'select_generation' ),
					options: genOptions,
					onChange: onGenChange
				} ),
				createElement( Select, {
					id: 'remap4me-engine',
					label: t( 'variants' ),
					value: engineId,
					disabled: ! genId || ( isBusy && loading === 'engines' ),
					placeholder: t( 'select_engine' ),
					options: engineOptions,
					onChange: onEngineChange
				} ),
				createElement(
					'div',
					{ className: 'remap4me-field' },
					createElement(
						'label',
						{
							className: 'powered-by',
							onClick: onFind
						},
						'Powered by ',
						createElement(
							'a',
							{
								href:'https://www.remap4.me/',
							},
							'remap4.me'
						),
					),
					createElement(
						'button',
						{
							id: 'find-btn',
							type: 'button',
							className: 'remap4me-btn',
							disabled: ! engineId || isBusy,
							onClick: onFind
						},
						t( 'find' )
					)
				)
			),
			// loading === 'details' ? createElement( 'div', { className: 'remap4me-status' }, t( 'loading' ) ) : null,
			error ? createElement( 'div', { className: 'remap4me-status is-error' }, error ) : null,
			details ? createElement( ResultsPanel, { lang: lang, stage: config.stage, details: details } ) : null
		);
	}

	function parseConfig( el: Element ): Remap4meConfig | null {
		var raw = el.getAttribute( 'data-remap4me' );
		if ( ! raw ) {
			return null;
		}
		try {
			var parsed:Remap4meConfig = JSON.parse( raw );
			return {
				clientId: parsed.clientId,
				type: parsed.type || 'car',
				stage: parsed.stage || '1',
				lang: ( parsed.lang || 'en' ).toLowerCase(),
				theme: parsed.theme === 'dark' ? 'dark' : 'light',
				radius: parsed.radius !== false,
				accent_color: parsed.accent_color || ''
			};
		} catch ( e ) {
			return null;
		}
	}

	// Re-applies the appearance settings as CSS custom properties on the
	// widget root itself, so they still land even if a page builder strips
	// the inline style="" attribute the PHP shortcode also writes.
	function applyAppearance( el: HTMLElement, config: Remap4meConfig ) {
		if ( config.accent_color ) {
			el.style.setProperty( '--r4m-accent', config.accent_color );
		}
		if ( config.radius === false ) {
			el.style.setProperty( '--r4m-radius', '0' );
			el.style.setProperty( '--r4m-radius-sm', '0' );
		}
	}

	function mountAll() {
		var nodes = document.querySelectorAll( '.remap4me-widget[data-remap4me]:not([data-remap4me-mounted])' );

		nodes.forEach( function ( el ) {
			var config = parseConfig( el );
			if ( ! config || ! config.clientId ) {
				return;
			}

			el.setAttribute( 'data-remap4me-mounted', '1' );
			el.setAttribute( 'dir', ( I18N[ config.lang ] && I18N[ config.lang ].dir ) || 'ltr' );
			applyAppearance( el as HTMLElement, config );

			var root = ReactDOM.createRoot( el );
			root.render( createElement( Widget, { config: config } ) );
		} );
	}

	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', mountAll );
	} else {
		mountAll();
	}
} )();
