/**
 * Kurato Segment-Builder (Etappe K4d-1).
 *
 * No-Build-React (globale wp.*-Objekte, D13/D14). Liste der Segmente, Anlegen,
 * Umbenennen, Loeschen; Bedingungszeilen (Feld/Operator/Wert) mit UND-Verknuepfung
 * und ein Live-Zaehler ueber kurato/v1/segments/preview-count. Tags und Stufen
 * kommen aus /tags und /stages, die Listen aus wp_localize_script (kuratoSegments).
 */
( 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.kuratoSegments || {};
	var i18n = cfg.i18n || {};
	var lists = Array.isArray( cfg.lists ) ? cfg.lists : [];

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

	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 ) || t( 'error', 'Fehler' ) );
				}
				return body;
			} );
		} );
	}

	function arr( x ) {
		return Array.isArray( x ) ? x : [];
	}

	// Erlaubte Operatoren je Feld (Spiegel der PHP-Sanitisierung, v1).
	function opsFor( field ) {
		if ( 'tag' === field ) {
			return [ 'has', 'has_not' ];
		}
		if ( 'stage' === field ) {
			return [ 'in', 'not_in' ];
		}
		if ( 'list' === field ) {
			return [ 'subscribed' ];
		}
		return [];
	}

	function fieldLabel( field ) {
		if ( 'tag' === field ) {
			return t( 'fieldTag', 'Tag' );
		}
		if ( 'stage' === field ) {
			return t( 'fieldStage', 'Pipeline-Stufe' );
		}
		return t( 'fieldList', 'Liste' );
	}

	function opLabel( op ) {
		var map = {
			has: t( 'opHas', 'hat' ),
			has_not: t( 'opHasNot', 'hat nicht' ),
			in: t( 'opIn', 'ist in' ),
			not_in: t( 'opNotIn', 'ist nicht in' ),
			subscribed: t( 'opSubscribed', 'abonniert (bestaetigt)' ),
		};
		return map[ op ] || op;
	}

	// Standardwert fuer ein Feld: Stufe = Liste von IDs, sonst einzelne ID (0).
	function defaultValue( field ) {
		return 'stage' === field ? [] : 0;
	}

	// Baut die Definition fuer Speichern und Vorschau (match=all in v1).
	function buildDefinition( conditions ) {
		return {
			match: 'all',
			conditions: conditions.map( function ( c ) {
				return { field: c.field, op: c.op, value: c.value };
			} ),
		};
	}

	// Wandelt eine gespeicherte Definition in den Editor-Zustand.
	function conditionsFromDefinition( def ) {
		if ( ! def || ! Array.isArray( def.conditions ) ) {
			return [];
		}
		return def.conditions.map( function ( c ) {
			return {
				field: c.field,
				op: c.op,
				value: 'stage' === c.field ? arr( c.value ).map( Number ) : Number( c.value ) || 0,
			};
		} );
	}

	function App() {
		var segmentsState = useState( [] );
		var tagsState = useState( [] );
		var stagesState = useState( [] );
		var editingState = useState( null ); // { id, label, conditions } oder null
		var countState = useState( null );
		var noticeState = useState( '' );
		var errorState = useState( '' );
		var loadingState = useState( true );

		var editing = editingState[ 0 ];

		useEffect( function () {
			Promise.all( [ api( '/segments' ), api( '/tags' ), api( '/stages' ) ] )
				.then( function ( res ) {
					segmentsState[ 1 ]( arr( res[ 0 ] ) );
					tagsState[ 1 ]( arr( res[ 1 ] ) );
					stagesState[ 1 ]( arr( res[ 2 ] ) );
					loadingState[ 1 ]( false );
				} )
				.catch( function ( err ) {
					errorState[ 1 ]( err.message );
					loadingState[ 1 ]( false );
				} );
		}, [] );

		// Live-Zaehler: bei jeder Aenderung der Bedingungen (entprellt).
		useEffect(
			function () {
				if ( null === editing ) {
					return undefined;
				}
				countState[ 1 ]( null );
				var handle = window.setTimeout( function () {
					api( '/segments/preview-count', {
						method: 'POST',
						body: JSON.stringify( { definition: buildDefinition( editing.conditions ) } ),
					} )
						.then( function ( body ) {
							countState[ 1 ]( body && typeof body.count === 'number' ? body.count : 0 );
						} )
						.catch( function () {
							countState[ 1 ]( null );
						} );
				}, 400 );
				return function () {
					window.clearTimeout( handle );
				};
			},
			// Neu berechnen, wenn sich die Bedingungen als JSON aendern.
			[ editing ? JSON.stringify( editing.conditions ) : '' ]
		);

		function startNew() {
			noticeState[ 1 ]( '' );
			editingState[ 1 ]( { id: 0, label: '', conditions: [] } );
		}

		function startEdit( segment ) {
			noticeState[ 1 ]( '' );
			editingState[ 1 ]( {
				id: segment.id,
				label: segment.label,
				conditions: conditionsFromDefinition( segment.definition ),
			} );
		}

		function cancelEdit() {
			editingState[ 1 ]( null );
			countState[ 1 ]( null );
		}

		function patchEditing( next ) {
			editingState[ 1 ]( Object.assign( {}, editing, next ) );
		}

		function addCondition() {
			var field = 'tag';
			var next = editing.conditions.concat( [ { field: field, op: opsFor( field )[ 0 ], value: defaultValue( field ) } ] );
			patchEditing( { conditions: next } );
		}

		function removeCondition( index ) {
			var next = editing.conditions.filter( function ( _c, i ) {
				return i !== index;
			} );
			patchEditing( { conditions: next } );
		}

		function updateCondition( index, changes ) {
			var next = editing.conditions.map( function ( c, i ) {
				return i === index ? Object.assign( {}, c, changes ) : c;
			} );
			patchEditing( { conditions: next } );
		}

		function changeField( index, field ) {
			updateCondition( index, { field: field, op: opsFor( field )[ 0 ], value: defaultValue( field ) } );
		}

		function save() {
			noticeState[ 1 ]( '' );
			var label = ( editing.label || '' ).trim();
			if ( '' === label ) {
				noticeState[ 1 ]( t( 'namePlaceholder', 'Name des Segments' ) );
				return;
			}
			var payload = { label: label, definition: buildDefinition( editing.conditions ) };
			var request = editing.id > 0
				? api( '/segments/' + editing.id, { method: 'PUT', body: JSON.stringify( payload ) } )
				: api( '/segments', { method: 'POST', body: JSON.stringify( payload ) } );

			request
				.then( function ( saved ) {
					return api( '/segments' ).then( function ( all ) {
						segmentsState[ 1 ]( arr( all ) );
						noticeState[ 1 ]( t( 'saved', 'Gespeichert.' ) );
						editingState[ 1 ]( {
							id: saved.id,
							label: saved.label,
							conditions: conditionsFromDefinition( saved.definition ),
						} );
					} );
				} )
				.catch( function ( err ) {
					noticeState[ 1 ]( err.message );
				} );
		}

		function removeSegment( segment ) {
			if ( ! window.confirm( t( 'confirmDelete', 'Dieses Segment wirklich loeschen?' ) ) ) {
				return;
			}
			api( '/segments/' + segment.id, { method: 'DELETE' } )
				.then( function () {
					return api( '/segments' );
				} )
				.then( function ( all ) {
					segmentsState[ 1 ]( arr( all ) );
					if ( editing && editing.id === segment.id ) {
						cancelEdit();
					}
				} )
				.catch( function ( err ) {
					noticeState[ 1 ]( err.message );
				} );
		}

		if ( errorState[ 0 ] ) {
			return el( 'div', { className: 'notice notice-error' }, el( 'p', null, errorState[ 0 ] ) );
		}
		if ( loadingState[ 0 ] ) {
			return el( 'p', null, t( 'loading', 'Wird geladen.' ) );
		}

		return el(
			'div',
			{ className: 'hs-segments' },
			! cfg.canManage ? el( 'p', { className: 'hs-muted' }, t( 'readOnly', 'Sie koennen Segmente ansehen, aber nicht aendern.' ) ) : null,
			segmentListView(),
			cfg.canManage && null !== editing ? editorView() : null
		);

		// --- Teilansichten --------------------------------------------------

		function segmentListView() {
			var items = segmentsState[ 0 ];
			return el(
				'div',
				{ className: 'hs-segments-list' },
				el(
					'p',
					null,
					cfg.canManage
						? el( 'button', { type: 'button', className: 'button button-primary', onClick: startNew }, t( 'newSegment', 'Neues Segment' ) )
						: null
				),
				items.length === 0
					? el( 'p', { className: 'hs-muted' }, t( 'noSegments', 'Noch keine Segmente. Legen Sie Ihr erstes an.' ) )
					: el(
							'table',
							{ className: 'wp-list-table widefat fixed striped' },
							el( 'thead', null, el( 'tr', null, el( 'th', null, t( 'name', 'Name' ) ), el( 'th', null, '' ) ) ),
							el(
								'tbody',
								null,
								items.map( function ( segment ) {
									return el(
										'tr',
										{ key: segment.id },
										el( 'td', null, el( 'strong', null, segment.label ) ),
										el(
											'td',
											{ style: { textAlign: 'right' } },
											cfg.canManage
												? el(
														wp.element.Fragment,
														null,
														el( 'button', { type: 'button', className: 'button button-small', onClick: function () { startEdit( segment ); } }, t( 'rename', 'Umbenennen' ) ),
														' ',
														el( 'button', { type: 'button', className: 'button button-small button-link-delete', onClick: function () { removeSegment( segment ); } }, t( 'delete', 'Loeschen' ) )
												  )
												: null
										)
									);
								} )
							)
					  )
			);
		}

		function editorView() {
			return el(
				'div',
				{ className: 'hs-segment-editor', style: { marginTop: '24px', padding: '16px', background: '#fff', border: '1px solid #dcdcde' } },
				el( 'h2', null, editing.id > 0 ? editing.label || t( 'newSegment', 'Neues Segment' ) : t( 'newSegment', 'Neues Segment' ) ),
				noticeState[ 0 ] ? el( 'div', { className: 'notice notice-info' }, el( 'p', null, noticeState[ 0 ] ) ) : null,
				el(
					'p',
					null,
					el( 'label', null, el( 'strong', null, t( 'name', 'Name' ) ), el( 'br' ), el( 'input', {
						type: 'text',
						className: 'regular-text',
						value: editing.label,
						placeholder: t( 'namePlaceholder', 'Name des Segments' ),
						onChange: function ( e ) { patchEditing( { label: e.target.value } ); },
					} ) )
				),
				el( 'h3', null, t( 'conditions', 'Bedingungen' ) ),
				el( 'p', { className: 'hs-muted' }, editing.conditions.length === 0 ? t( 'noConditions', 'Ohne Bedingungen trifft das Segment alle Kontakte.' ) : t( 'allMatch', 'Ein Kontakt passt, wenn ALLE Bedingungen zutreffen.' ) ),
				el( 'div', { className: 'hs-conditions' }, editing.conditions.map( conditionRow ) ),
				el( 'p', null, el( 'button', { type: 'button', className: 'button', onClick: addCondition }, t( 'addCondition', 'Bedingung hinzufuegen' ) ) ),
				el( 'p', { className: 'hs-segment-count' }, el( 'strong', null, countText() ) ),
				el(
					'p',
					null,
					el( 'button', { type: 'button', className: 'button button-primary', onClick: save }, t( 'save', 'Speichern' ) ),
					' ',
					el( 'button', { type: 'button', className: 'button', onClick: cancelEdit }, t( 'cancel', 'Abbrechen' ) )
				)
			);
		}

		function countText() {
			if ( null === countState[ 0 ] ) {
				return t( 'counting', 'Trefferzahl wird ermittelt.' );
			}
			return ( t( 'matchCount', 'Segment trifft aktuell %s Kontakte' ) ).replace( '%s', String( countState[ 0 ] ) );
		}

		function conditionRow( cond, index ) {
			return el(
				'div',
				{ key: index, className: 'hs-condition', style: { marginBottom: '8px', display: 'flex', gap: '8px', alignItems: 'flex-start', flexWrap: 'wrap' } },
				// Feld.
				el(
					'select',
					{
						'aria-label': t( 'field', 'Feld' ),
						value: cond.field,
						onChange: function ( e ) { changeField( index, e.target.value ); },
					},
					[ 'tag', 'stage', 'list' ].map( function ( f ) {
						return el( 'option', { key: f, value: f }, fieldLabel( f ) );
					} )
				),
				// Operator.
				el(
					'select',
					{
						'aria-label': t( 'operator', 'Operator' ),
						value: cond.op,
						onChange: function ( e ) { updateCondition( index, { op: e.target.value } ); },
					},
					opsFor( cond.field ).map( function ( op ) {
						return el( 'option', { key: op, value: op }, opLabel( op ) );
					} )
				),
				// Wert.
				valueControl( cond, index ),
				el( 'button', { type: 'button', className: 'button button-small', 'aria-label': t( 'removeCondition', 'Bedingung entfernen' ), onClick: function () { removeCondition( index ); } }, '×' )
			);
		}

		function valueControl( cond, index ) {
			if ( 'tag' === cond.field ) {
				return singleSelect(
					tagsState[ 0 ].map( function ( tag ) { return { value: tag.id, label: tag.label }; } ),
					cond.value,
					function ( v ) { updateCondition( index, { value: v } ); }
				);
			}
			if ( 'list' === cond.field ) {
				return singleSelect(
					lists.map( function ( list ) { return { value: list.id, label: list.label }; } ),
					cond.value,
					function ( v ) { updateCondition( index, { value: v } ); }
				);
			}
			// stage: Mehrfachauswahl per Checkboxen.
			return el(
				'span',
				{ className: 'hs-stage-choices', style: { display: 'inline-flex', flexWrap: 'wrap', gap: '8px' } },
				stagesState[ 0 ].map( function ( stage ) {
					var checked = arr( cond.value ).indexOf( stage.id ) !== -1;
					return el(
						'label',
						{ key: stage.id, style: { whiteSpace: 'nowrap' } },
						el( 'input', {
							type: 'checkbox',
							checked: checked,
							onChange: function () {
								var vals = arr( cond.value ).slice();
								if ( checked ) {
									vals = vals.filter( function ( id ) { return id !== stage.id; } );
								} else {
									vals.push( stage.id );
								}
								updateCondition( index, { value: vals } );
							},
						} ),
						' ' + stage.label
					);
				} )
			);
		}

		function singleSelect( options, value, onChange ) {
			return el(
				'select',
				{
					'aria-label': t( 'value', 'Wert' ),
					value: value ? String( value ) : '',
					onChange: function ( e ) { onChange( e.target.value ? parseInt( e.target.value, 10 ) : 0 ); },
				},
				[ el( 'option', { key: 0, value: '' }, t( 'chooseValue', 'Bitte waehlen' ) ) ].concat(
					options.map( function ( opt ) {
						return el( 'option', { key: opt.value, value: String( opt.value ) }, opt.label );
					} )
				)
			);
		}
	}

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