/**
 * Connect Wizard: paste a URL → see your data → put it on a page.
 * Buildless (no JSX); talks to /datastream/v1/detect and /wizard-create.
 */
( function ( wp ) {
	'use strict';

	const root = document.getElementById( 'datastream-wizard' );

	if ( ! root || ! wp || ! wp.apiFetch ) {
		return;
	}

	const apiFetch = wp.apiFetch;
	const S = JSON.parse( root.getAttribute( 'data-strings' ) || '{}' );
	const SAMPLES = JSON.parse( root.getAttribute( 'data-samples' ) || '[]' );

	const state = {
		url: '',
		key: '',
		detection: null,
		selected: [], // field specs like "title" or "image:image"
		template: 'list',
		startedAt: 0,
	};

	function el( tag, attrs, children ) {
		const node = document.createElement( tag );
		Object.keys( attrs || {} ).forEach( function ( name ) {
			if ( 'text' === name ) {
				node.textContent = attrs[ name ];
			} else if ( 'class' === name ) {
				node.className = attrs[ name ];
			} else if ( 0 === name.indexOf( 'on' ) ) {
				node.addEventListener( name.slice( 2 ), attrs[ name ] );
			} else {
				node.setAttribute( name, attrs[ name ] );
			}
		} );
		( children || [] ).forEach( function ( child ) {
			if ( child ) {
				node.appendChild( child );
			}
		} );
		return node;
	}

	function sprintf1( format ) {
		const args = Array.prototype.slice.call( arguments, 1 );
		let i = 0;
		return format.replace( /%\d?\$?[ds]/g, function () {
			return String( args[ i++ ] );
		} );
	}

	function clear() {
		root.innerHTML = '';
	}

	function stepsIndicator( current ) {
		const list = el( 'ol', { class: 'ds-wizard-steps', 'aria-label': 'Progress' } );
		[ S.stepConnect || 'Connect', S.stepChoose || 'Choose', S.stepPlace || 'Place' ].forEach( function ( name, index ) {
			const item = el( 'li', { text: ( index + 1 ) + '. ' + name } );
			if ( index + 1 === current ) {
				item.className = 'is-current';
				item.setAttribute( 'aria-current', 'step' );
			} else if ( index + 1 < current ) {
				item.className = 'is-done';
			}
			list.appendChild( item );
		} );
		return list;
	}

	function focusHeading() {
		const heading = root.querySelector( 'h2' );
		if ( heading ) {
			heading.setAttribute( 'tabindex', '-1' );
			heading.focus();
		}
	}

	function friendlyStatus( status, fallback ) {
		const map = {
			404: S.err404 || 'The address answered with "not found" — check it for typos.',
			401: S.err401 || 'The API wants a key before it will answer.',
			403: S.err403 || 'The API refused — it may need a key, or it blocks servers.',
			429: S.err429 || 'The API says "slow down" — wait a minute and try again.',
			500: S.err500 || 'The API had an internal problem — try again; some APIs are slow to wake up.',
			503: S.err500 || 'The API had an internal problem — try again; some APIs are slow to wake up.',
		};
		return map[ status ] || fallback || ( S.failed || 'That did not work.' );
	}

	// ---------------------------------------------------------------- Step 1

	function stepUrl( errorMessage, needsKey ) {
		clear();
		state.detection = null;

		const input = el( 'input', {
			type: 'url',
			class: 'large-text',
			placeholder: 'https://api.example.com/things',
			value: state.url,
			style: 'font-size:1.2em;padding:.5em',
		} );

		const go = el( 'button', { type: 'button', class: 'button button-primary button-hero', text: S.go } );

		const form = el( 'div', { class: 'datastream-wizard-step' }, [
			stepsIndicator( 1 ),
			el( 'h2', { text: S.urlLabel } ),
			input,
			el( 'p', {}, [ go ] ),
		] );

		if ( errorMessage ) {
			form.appendChild( el( 'div', { class: 'ds-wizard-error', role: 'alert' }, [ el( 'p', { text: errorMessage } ) ] ) );
		}

		let keyInput = null;

		if ( needsKey ) {
			keyInput = el( 'input', { type: 'password', class: 'regular-text', placeholder: 'paste-your-api-key', value: state.key, 'aria-label': S.needsKey } );
			form.appendChild( el( 'div', { class: 'ds-wizard-keypanel' }, [
				el( 'p', { text: S.needsKey } ),
				keyInput,
				el( 'button', {
					type: 'button',
					class: 'button',
					style: 'margin-left:.5em',
					text: S.keyGo,
					onclick: function () {
						state.key = keyInput.value.trim();
						detect();
					},
				} ),
			] ) );
		}

		const gallery = el( 'p', {}, [ el( 'span', { class: 'description', text: S.tryFun + ' ' } ) ] );
		SAMPLES.forEach( function ( sample ) {
			gallery.appendChild( el( 'button', {
				type: 'button',
				class: 'button button-small',
				style: 'margin:0 4px 4px 0',
				text: sample.label,
				onclick: function () {
					state.url = sample.url;
					state.key = '';
					input.value = sample.url;
					detect();
				},
			} ) );
		} );
		form.appendChild( gallery );

		// Recipes: famous setups that only need one piece of information.
		const recipes = el( 'p', {}, [ el( 'span', { class: 'description', text: 'Popular setups: ' } ) ] );
		[
			{
				label: 'Another WordPress site',
				ask: 'Site address (e.g. example.com):',
				build: function ( answer ) {
					const host = answer.replace( /^https?:\/\//, '' ).replace( /\/.*$/, '' );
					return 'https://' + host + '/wp-json/wp/v2/posts?per_page=10';
				},
			},
			{
				label: 'GitHub releases',
				ask: 'Repository (owner/repo):',
				build: function ( answer ) {
					return 'https://api.github.com/repos/' + answer.trim() + '/releases';
				},
			},
		].forEach( function ( recipe ) {
			recipes.appendChild( el( 'button', {
				type: 'button',
				class: 'button button-small',
				style: 'margin:0 4px 4px 0',
				text: recipe.label,
				onclick: function () {
					const answer = window.prompt( recipe.ask );
					if ( answer ) {
						state.url = recipe.build( answer );
						state.key = '';
						input.value = state.url;
						detect();
					}
				},
			} ) );
		} );
		form.appendChild( recipes );

		go.addEventListener( 'click', function () {
			state.url = input.value.trim();
			state.key = '';
			if ( state.url ) {
				detect();
			}
		} );
		input.addEventListener( 'keydown', function ( event ) {
			if ( 'Enter' === event.key ) {
				go.click();
			}
		} );

		root.appendChild( form );

		if ( errorMessage || needsKey ) {
			focusHeading();
		}
		input.focus();
	}

	function detect() {
		if ( ! state.startedAt ) {
			state.startedAt = Date.now();
		}

		clear();
		root.appendChild( el( 'p', { class: 'description', text: S.fetching, 'aria-live': 'polite' } ) );

		apiFetch( {
			path: '/datastream/v1/detect',
			method: 'POST',
			data: { url: state.url, key: state.key },
		} ).then( function ( d ) {
			if ( ! d.success ) {
				stepUrl( d.needs_auth ? '' : friendlyStatus( d.status, d.message ), !! d.needs_auth );
				return;
			}
			state.detection = d;
			state.selected = ( d.suggested_fields || [] ).slice();
			stepFields();
		} ).catch( function ( error ) {
			stepUrl( friendlyStatus( 0, error && error.message ), false );
		} );
	}

	// ---------------------------------------------------------------- Step 2

	function specPath( spec ) {
		return spec.split( ':' )[ 0 ];
	}

	function stepFields() {
		clear();
		const d = state.detection;

		const headline = d.single_object
			? sprintf1( S.single, Object.keys( d.fields ).length )
			: sprintf1( S.found, d.item_count, Object.keys( d.fields ).length );

		const heading = el( 'h2', {} );
		heading.appendChild( el( 'span', { class: 'ds-wizard-count', text: headline } ) );

		const step = el( 'div', { class: 'datastream-wizard-step' }, [
			stepsIndicator( 2 ),
			heading,
		] );

		( d.evidence || [] ).forEach( function ( sentence, index ) {
			const line = el( 'p', { class: 'ds-wizard-evidence', text: sentence } );
			line.style.animationDelay = ( 0.15 * ( index + 1 ) ) + 's';
			step.appendChild( line );
		} );

		step.appendChild( el( 'h3', { text: S.pickFields } ) );

		const chips = el( 'p', {} );
		Object.keys( d.fields ).forEach( function ( path ) {
			const type = d.fields[ path ].type;
			const spec = ( 'image' === type || 'url' === type || 'date' === type || 'number' === type || 'bool' === type ) ? path + ':' + type : path;
			const isOn = function () {
				return state.selected.some( function ( s ) {
					return specPath( s ) === path;
				} );
			};
			const chip = el( 'button', {
				type: 'button',
				class: 'button button-small' + ( isOn() ? ' button-primary' : '' ),
				style: 'margin:0 4px 4px 0',
				text: path + ' · ' + type,
				onclick: function () {
					if ( isOn() ) {
						state.selected = state.selected.filter( function ( s ) {
							return specPath( s ) !== path;
						} );
						chip.classList.remove( 'button-primary' );
					} else {
						state.selected.push( spec );
						chip.classList.add( 'button-primary' );
					}
					renderPreview();
				},
			} );
			chips.appendChild( chip );
		} );
		step.appendChild( chips );

		step.appendChild( el( 'h3', { text: S.template } ) );
		const select = el( 'select', {} );
		[ 'list', 'table', 'cards', 'grid' ].forEach( function ( t ) {
			const option = el( 'option', { value: t, text: t } );
			if ( t === state.template ) {
				option.setAttribute( 'selected', 'selected' );
			}
			select.appendChild( option );
		} );
		select.addEventListener( 'change', function () {
			state.template = select.value;
			renderPreview();
		} );
		step.appendChild( el( 'p', {}, [ select ] ) );

		step.appendChild( el( 'h3', { text: S.preview } ) );
		const preview = el( 'div', { id: 'ds-wizard-preview', class: 'ds-wizard-preview' } );
		step.appendChild( preview );

		step.appendChild( el( 'p', {}, [
			el( 'button', { type: 'button', class: 'button', text: S.back, onclick: function () {
				stepUrl( '', false );
			} } ),
			el( 'button', { type: 'button', class: 'button button-primary', style: 'margin-left:.5em', text: S.next, onclick: stepName } ),
		] ) );

		root.appendChild( step );
		renderPreview();
		focusHeading();
	}

	function pluck( data, path ) {
		let current = data;
		const segments = path.split( '.' );
		for ( let i = 0; i < segments.length; i++ ) {
			if ( null === current || 'object' !== typeof current || ! ( segments[ i ] in current ) ) {
				return null;
			}
			current = current[ segments[ i ] ];
		}
		return current;
	}

	function valueNode( item, spec ) {
		const path = specPath( spec );
		const format = spec.indexOf( ':' ) > -1 ? spec.split( ':' ).pop() : 'text';
		const value = pluck( item, path );

		if ( null === value || undefined === value ) {
			return document.createTextNode( '' );
		}

		if ( 'image' === format && /^https?:\/\//.test( String( value ) ) ) {
			return el( 'img', { src: String( value ), style: 'max-width:80px;height:auto', alt: path } );
		}

		if ( 'object' === typeof value ) {
			return document.createTextNode( JSON.stringify( value ) );
		}

		return document.createTextNode( String( value ) );
	}

	function renderPreview() {
		const preview = document.getElementById( 'ds-wizard-preview' );
		if ( ! preview ) {
			return;
		}
		preview.innerHTML = '';
		const items = ( state.detection.samples || [] ).slice( 0, 3 );

		if ( 'table' === state.template ) {
			const table = el( 'table', { class: 'widefat striped' } );
			const head = el( 'tr', {} );
			state.selected.forEach( function ( spec ) {
				head.appendChild( el( 'th', { text: specPath( spec ) } ) );
			} );
			table.appendChild( head );
			items.forEach( function ( item ) {
				const row = el( 'tr', {} );
				state.selected.forEach( function ( spec ) {
					const cell = el( 'td', {} );
					cell.appendChild( valueNode( item, spec ) );
					row.appendChild( cell );
				} );
				table.appendChild( row );
			} );
			preview.appendChild( table );
			return;
		}

		// list / cards / grid preview: title + meta lines per item.
		items.forEach( function ( item ) {
			const box = el( 'div', { style: 'cards' === state.template || 'grid' === state.template ? 'display:inline-block;vertical-align:top;border:1px solid #dcdcde;border-radius:4px;padding:.75em;margin:0 .5em .5em 0;max-width:220px' : 'padding:.4em 0;border-bottom:1px solid #eee' } );
			state.selected.forEach( function ( spec, index ) {
				const line = el( 'div', { style: 0 === index ? 'font-weight:600' : 'font-size:.9em;opacity:.85' } );
				line.appendChild( valueNode( item, spec ) );
				box.appendChild( line );
			} );
			preview.appendChild( box );
		} );
	}

	// ---------------------------------------------------------------- Step 3

	function suggestId() {
		try {
			const host = new URL( state.url ).hostname.replace( /^www\.|^api\./, '' );
			return host.split( '.' )[ 0 ].replace( /[^a-z0-9_]/gi, '_' ).toLowerCase();
		} catch ( e ) {
			return 'my_api';
		}
	}

	function stepName() {
		clear();
		const d = state.detection;
		const idInput = el( 'input', { type: 'text', class: 'regular-text', value: suggestId() } );
		const pageCheck = el( 'input', { type: 'checkbox', checked: 'checked' } );
		const createBtn = el( 'button', { type: 'button', class: 'button button-primary button-hero', text: S.create } );

		const step = el( 'div', { class: 'datastream-wizard-step' }, [
			stepsIndicator( 3 ),
			el( 'h2', { text: S.nameIt } ),
			el( 'p', {}, [ idInput ] ),
			el( 'p', {}, [ el( 'label', {}, [ pageCheck, document.createTextNode( ' ' + S.createPage ) ] ) ] ),
			el( 'p', {}, [
				el( 'button', { type: 'button', class: 'button', text: S.back, onclick: stepFields } ),
				createBtn,
			] ),
		] );

		createBtn.style.marginLeft = '.5em';
		createBtn.addEventListener( 'click', function () {
			createBtn.disabled = true;
			createBtn.textContent = S.creating;

			const stream = {
				id: idInput.value.trim().toLowerCase().replace( /[^a-z0-9_-]/g, '_' ) || suggestId(),
				label: idInput.value.trim(),
				enabled: 1,
				api_url: state.url,
				format: d.format || 'auto',
				json_items_path: d.items_path || '',
				id_field: d.id_field || 'id',
				id_source: d.id_source || 'field',
				pagination: ( d.pagination && d.pagination.mode ) || 'none',
				page_param: ( d.pagination && d.pagination.page_param ) || 'page',
				per_page_param: ( d.pagination && d.pagination.per_page_param ) || '',
				max_pages: d.pagination && 'none' !== d.pagination.mode ? 5 : 1,
			};

			Object.keys( d.auth_patch || {} ).forEach( function ( key ) {
				stream[ key ] = d.auth_patch[ key ];
			} );

			apiFetch( {
				path: '/datastream/v1/wizard-create',
				method: 'POST',
				data: {
					stream: stream,
					fields: state.selected.join( ',' ),
					template: state.template,
					create_page: pageCheck.checked ? 1 : 0,
				},
			} ).then( stepDone ).catch( function ( error ) {
				createBtn.disabled = false;
				createBtn.textContent = S.create;
				step.appendChild( el( 'div', { class: 'ds-wizard-error', role: 'alert' }, [
					el( 'p', { text: ( error && error.message ) || S.failed } ),
				] ) );
			} );
		} );

		root.appendChild( step );
		focusHeading();
	}

	function stepDone( result ) {
		clear();
		const seconds = Math.round( ( Date.now() - state.startedAt ) / 1000 );

		const step = el( 'div', { class: 'datastream-wizard-step ds-wizard-success' }, [
			stepsIndicator( 4 ),
			el( 'div', { class: 'ds-wizard-check', 'aria-hidden': 'true', text: '✓' } ),
			el( 'h2', { text: S.doneTitle } ),
			el( 'p', { text: sprintf1( S.doneBody, result.processed, seconds ) } ),
			el( 'p', {}, [ el( 'code', { text: result.shortcode } ) ] ),
		] );

		const actions = el( 'p', {} );

		if ( result.page_edit ) {
			const link = el( 'a', { class: 'button button-primary', href: result.page_edit, text: S.editPage } );
			actions.appendChild( link );
		}

		const copy = el( 'button', { type: 'button', class: 'button', style: 'margin-left:.5em', text: S.copyCode } );
		copy.addEventListener( 'click', function () {
			if ( navigator.clipboard ) {
				navigator.clipboard.writeText( result.shortcode );
			}
			copy.textContent = S.copied;
		} );
		actions.appendChild( copy );

		step.appendChild( actions );
		root.appendChild( step );
		focusHeading();
	}

	stepUrl( '', false );
} )( window.wp );
