/**
 * Leadlotse Formular-Builder (Etappe 4b).
 *
 * No-Build-React (globale wp.*-Objekte, D13). Zwei Ansichten: Zweck-Galerie
 * (neues Formular aus einer der 8 Vorlagen) und der Builder mit drei Bereichen
 * (Feldliste, Live-Vorschau, Einstellungen), UX-KONZEPT Screen "Builder".
 * Spricht ausschliesslich die REST-API leadlotse/v1/forms (D8).
 *
 * Feld-Umsortierung ueber Hoch/Runter-Knoepfe statt Drag-and-drop: das ist die
 * barrierefreie, tastaturbediente Variante (UX-KONZEPT 7). Conditional Logic in
 * v1 als einzelne Regel je Feld ("zeigen/verbergen, wenn Feld X Operator Y");
 * die Datenstruktur erlaubt spaeter mehrere Regeln.
 */
( function ( wp ) {
	'use strict';

	var el = wp.element.createElement;
	var useState = wp.element.useState;
	var useEffect = wp.element.useEffect;
	var render = wp.element.render;
	var cfg = window.leadlotseBuilder || {};
	var i18n = cfg.i18n || {};
	var OPERATORS = [ 'equals', 'not_equals', 'contains', 'not_empty', 'empty' ];

	/**
	 * REST-Aufruf mit Nonce, liefert ein Promise mit geparstem JSON.
	 *
	 * @param {string} path   Pfad relativ zu restBase.
	 * @param {Object} [opts] fetch-Optionen.
	 * @return {Promise<Object>}
	 */
	function api( path, opts ) {
		opts = opts || {};
		opts.headers = opts.headers || {};
		opts.headers[ 'X-WP-Nonce' ] = cfg.nonce;
		opts.headers[ 'Content-Type' ] = 'application/json';
		opts.credentials = 'same-origin';
		return fetch( cfg.restBase + path, opts ).then( function ( res ) {
			return res.json().then( function ( body ) {
				if ( ! res.ok ) {
					throw new Error( ( body && body.message ) || 'Fehler' );
				}
				return body;
			} );
		} );
	}

	function t( key, fallback ) {
		return i18n[ key ] || fallback;
	}

	/**
	 * Feldtypen, die im Add-Menue angeboten werden.
	 *
	 * @return {Array<Object>}
	 */
	function addableTypes() {
		return ( cfg.fieldTypes || [] ).filter( function ( ft ) {
			return ft.addable;
		} );
	}

	function typeLabel( type ) {
		var found = ( cfg.fieldTypes || [] ).find( function ( ft ) {
			return ft.key === type;
		} );
		return found ? found.label : type;
	}

	/**
	 * Erzeugt eine eindeutige Feld-ID aus einem Typ.
	 *
	 * @param {string} type   Feldtyp.
	 * @param {Array}  fields Bestehende Felder.
	 * @return {string}
	 */
	function uniqueId( type, fields ) {
		var used = {};
		fields.forEach( function ( f ) {
			used[ f.id ] = true;
		} );
		var n = 1;
		var id = type + '_' + n;
		while ( used[ id ] ) {
			n++;
			id = type + '_' + n;
		}
		return id;
	}

	/**
	 * Zaehlt die im Frontend sichtbaren Felder (ohne hidden/honeypot).
	 *
	 * @param {Array} fields Felder.
	 * @return {number}
	 */
	function visibleCount( fields ) {
		return fields.filter( function ( f ) {
			return 'hidden' !== f.type && 'honeypot' !== f.type;
		} ).length;
	}

	// --- Pro-Schnitt (L-P1) ------------------------------------------------
	// Spiegelt Support\ProFeatures. Verbindlich ist der Server; hier geht es
	// nur darum, gesperrte Flaechen sichtbar aber verschlossen zu zeigen.

	/**
	 * Nutzt diese Definition die Pro-Funktion bereits?
	 *
	 * @param {Object} def     Formular-Definition.
	 * @param {string} feature event, whatsapp oder identity.
	 * @return {boolean}
	 */
	function featureUsed( def, feature ) {
		var s = ( def && def.settings ) || {};
		if ( 'event' === feature ) {
			return !! ( s.event && s.event.enabled );
		}
		if ( 'whatsapp' === feature ) {
			if ( s.whatsapp && s.whatsapp.enabled ) {
				return true;
			}
			return ( ( def && def.fields ) || [] ).some( function ( f ) {
				return !! f.whatsapp_optin;
			} );
		}
		// Ausfuellhilfe: Default an, nur ein ausdrueckliches false ist aus.
		return ! s.identity || false !== s.identity.enabled;
	}

	/**
	 * Gesperrt = ohne Lizenz und noch nicht in Benutzung (Bestandsschutz).
	 *
	 * @param {Object} def     Formular-Definition.
	 * @param {string} feature Funktionsschluessel.
	 * @return {boolean}
	 */
	function featureLocked( def, feature ) {
		return ! cfg.pro && ! featureUsed( def, feature );
	}

	/**
	 * Klartext-Begruendung je Funktion (dieselben Saetze wie serverseitig).
	 *
	 * @param {string} feature Funktionsschluessel.
	 * @return {string}
	 */
	function proMessage( feature ) {
		return ( cfg.proMessages || {} )[ feature ] || '';
	}

	/**
	 * Schloss-Schild. Traegt immer den Text "Pro" (Farbe nie allein). Mit
	 * Klick-Handler wird es der Knopf, der den Kauf-Moment oeffnet.
	 *
	 * @param {Function} [onClick] Handler.
	 * @return {Object}
	 */
	function lockBadge( onClick ) {
		var attrs = { className: 'hs-shield hs-shield--grey hs-shield--locked' };
		var icon = el( 'span', {
			className: 'dashicons dashicons-lock',
			'aria-hidden': 'true',
		} );
		if ( ! onClick ) {
			return el( 'span', attrs, icon, t( 'proBadge', 'Pro' ) );
		}
		attrs.type = 'button';
		attrs.onClick = onClick;
		return el( 'button', attrs, icon, t( 'proBadge', 'Pro' ) );
	}

	/**
	 * Der Kauf-Moment: eine Karte, ein Satz, Preis, ein Knopf. Kein Modal.
	 *
	 * @param {Object} props card, onDismiss.
	 * @return {Object}
	 */
	function ProCard( props ) {
		var card = props.card;
		return el(
			'div',
			{ className: 'hs-hans-card hs-hans-card--info hs-builder-pro-card' },
			el(
				'div',
				{ className: 'hs-hans-card__body' },
				el( 'p', { className: 'hs-hans-card__title' }, card.title ),
				el( 'p', { className: 'hs-hans-card__text' }, card.text + ' ' + card.price ),
				el(
					'a',
					{
						className: 'button button-primary hs-hans-card__action',
						href: card.url,
					},
					card.button
				)
			),
			el(
				'button',
				{
					type: 'button',
					className: 'hs-hans-card__dismiss',
					'aria-label': t( 'proDismiss', 'Hinweis schliessen' ),
					onClick: props.onDismiss,
				},
				el( 'span', { 'aria-hidden': 'true' }, '×' )
			)
		);
	}

	// --- Zweck-Galerie -----------------------------------------------------

	function Gallery( props ) {
		var lang = props.lang;
		var gallery = cfg.gallery || [];

		return el(
			'div',
			{ className: 'hs-builder-gallery' },
			el(
				'div',
				{ className: 'hs-builder-gallery-head' },
				el( 'h1', null, t( 'galleryTitle', 'Wofuer ist Ihr Formular?' ) ),
				el(
					'p',
					null,
					t(
						'galleryIntro',
						'Waehlen Sie einen Zweck. Sie bekommen ein fertiges Formular, das Sie anpassen koennen.'
					)
				),
				el( LangSwitch, { lang: lang, onChange: props.onLang } )
			),
			el(
				'div',
				{ className: 'hs-builder-cards' },
				gallery.map( function ( item ) {
					var name = 'en' === lang ? item.name_en : item.name;
					var desc = 'en' === lang ? item.description_en : item.description;
					// Gesperrte Vorlage bleibt sichtbar und klickbar: der Klick
					// zeigt den Kauf-Moment statt ein Formular anzulegen.
					var locked = item.pro && ! cfg.pro;
					return el(
						'button',
						{
							key: item.key,
							type: 'button',
							className:
								'hs-builder-card' +
								( locked ? ' hs-builder-card--locked' : '' ),
							// Grund steht auch am Knopf, falls der Kauf-Moment
							// schon weggeklickt wurde (er kommt nie wieder).
							title: locked ? proMessage( 'event' ) : null,
							disabled: props.busy,
							onClick: function () {
								if ( locked ) {
									props.onLocked();
									return;
								}
								props.onPick( item.key );
							},
						},
						el(
							'span',
							{ className: 'hs-builder-card-name' },
							name,
							locked ? ' ' : null,
							locked ? lockBadge() : null
						),
						el( 'span', { className: 'hs-builder-card-desc' }, desc )
					);
				} )
			),
			el(
				'p',
				null,
				el(
					'a',
					{ href: cfg.listUrl, className: 'button' },
					t( 'backToList', 'Zurueck zur Uebersicht' )
				)
			)
		);
	}

	function LangSwitch( props ) {
		return el(
			'div',
			{ className: 'hs-builder-lang' },
			[ 'de', 'en' ].map( function ( code ) {
				return el(
					'button',
					{
						key: code,
						type: 'button',
						className:
							'button' +
							( props.lang === code ? ' button-primary' : '' ),
						onClick: function () {
							props.onChange( code );
						},
					},
					code.toUpperCase()
				);
			} )
		);
	}

	// --- Builder -----------------------------------------------------------

	function Builder( props ) {
		var form = props.form;
		var def = form.definition;
		var fields = def.fields || [];
		var selected = props.selectedId;

		var selectedField = null;
		fields.forEach( function ( f ) {
			if ( f.id === selected ) {
				selectedField = f;
			}
		} );

		return el(
			'div',
			{ className: 'hs-builder' },
			el( BuilderHeader, props ),
			props.notice
				? el(
						'div',
						{
							className:
								'notice notice-' +
								( props.notice.type || 'info' ) +
								' hs-builder-notice',
						},
						el( 'p', null, props.notice.text )
				  )
				: null,
			el(
				'div',
				{ className: 'hs-builder-cols' },
				el( FieldColumn, props ),
				el(
					'div',
					{ className: 'hs-builder-preview' },
					el(
						'h2',
						{ className: 'hs-builder-col-title' },
						t( 'preview', 'Vorschau' )
					),
					el( Preview, { fields: fields } )
				),
				el(
					'div',
					{ className: 'hs-builder-settings' },
					selectedField
						? el( FieldSettings, {
								field: selectedField,
								fields: fields,
								onChange: props.onFieldChange,
						  } )
						: el( FormSettings, {
								definition: def,
								onChange: props.onSettingsChange,
								onLocked: props.onLocked,
						  } )
				)
			)
		);
	}

	function BuilderHeader( props ) {
		var form = props.form;
		return el(
			'div',
			{ className: 'hs-builder-header' },
			el(
				'div',
				{ className: 'hs-builder-title' },
				el( 'input', {
					type: 'text',
					value: form.title,
					'aria-label': t( 'formTitle', 'Formularname' ),
					onChange: function ( e ) {
						props.onTitle( e.target.value );
					},
				} ),
				el(
					'span',
					{ className: 'hs-builder-shortcode' },
					'[leadlotse id="' + form.id + '"]'
				)
			),
			el(
				'div',
				{ className: 'hs-builder-actions' },
				el(
					'label',
					{ className: 'hs-builder-status' },
					el( 'input', {
						type: 'checkbox',
						checked: 'publish' === form.status,
						onChange: function ( e ) {
							props.onStatus(
								e.target.checked ? 'publish' : 'draft'
							);
						},
					} ),
					' ' + t( 'published', 'Veroeffentlicht' )
				),
				el(
					'a',
					{ href: cfg.listUrl, className: 'button' },
					t( 'backToList', 'Zurueck zur Uebersicht' )
				),
				el(
					'button',
					{
						type: 'button',
						className: 'button button-primary',
						disabled: props.saving,
						onClick: props.onSave,
					},
					props.saving
						? t( 'saving', 'Speichern...' )
						: t( 'save', 'Speichern' )
				)
			)
		);
	}

	function FieldColumn( props ) {
		var fields = props.form.definition.fields || [];
		var editable = fields.filter( function ( f ) {
			return 'honeypot' !== f.type;
		} );
		var warn = visibleCount( fields ) >= 6;
		var hasConsent = fields.some( function ( f ) {
			return 'consent' === f.type;
		} );

		return el(
			'div',
			{ className: 'hs-builder-fields' },
			el(
				'h2',
				{ className: 'hs-builder-col-title' },
				t( 'fields', 'Felder' )
			),
			warn
				? el(
						'p',
						{ className: 'hs-builder-warn' },
						t(
							'fieldWarn',
							'Viele Pflichtfelder kosten Anfragen. Fragen Sie nur ab, was Sie wirklich brauchen.'
						)
				  )
				: null,
			el(
				'ul',
				{ className: 'hs-builder-fieldlist' },
				editable.map( function ( field, index ) {
					return el( FieldRow, {
						key: field.id,
						field: field,
						index: index,
						total: editable.length,
						selected: field.id === props.selectedId,
						onSelect: props.onSelect,
						onMove: props.onMove,
						onDelete: props.onDelete,
					} );
				} )
			),
			el( AddMenu, {
				onAdd: props.onAdd,
				hasConsent: hasConsent,
			} )
		);
	}

	function FieldRow( props ) {
		var f = props.field;
		var protectedField = 'consent' === f.type;
		var label =
			f.label ||
			( 'consent' === f.type
				? t( 'consentField', 'Einwilligung' )
				: 'hidden' === f.type
				? f.capture || t( 'hiddenField', 'Verstecktes Feld' )
				: typeLabel( f.type ) );

		return el(
			'li',
			{
				className:
					'hs-builder-fieldrow' +
					( props.selected ? ' is-selected' : '' ),
			},
			el(
				'button',
				{
					type: 'button',
					className: 'hs-builder-fieldrow-main',
					onClick: function () {
						props.onSelect( f.id );
					},
				},
				el( 'span', { className: 'hs-builder-field-label' }, label ),
				el(
					'span',
					{ className: 'hs-builder-field-type' },
					typeLabel( f.type ) + ( f.required ? ' *' : '' )
				)
			),
			el(
				'span',
				{ className: 'hs-builder-fieldrow-tools' },
				el(
					'button',
					{
						type: 'button',
						className: 'button-link',
						'aria-label': t( 'moveUp', 'Nach oben' ),
						disabled: 0 === props.index,
						onClick: function () {
							props.onMove( f.id, -1 );
						},
					},
					'↑'
				),
				el(
					'button',
					{
						type: 'button',
						className: 'button-link',
						'aria-label': t( 'moveDown', 'Nach unten' ),
						disabled: props.index === props.total - 1,
						onClick: function () {
							props.onMove( f.id, 1 );
						},
					},
					'↓'
				),
				protectedField
					? null
					: el(
							'button',
							{
								type: 'button',
								className: 'button-link hs-builder-delete',
								'aria-label': t( 'deleteField', 'Feld loeschen' ),
								onClick: function () {
									props.onDelete( f.id );
								},
							},
							'×'
					  )
			)
		);
	}

	function AddMenu( props ) {
		var types = addableTypes().filter( function ( ft ) {
			return 'consent' !== ft.key || ! props.hasConsent;
		} );
		return el(
			'div',
			{ className: 'hs-builder-add' },
			el(
				'span',
				{ className: 'hs-builder-add-label' },
				t( 'addField', 'Feld hinzufuegen' ) + ':'
			),
			types.map( function ( ft ) {
				return el(
					'button',
					{
						key: ft.key,
						type: 'button',
						className: 'button',
						onClick: function () {
							props.onAdd( ft.key );
						},
					},
					ft.label
				);
			} )
		);
	}

	// --- Live-Vorschau -----------------------------------------------------

	function Preview( props ) {
		var fields = props.fields.filter( function ( f ) {
			return 'hidden' !== f.type && 'honeypot' !== f.type;
		} );
		if ( 0 === fields.length ) {
			return el(
				'p',
				{ className: 'hs-builder-preview-empty' },
				t( 'previewEmpty', 'Fuegen Sie links Felder hinzu.' )
			);
		}
		return el(
			'form',
			{ className: 'leadlotse-form hs-builder-preview-form' },
			fields.map( function ( f ) {
				return el( PreviewField, { key: f.id, field: f } );
			} ),
			el(
				'button',
				{ type: 'button', className: 'leadlotse-submit', disabled: true },
				t( 'submit', 'Absenden' )
			)
		);
	}

	function PreviewField( props ) {
		var f = props.field;
		var labelText =
			( f.label || typeLabel( f.type ) ) + ( f.required ? ' *' : '' );

		if ( 'consent' === f.type ) {
			return el(
				'p',
				{ className: 'leadlotse-field leadlotse-field--consent' },
				el( 'label', null, el( 'input', { type: 'checkbox', disabled: true } ), ' ' + ( f.consent_text || t( 'consentField', 'Einwilligung' ) ) )
			);
		}

		var control;
		if ( 'textarea' === f.type ) {
			control = el( 'textarea', { rows: 3, disabled: true, placeholder: f.placeholder || '' } );
		} else if ( 'select' === f.type ) {
			if ( 'radio' === f.display ) {
				control = el(
					'span',
					{ className: 'leadlotse-radios' },
					( f.options || [] ).map( function ( o, i ) {
						return el(
							'label',
							{ key: i, className: 'leadlotse-radio' },
							el( 'input', { type: 'radio', disabled: true } ),
							' ' + o.label
						);
					} )
				);
			} else {
				control = el(
					'select',
					{ disabled: true },
					( f.options || [] ).map( function ( o, i ) {
						return el( 'option', { key: i }, o.label );
					} )
				);
			}
		} else if ( 'checkbox' === f.type ) {
			control = el( 'input', { type: 'checkbox', disabled: true } );
		} else {
			var inputType =
				'email' === f.type
					? 'email'
					: 'phone' === f.type
					? 'tel'
					: 'date' === f.type
					? 'date'
					: 'text';
			control = el( 'input', {
				type: inputType,
				disabled: true,
				placeholder: f.placeholder || '',
			} );
		}

		return el(
			'p',
			{ className: 'leadlotse-field' },
			el( 'label', null, labelText ),
			control,
			f.help ? el( 'span', { className: 'leadlotse-help' }, f.help ) : null
		);
	}

	// --- Einstellungen (rechte Spalte) -------------------------------------

	function textRow( label, value, onChange, opts ) {
		opts = opts || {};
		return el(
			'p',
			{ className: 'hs-builder-row' },
			el( 'label', null, label ),
			el( opts.textarea ? 'textarea' : 'input', {
				type: opts.textarea ? undefined : opts.type || 'text',
				rows: opts.textarea ? 3 : undefined,
				value: value || '',
				placeholder: opts.placeholder || undefined,
				onChange: function ( e ) {
					onChange( e.target.value );
				},
			} )
		);
	}

	function FieldSettings( props ) {
		var f = props.field;
		var isConsent = 'consent' === f.type;
		var isHidden = 'hidden' === f.type;

		function set( patch ) {
			props.onChange( f.id, patch );
		}

		var rows = [];
		rows.push(
			el(
				'h2',
				{ key: 'h', className: 'hs-builder-col-title' },
				t( 'fieldSettings', 'Feld-Einstellungen' )
			)
		);

		if ( isConsent ) {
			rows.push(
				el(
					'p',
					{ key: 'ci', className: 'hs-builder-hint' },
					t(
						'consentHint',
						'Das Einwilligungsfeld ist Pflicht und kann nicht entfernt werden. Sie koennen den Text anpassen.'
					)
				)
			);
			rows.push(
				textRow(
					t( 'consentText', 'Einwilligungstext' ),
					f.consent_text,
					function ( v ) {
						set( { consent_text: v } );
					},
					{ textarea: true }
				)
			);
			return el( 'div', null, rows );
		}

		if ( isHidden ) {
			rows.push(
				el(
					'p',
					{ key: 'hi', className: 'hs-builder-hint' },
					t(
						'hiddenHint',
						'Verstecktes Feld fuer die Attribution (zum Beispiel utm_source). Es ist fuer Besucher nicht sichtbar.'
					)
				)
			);
			rows.push(
				textRow( t( 'captureKey', 'Erfasster Parameter' ), f.capture, function ( v ) {
					set( { capture: v } );
				} )
			);
			return el( 'div', null, rows );
		}

		rows.push(
			textRow( t( 'label', 'Beschriftung' ), f.label, function ( v ) {
				set( { label: v } );
			} )
		);
		rows.push(
			el(
				'p',
				{ key: 'req', className: 'hs-builder-row' },
				el(
					'label',
					null,
					el( 'input', {
						type: 'checkbox',
						checked: !! f.required,
						onChange: function ( e ) {
							set( { required: e.target.checked } );
						},
					} ),
					' ' + t( 'required', 'Pflichtfeld' )
				)
			)
		);
		rows.push(
			textRow( t( 'help', 'Hilfetext' ), f.help, function ( v ) {
				set( { help: v } );
			} )
		);
		if ( 'select' !== f.type && 'checkbox' !== f.type && 'date' !== f.type ) {
			rows.push(
				textRow( t( 'placeholder', 'Platzhalter' ), f.placeholder, function ( v ) {
					set( { placeholder: v } );
				} )
			);
		}
		if ( 'select' === f.type ) {
			rows.push(
				el( OptionsEditor, {
					key: 'opts',
					field: f,
					onChange: set,
				} )
			);
		}

		if ( 'phone' === f.type ) {
			rows.push(
				el(
					'p',
					{ key: 'waopt', className: 'hs-builder-row' },
					el(
						'label',
						null,
						el( 'input', {
							type: 'checkbox',
							checked: !! f.whatsapp_optin,
							onChange: function ( e ) {
								set( { whatsapp_optin: e.target.checked } );
							},
						} ),
						' ' + t( 'whatsappOptin', 'WhatsApp-Opt-in anzeigen' )
					)
				)
			);
			if ( f.whatsapp_optin ) {
				rows.push(
					textRow(
						t( 'whatsappOptinText', 'Text des Opt-in' ),
						f.whatsapp_optin_text,
						function ( v ) {
							set( { whatsapp_optin_text: v } );
						}
					)
				);
			}
		}

		rows.push(
			el( ConditionEditor, {
				key: 'cond',
				field: f,
				fields: props.fields,
				onChange: set,
			} )
		);

		return el( 'div', null, rows );
	}

	function OptionsEditor( props ) {
		var f = props.field;
		var options = f.options || [];
		var text = options
			.map( function ( o ) {
				return o.label;
			} )
			.join( '\n' );

		return el(
			'div',
			{ className: 'hs-builder-row' },
			el( 'label', null, t( 'options', 'Optionen (eine pro Zeile)' ) ),
			el( 'textarea', {
				rows: 4,
				value: text,
				onChange: function ( e ) {
					var opts = e.target.value
						.split( '\n' )
						.map( function ( line ) {
							return line.trim();
						} )
						.filter( function ( line ) {
							return '' !== line;
						} )
						.map( function ( line ) {
							return { value: line, label: line };
						} );
					props.onChange( { options: opts } );
				},
			} ),
			el(
				'label',
				{ className: 'hs-builder-inline' },
				el( 'input', {
					type: 'checkbox',
					checked: 'radio' === f.display,
					onChange: function ( e ) {
						props.onChange( {
							display: e.target.checked ? 'radio' : 'dropdown',
						} );
					},
				} ),
				' ' + t( 'asRadio', 'Als Auswahlknoepfe anzeigen' )
			)
		);
	}

	function ConditionEditor( props ) {
		var f = props.field;
		var cond = f.conditions || { enabled: false, action: 'show', logic: 'and', rules: [] };
		var rule = ( cond.rules && cond.rules[ 0 ] ) || { field: '', operator: 'equals', value: '' };
		var others = props.fields.filter( function ( other ) {
			return (
				other.id !== f.id &&
				'hidden' !== other.type &&
				'honeypot' !== other.type &&
				'consent' !== other.type
			);
		} );

		function update( patch ) {
			var next = {
				enabled: cond.enabled,
				action: cond.action || 'show',
				logic: 'and',
				rules: [ Object.assign( {}, rule, patch.rule || {} ) ],
			};
			if ( undefined !== patch.enabled ) {
				next.enabled = patch.enabled;
			}
			if ( undefined !== patch.action ) {
				next.action = patch.action;
			}
			props.onChange( { conditions: next } );
		}

		var children = [
			el(
				'label',
				{ key: 'en', className: 'hs-builder-inline' },
				el( 'input', {
					type: 'checkbox',
					checked: !! cond.enabled,
					onChange: function ( e ) {
						update( { enabled: e.target.checked } );
					},
				} ),
				' ' + t( 'conditionEnable', 'Dieses Feld nur unter einer Bedingung zeigen' )
			),
		];

		if ( cond.enabled ) {
			if ( 0 === others.length ) {
				children.push(
					el(
						'p',
						{ key: 'no', className: 'hs-builder-hint' },
						t( 'conditionNoFields', 'Fuegen Sie zuerst weitere Felder hinzu.' )
					)
				);
			} else {
				children.push(
					el(
						'div',
						{ key: 'rule', className: 'hs-builder-condition' },
						el(
							'select',
							{
								value: cond.action || 'show',
								'aria-label': t( 'action', 'Aktion' ),
								onChange: function ( e ) {
									update( { action: e.target.value } );
								},
							},
							el( 'option', { value: 'show' }, t( 'show', 'Zeigen' ) ),
							el( 'option', { value: 'hide' }, t( 'hide', 'Verbergen' ) )
						),
						el(
							'select',
							{
								value: rule.field,
								'aria-label': t( 'field', 'Feld' ),
								onChange: function ( e ) {
									update( { rule: { field: e.target.value } } );
								},
							},
							el( 'option', { value: '' }, t( 'chooseField', 'Feld waehlen' ) ),
							others.map( function ( o ) {
								return el(
									'option',
									{ key: o.id, value: o.id },
									o.label || o.id
								);
							} )
						),
						el(
							'select',
							{
								value: rule.operator,
								'aria-label': t( 'operator', 'Bedingung' ),
								onChange: function ( e ) {
									update( { rule: { operator: e.target.value } } );
								},
							},
							OPERATORS.map( function ( op ) {
								return el(
									'option',
									{ key: op, value: op },
									t( 'op_' + op, op )
								);
							} )
						),
						'not_empty' !== rule.operator && 'empty' !== rule.operator
							? el( 'input', {
									type: 'text',
									value: rule.value,
									placeholder: t( 'value', 'Wert' ),
									'aria-label': t( 'value', 'Wert' ),
									onChange: function ( e ) {
										update( { rule: { value: e.target.value } } );
									},
							  } )
							: null
					)
				);
			}
		}

		return el(
			'div',
			{ className: 'hs-builder-row hs-builder-conditions' },
			el( 'label', null, t( 'conditions', 'Sichtbarkeit' ) ),
			children
		);
	}

	function WhatsAppSettings( props ) {
		var wa = props.whatsapp || {};
		var locked = props.locked;

		function setWa( patch ) {
			props.onChange( { whatsapp: Object.assign( {}, wa, patch ) } );
		}

		return el(
			'div',
			{
				className:
					'hs-builder-whatsapp' + ( locked ? ' hs-builder-locked' : '' ),
			},
			el(
				'h3',
				{ className: 'hs-builder-subtitle' },
				t( 'whatsappSection', 'WhatsApp' ),
				locked ? ' ' : null,
				locked ? lockBadge( props.onLocked ) : null
			),
			el(
				'p',
				{ className: 'hs-builder-row' },
				el(
					'label',
					null,
					el( 'input', {
						type: 'checkbox',
						checked: !! wa.enabled,
						disabled: !! locked,
						onChange: function ( e ) {
							setWa( { enabled: e.target.checked } );
						},
					} ),
					' ' + t( 'whatsappOffer', 'WhatsApp-Kontakt anbieten' )
				)
			),
			locked
				? el(
						'p',
						{ className: 'hs-builder-hint' },
						proMessage( 'whatsapp' )
				  )
				: null,
			wa.enabled
				? el(
						'div',
						{ className: 'hs-builder-subsettings' },
						textRow(
							t( 'whatsappNumber', 'Nummer' ),
							wa.number,
							function ( v ) {
								setWa( { number: v } );
							}
						),
						el(
							'p',
							{ className: 'hs-builder-hint' },
							t(
								'whatsappNumberHint',
								'Im internationalen Format, zum Beispiel +49 171 2345678'
							)
						),
						textRow(
							t( 'whatsappButton', 'Knopf-Beschriftung' ),
							wa.button_label,
							function ( v ) {
								setWa( { button_label: v } );
							}
						),
						textRow(
							t( 'whatsappPrefill', 'Vorbefuellter Text' ),
							wa.prefill_text,
							function ( v ) {
								setWa( { prefill_text: v } );
							},
							{ textarea: true }
						),
						textRow(
							t( 'whatsappHint', 'Hinweistext' ),
							wa.hint_text,
							function ( v ) {
								setWa( { hint_text: v } );
							},
							{
								textarea: true,
								placeholder: t(
									'whatsappHintHint',
									'Standardhinweis, wenn leer.'
								),
							}
						)
				  )
				: null
		);
	}

	function IdentitySettings( props ) {
		var identity = props.identity || {};
		// Default an: nur ein ausdrueckliches false schaltet die Knoepfe aus.
		var enabled = false !== identity.enabled;
		// Gesperrt ist nur der Weg zurueck AN (Abschalten bleibt immer moeglich).
		var locked = props.locked;

		return el(
			'div',
			{
				className:
					'hs-builder-identity' + ( locked ? ' hs-builder-locked' : '' ),
			},
			el(
				'h3',
				{ className: 'hs-builder-subtitle' },
				t( 'identitySection', 'Ausfuellhilfe' ),
				locked ? ' ' : null,
				locked ? lockBadge( props.onLocked ) : null
			),
			el(
				'p',
				{ className: 'hs-builder-row' },
				el(
					'label',
					null,
					el( 'input', {
						type: 'checkbox',
						checked: enabled,
						disabled: !! locked,
						onChange: function ( e ) {
							props.onChange( {
								identity: Object.assign( {}, identity, {
									enabled: e.target.checked,
								} ),
							} );
						},
					} ),
					' ' +
						t(
							'identityShow',
							'Knoepfe "Weiter mit Google/Apple" anzeigen, wenn eingerichtet'
						)
				)
			),
			locked
				? el( 'p', { className: 'hs-builder-hint' }, proMessage( 'identity' ) )
				: null
		);
	}

	function EventSettings( props ) {
		var ev = props.event || {};
		var locked = props.locked;

		function setEvent( patch ) {
			props.onChange( { event: Object.assign( {}, ev, patch ) } );
		}

		return el(
			'div',
			{
				className:
					'hs-builder-event' + ( locked ? ' hs-builder-locked' : '' ),
			},
			el(
				'h3',
				{ className: 'hs-builder-subtitle' },
				t( 'eventSection', 'Veranstaltung' ),
				locked ? ' ' : null,
				locked ? lockBadge( props.onLocked ) : null
			),
			el(
				'p',
				{ className: 'hs-builder-row' },
				el(
					'label',
					null,
					el( 'input', {
						type: 'checkbox',
						checked: !! ev.enabled,
						disabled: !! locked,
						onChange: function ( e ) {
							setEvent( { enabled: e.target.checked } );
						},
					} ),
					' ' + t( 'eventEnable', 'Dieses Formular ist eine Veranstaltungs-Anmeldung' )
				)
			),
			locked
				? el( 'p', { className: 'hs-builder-hint' }, proMessage( 'event' ) )
				: null,
			ev.enabled
				? el(
						'div',
						{ className: 'hs-builder-subsettings' },
						el(
							'p',
							{ className: 'hs-builder-hint' },
							t(
								'eventHint',
								'Die Veranstaltungsdaten erscheinen in den Mails und auf dem Ticket mit QR-Code.'
							)
						),
						textRow( t( 'eventTitle', 'Titel der Veranstaltung' ), ev.title, function ( v ) {
							setEvent( { title: v } );
						} ),
						textRow(
							t( 'eventDate', 'Datum und Uhrzeit' ),
							ev.date,
							function ( v ) {
								setEvent( { date: v } );
							},
							{ type: 'datetime-local' }
						),
						textRow( t( 'eventLocation', 'Ort' ), ev.location, function ( v ) {
							setEvent( { location: v } );
						} ),
						textRow(
							t( 'eventUrl', 'Externe Event-Seite (URL, optional)' ),
							ev.url,
							function ( v ) {
								setEvent( { url: v } );
							},
							{ type: 'url' }
						),
						textRow(
							t( 'eventCapacity', 'Kapazitaet (Personen insgesamt, 0 = unbegrenzt)' ),
							undefined === ev.capacity ? '0' : String( ev.capacity ),
							function ( v ) {
								setEvent( { capacity: parseInt( v, 10 ) || 0 } );
							},
							{ type: 'number' }
						),
						el(
							'p',
							{ className: 'hs-builder-hint' },
							t(
								'eventCapacityHint',
								'Begleitpersonen zaehlen mit. Bei Erreichen zeigt das Formular "ausgebucht".'
							)
						)
				  )
				: null
		);
	}

	function FormSettings( props ) {
		var def = props.definition;
		var s = def.settings || {};

		function set( patch ) {
			props.onChange( patch );
		}

		return el(
			'div',
			null,
			el(
				'h2',
				{ className: 'hs-builder-col-title' },
				t( 'formSettings', 'Formular-Einstellungen' )
			),
			el(
				'p',
				{ className: 'hs-builder-hint' },
				t( 'selectFieldHint', 'Waehlen Sie links ein Feld, um es zu bearbeiten. Hier legen Sie fest, was nach dem Absenden passiert.' )
			),
			textRow(
				t( 'recipients', 'Empfaenger (eine E-Mail pro Zeile)' ),
				( s.recipients || [] ).join( '\n' ),
				function ( v ) {
					set( {
						recipients: v
							.split( '\n' )
							.map( function ( line ) {
								return line.trim();
							} )
							.filter( function ( line ) {
								return '' !== line;
							} ),
					} );
				},
				{ textarea: true }
			),
			textRow(
				t( 'successMessage', 'Danke-Nachricht' ),
				s.success_message,
				function ( v ) {
					set( { success_message: v } );
				},
				{ textarea: true }
			),
			textRow(
				t( 'redirectUrl', 'Oder Weiterleitung zu (URL, optional)' ),
				s.redirect_url,
				function ( v ) {
					set( { redirect_url: v } );
				},
				{ type: 'url' }
			),
			el(
				'p',
				{ className: 'hs-builder-row' },
				el(
					'label',
					null,
					el( 'input', {
						type: 'checkbox',
						checked: ! s.confirmation || false !== s.confirmation.enabled ? !! ( s.confirmation && s.confirmation.enabled ) : false,
						onChange: function ( e ) {
							set( {
								confirmation: Object.assign( {}, s.confirmation, {
									enabled: e.target.checked,
								} ),
							} );
						},
					} ),
					' ' + t( 'sendConfirmation', 'Bestaetigungsmail an den Absender senden' )
				)
			),
			s.confirmation && s.confirmation.enabled
				? el(
						'div',
						{ className: 'hs-builder-subsettings' },
						textRow(
							t( 'confirmSubject', 'Betreff der Bestaetigung' ),
							s.confirmation.subject,
							function ( v ) {
								set( {
									confirmation: Object.assign( {}, s.confirmation, { subject: v } ),
								} );
							}
						),
						textRow(
							t( 'confirmBody', 'Text der Bestaetigung' ),
							s.confirmation.body,
							function ( v ) {
								set( {
									confirmation: Object.assign( {}, s.confirmation, { body: v } ),
								} );
							},
							{ textarea: true }
						)
				  )
				: null,
			el( EventSettings, {
				event: s.event,
				onChange: set,
				locked: featureLocked( def, 'event' ),
				onLocked: props.onLocked,
			} ),
			el( WhatsAppSettings, {
				whatsapp: s.whatsapp,
				onChange: set,
				locked: featureLocked( def, 'whatsapp' ),
				onLocked: props.onLocked,
			} ),
			el( IdentitySettings, {
				identity: s.identity,
				onChange: set,
				locked: featureLocked( def, 'identity' ),
				onLocked: props.onLocked,
			} )
		);
	}

	// --- App (Zustand und REST) -------------------------------------------

	function App() {
		var formState = useState( null );
		var form = formState[ 0 ];
		var setForm = formState[ 1 ];
		var viewState = useState( cfg.formId ? 'loading' : 'gallery' );
		var view = viewState[ 0 ];
		var setView = viewState[ 1 ];
		var langState = useState( 'de' );
		var selState = useState( null );
		var savingState = useState( false );
		var busyState = useState( false );
		var noticeState = useState( null );
		var proState = useState( false );

		/**
		 * Kauf-Moment zeigen (nur wenn er nicht schon weggeklickt wurde).
		 */
		function showPro() {
			if ( cfg.proCard ) {
				proState[ 1 ]( true );
			}
		}

		/**
		 * Wegklicken gilt dauerhaft: der Hans-Speicher merkt sich die Karte je
		 * Nutzer, danach liefert der Server proCard nicht mehr aus.
		 */
		function dismissPro() {
			var card = cfg.proCard;
			cfg.proCard = null;
			proState[ 1 ]( false );
			if ( card && cfg.dismissUrl ) {
				fetch( cfg.dismissUrl, {
					method: 'POST',
					credentials: 'same-origin',
					headers: {
						'Content-Type': 'application/json',
						'X-WP-Nonce': cfg.nonce,
					},
					body: JSON.stringify( { card_id: card.id } ),
				} );
			}
		}

		useEffect( function () {
			if ( cfg.formId ) {
				api( '/forms/' + cfg.formId )
					.then( function ( data ) {
						setForm( data );
						setView( 'builder' );
					} )
					.catch( function ( err ) {
						noticeState[ 1 ]( { type: 'error', text: err.message } );
						setView( 'gallery' );
					} );
			}
		}, [] );

		function pickTemplate( key ) {
			busyState[ 1 ]( true );
			var templates = ( cfg.templates || {} )[ langState[ 0 ] ] || {};
			var definition = templates[ key ];
			var name = ( cfg.gallery || [] ).find( function ( g ) {
				return g.key === key;
			} );
			var title = name
				? 'en' === langState[ 0 ]
					? name.name_en
					: name.name
				: key;

			api( '/forms', {
				method: 'POST',
				body: JSON.stringify( {
					title: title,
					status: 'draft',
					definition: definition,
				} ),
			} )
				.then( function ( data ) {
					// URL aktualisieren, ohne neu zu laden.
					if ( window.history && window.history.replaceState ) {
						window.history.replaceState(
							{},
							'',
							cfg.builderBaseUrl + '&form=' + data.id
						);
					}
					setForm( data );
					setView( 'builder' );
					busyState[ 1 ]( false );
				} )
				.catch( function ( err ) {
					noticeState[ 1 ]( { type: 'error', text: err.message } );
					busyState[ 1 ]( false );
				} );
		}

		function patchForm( patch ) {
			setForm( Object.assign( {}, form, patch ) );
		}

		function patchDefinition( patch ) {
			patchForm( {
				definition: Object.assign( {}, form.definition, patch ),
			} );
		}

		function onFieldChange( id, patch ) {
			var fields = ( form.definition.fields || [] ).map( function ( f ) {
				return f.id === id ? Object.assign( {}, f, patch ) : f;
			} );
			patchDefinition( { fields: fields } );
		}

		function onSettingsChange( patch ) {
			patchDefinition( {
				settings: Object.assign( {}, form.definition.settings, patch ),
			} );
		}

		function onAdd( type ) {
			var fields = ( form.definition.fields || [] ).slice();
			var field = {
				id: uniqueId( type, fields ),
				type: type,
				label: typeLabel( type ),
				required: false,
			};
			if ( 'consent' === type ) {
				field.label = '';
				field.required = true;
				field.consent_text = t(
					'defaultConsent',
					'Ich willige ein, dass meine Angaben zur Bearbeitung meiner Anfrage gespeichert und verarbeitet werden.'
				);
			}
			if ( 'select' === type ) {
				field.options = [];
				field.display = 'dropdown';
			}
			// Consent ans Ende, sonst vor ein evtl. Consent-Feld einfuegen.
			var consentIdx = fields.findIndex( function ( f ) {
				return 'consent' === f.type;
			} );
			if ( 'consent' !== type && consentIdx >= 0 ) {
				fields.splice( consentIdx, 0, field );
			} else {
				fields.push( field );
			}
			patchDefinition( { fields: fields } );
			selState[ 1 ]( field.id );
		}

		function onDelete( id ) {
			var fields = ( form.definition.fields || [] ).filter( function ( f ) {
				return f.id !== id;
			} );
			patchDefinition( { fields: fields } );
			if ( selState[ 0 ] === id ) {
				selState[ 1 ]( null );
			}
		}

		function onMove( id, dir ) {
			var fields = ( form.definition.fields || [] ).slice();
			var idx = fields.findIndex( function ( f ) {
				return f.id === id;
			} );
			var target = idx + dir;
			if ( idx < 0 || target < 0 || target >= fields.length ) {
				return;
			}
			var tmp = fields[ idx ];
			fields[ idx ] = fields[ target ];
			fields[ target ] = tmp;
			patchDefinition( { fields: fields } );
		}

		function save() {
			savingState[ 1 ]( true );
			noticeState[ 1 ]( null );
			api( '/forms/' + form.id, {
				method: 'PUT',
				body: JSON.stringify( {
					title: form.title,
					status: form.status,
					definition: form.definition,
				} ),
			} )
				.then( function ( data ) {
					setForm( data );
					savingState[ 1 ]( false );
					noticeState[ 1 ]( {
						type: 'success',
						text: t( 'saved', 'Gespeichert.' ),
					} );
				} )
				.catch( function ( err ) {
					savingState[ 1 ]( false );
					noticeState[ 1 ]( { type: 'error', text: err.message } );
				} );
		}

		var content;
		if ( 'loading' === view ) {
			content = el(
				'p',
				{ className: 'hs-builder-loading' },
				t( 'loading', 'Wird geladen.' )
			);
		} else if ( 'gallery' === view ) {
			content = el( Gallery, {
				lang: langState[ 0 ],
				onLang: langState[ 1 ],
				onPick: pickTemplate,
				onLocked: showPro,
				busy: busyState[ 0 ],
			} );
		} else {
			content = el( Builder, {
				form: form,
				selectedId: selState[ 0 ],
				saving: savingState[ 0 ],
				notice: noticeState[ 0 ],
				onTitle: function ( v ) {
					patchForm( { title: v } );
				},
				onStatus: function ( v ) {
					patchForm( { status: v } );
				},
				onSave: save,
				onSelect: selState[ 1 ],
				onAdd: onAdd,
				onDelete: onDelete,
				onMove: onMove,
				onFieldChange: onFieldChange,
				onSettingsChange: onSettingsChange,
				onLocked: showPro,
			} );
		}

		return el(
			'div',
			null,
			proState[ 0 ] && cfg.proCard
				? el( ProCard, { card: cfg.proCard, onDismiss: dismissPro } )
				: null,
			content
		);
	}

	document.addEventListener( 'DOMContentLoaded', function () {
		var mount = document.getElementById( 'hs-leadlotse-builder' );
		if ( mount ) {
			render( el( App ), mount );
		}
	} );
} )( window.wp );
