/**
 * Kurato Kontaktprofil (Etappe K3 / K3b).
 *
 * No-Build-React. Stammdaten (editierbar), Pipeline-Stufe, Tags, Wiedervorlagen
 * und der Verlauf der Stufenwechsel (Timeline). Spricht kurato/v1/contacts.
 */
( 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.kuratoContact || {};
	var i18n = cfg.i18n || {};

	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 ) || 'Fehler' );
				}
				return body;
			} );
		} );
	}

	function formatDate( gmt, dateOnly ) {
		if ( ! gmt ) {
			return '';
		}
		var d = new Date( String( gmt ).replace( ' ', 'T' ) + ( dateOnly ? 'T00:00:00Z' : 'Z' ) );
		if ( isNaN( d.getTime() ) ) {
			return String( gmt );
		}
		return dateOnly ? d.toLocaleDateString() : d.toLocaleString();
	}

	function field( label, value, onChange, type ) {
		return el(
			'p',
			{ className: 'hs-contact-field' },
			el( 'label', null, label ),
			cfg.canManage
				? el( 'input', {
						type: type || 'text',
						value: value || '',
						onChange: function ( e ) {
							onChange( e.target.value );
						},
				  } )
				: el( 'span', null, value || '-' )
		);
	}

	function App() {
		var contactState = useState( null );
		var contact = contactState[ 0 ];
		var setContact = contactState[ 1 ];
		var stagesState = useState( [] );
		var historyState = useState( [] );
		var tagsState = useState( [] );
		var tasksState = useState( [] );
		var subsState = useState( [] );
		var bookingsState = useState( [] );
		var newTagState = useState( '' );
		var newTaskState = useState( { title: '', due: '' } );
		var noticeState = useState( '' );
		var errorState = useState( '' );

		var id = cfg.contactId;

		useEffect( function () {
			Promise.all( [
				api( '/contacts/' + id ),
				api( '/stages' ),
				api( '/contacts/' + id + '/history' ),
				api( '/contacts/' + id + '/tags' ),
				api( '/contacts/' + id + '/tasks' ),
				api( '/contacts/' + id + '/subscriptions' ),
				api( '/contacts/' + id + '/bookings' ),
			] )
				.then( function ( res ) {
					setContact( res[ 0 ] );
					stagesState[ 1 ]( arr( res[ 1 ] ) );
					historyState[ 1 ]( arr( res[ 2 ] ) );
					tagsState[ 1 ]( arr( res[ 3 ] ) );
					tasksState[ 1 ]( arr( res[ 4 ] ) );
					subsState[ 1 ]( arr( res[ 5 ] ) );
					bookingsState[ 1 ]( arr( res[ 6 ] ) );
				} )
				.catch( function ( err ) {
					errorState[ 1 ]( err.message );
				} );
		}, [] );

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

		function patch( key, value ) {
			var next = Object.assign( {}, contact );
			next[ key ] = value;
			setContact( next );
		}

		function save() {
			noticeState[ 1 ]( '' );
			api( '/contacts/' + id, {
				method: 'PUT',
				body: JSON.stringify( {
					display_name: contact.display_name,
					first_name: contact.first_name,
					last_name: contact.last_name,
					email: contact.email,
					phone: contact.phone,
				} ),
			} )
				.then( function ( updated ) {
					setContact( updated );
					noticeState[ 1 ]( t( 'saved', 'Gespeichert.' ) );
				} )
				.catch( function ( err ) {
					noticeState[ 1 ]( err.message );
				} );
		}

		function changeStage( stageId ) {
			api( '/contacts/' + id + '/stage', {
				method: 'POST',
				body: JSON.stringify( { stage_id: stageId ? parseInt( stageId, 10 ) : null } ),
			} )
				.then( function ( updated ) {
					setContact( updated );
					return api( '/contacts/' + id + '/history' );
				} )
				.then( function ( h ) {
					historyState[ 1 ]( arr( h ) );
				} )
				.catch( function ( err ) {
					noticeState[ 1 ]( err.message );
				} );
		}

		function addTag() {
			var label = newTagState[ 0 ].trim();
			if ( '' === label ) {
				return;
			}
			api( '/contacts/' + id + '/tags', {
				method: 'POST',
				body: JSON.stringify( { label: label } ),
			} ).then( function ( tags ) {
				tagsState[ 1 ]( arr( tags ) );
				newTagState[ 1 ]( '' );
			} ).catch( function ( err ) {
				noticeState[ 1 ]( err.message );
			} );
		}

		function removeTag( tagId ) {
			api( '/contacts/' + id + '/tags/' + tagId, { method: 'DELETE' } ).then( function ( tags ) {
				tagsState[ 1 ]( arr( tags ) );
			} ).catch( function ( err ) {
				noticeState[ 1 ]( err.message );
			} );
		}

		function addTask() {
			var task = newTaskState[ 0 ];
			if ( '' === task.title.trim() ) {
				return;
			}
			api( '/contacts/' + id + '/tasks', {
				method: 'POST',
				body: JSON.stringify( { title: task.title, due_date: task.due } ),
			} ).then( function ( tasks ) {
				tasksState[ 1 ]( arr( tasks ) );
				newTaskState[ 1 ]( { title: '', due: '' } );
			} ).catch( function ( err ) {
				noticeState[ 1 ]( err.message );
			} );
		}

		function toggleTask( task ) {
			api( '/tasks/' + task.id + '/done', {
				method: 'POST',
				body: JSON.stringify( { done: ! task.done } ),
			} ).then( function ( tasks ) {
				tasksState[ 1 ]( arr( tasks ) );
			} ).catch( function ( err ) {
				noticeState[ 1 ]( err.message );
			} );
		}

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

		var title = contact.display_name || contact.email || ( t( 'contact', 'Kontakt' ) + ' #' + contact.id );

		return el(
			'div',
			{ className: 'hs-contact' },
			el( 'p', null, el( 'a', { href: cfg.boardUrl, className: 'button' }, t( 'backToBoard', 'Zurueck zur Pipeline' ) ) ),
			el( 'h1', null, title ),
			noticeState[ 0 ] ? el( 'div', { className: 'notice notice-info' }, el( 'p', null, noticeState[ 0 ] ) ) : null,
			el(
				'div',
				{ className: 'hs-contact-cols' },
				el(
					'div',
					{ className: 'hs-contact-main' },
					deliverySection(),
					el( 'h2', null, t( 'details', 'Stammdaten' ) ),
					field( t( 'displayName', 'Anzeigename' ), contact.display_name, function ( v ) { patch( 'display_name', v ); } ),
					field( t( 'firstName', 'Vorname' ), contact.first_name, function ( v ) { patch( 'first_name', v ); } ),
					field( t( 'lastName', 'Nachname' ), contact.last_name, function ( v ) { patch( 'last_name', v ); } ),
					field( t( 'email', 'E-Mail' ), contact.email, function ( v ) { patch( 'email', v ); }, 'email' ),
					field( t( 'phone', 'Telefon' ), contact.phone, function ( v ) { patch( 'phone', v ); }, 'tel' ),
					cfg.canManage
						? el( 'p', null, el( 'button', { type: 'button', className: 'button button-primary', onClick: save }, t( 'save', 'Speichern' ) ) )
						: null,
					tasksSection()
				),
				el(
					'div',
					{ className: 'hs-contact-side' },
					stageSection(),
					tagsSection(),
					subscriptionsSection(),
					bookingsSection(),
					timelineSection()
				)
			)
		);

		// --- Teilbereiche ---------------------------------------------------

		function deliverySection() {
			var status = contact.email_status || 'active';
			if ( 'active' === status ) {
				return null;
			}
			var label = 'suppressed_complaint' === status
				? t( 'deliveryComplaint', 'Beschwerde eingegangen' )
				: t( 'deliveryBounce', 'Adresse unzustellbar' );
			var since = contact.email_status_since ? formatDate( contact.email_status_since ) : '';
			if ( since ) {
				label = label + ' ' + t( 'deliverySince', 'seit' ) + ' ' + since;
			}
			return el( 'div', { className: 'notice notice-warning hs-contact-delivery' }, el( 'p', null, label ) );
		}

		function stageSection() {
			return el(
				'div',
				{ className: 'hs-contact-block' },
				el( 'h2', null, t( 'stage', 'Pipeline-Stufe' ) ),
				cfg.canManage
					? el(
							'select',
							{
								value: contact.stage_id ? String( contact.stage_id ) : '',
								'aria-label': t( 'stage', 'Pipeline-Stufe' ),
								onChange: function ( e ) { changeStage( e.target.value ); },
							},
							[ el( 'option', { key: 0, value: '' }, t( 'noStage', 'Ohne Stufe' ) ) ].concat(
								stagesState[ 0 ].map( function ( s ) {
									return el( 'option', { key: s.id, value: String( s.id ) }, s.label );
								} )
							)
					  )
					: el( 'p', null, stageLabel( stagesState[ 0 ], contact.stage_id ) )
			);
		}

		function tagsSection() {
			return el(
				'div',
				{ className: 'hs-contact-block' },
				el( 'h2', null, t( 'tags', 'Tags' ) ),
				el(
					'div',
					{ className: 'hs-tags' },
					tagsState[ 0 ].length === 0
						? el( 'span', { className: 'hs-muted' }, t( 'noTags', 'Keine Tags' ) )
						: tagsState[ 0 ].map( function ( tag ) {
								return el(
									'span',
									{ key: tag.id, className: 'hs-tag' },
									tag.label,
									cfg.canManage
										? el(
												'button',
												{
													type: 'button',
													className: 'hs-tag-remove',
													'aria-label': t( 'removeTag', 'Tag entfernen' ),
													onClick: function () { removeTag( tag.id ); },
												},
												'×'
										  )
										: null
								);
						  } )
				),
				cfg.canManage
					? el(
							'div',
							{ className: 'hs-tag-add' },
							el( 'input', {
								type: 'text',
								value: newTagState[ 0 ],
								placeholder: t( 'newTag', 'Neuer Tag' ),
								'aria-label': t( 'newTag', 'Neuer Tag' ),
								onChange: function ( e ) { newTagState[ 1 ]( e.target.value ); },
								onKeyDown: function ( e ) { if ( 'Enter' === e.key ) { e.preventDefault(); addTag(); } },
							} ),
							el( 'button', { type: 'button', className: 'button', onClick: addTag }, t( 'add', 'Hinzufuegen' ) )
					  )
					: null
			);
		}

		function tasksSection() {
			return el(
				'div',
				{ className: 'hs-contact-block hs-tasks' },
				el( 'h2', null, t( 'tasks', 'Wiedervorlagen' ) ),
				tasksState[ 0 ].length === 0
					? el( 'p', { className: 'hs-muted' }, t( 'noTasks', 'Keine offenen Wiedervorlagen.' ) )
					: el(
							'ul',
							{ className: 'hs-task-list' },
							tasksState[ 0 ].map( function ( task ) {
								return el(
									'li',
									{ key: task.id, className: 'hs-task' + ( task.done ? ' is-done' : '' ) },
									el( 'input', {
										type: 'checkbox',
										checked: task.done,
										disabled: ! cfg.canManage,
										'aria-label': t( 'markDone', 'Als erledigt markieren' ),
										onChange: function () { toggleTask( task ); },
									} ),
									el( 'span', { className: 'hs-task-title' }, task.title ),
									task.due_date ? el( 'span', { className: 'hs-task-due' }, formatDate( task.due_date, true ) ) : null
								);
							} )
					  ),
				cfg.canManage
					? el(
							'div',
							{ className: 'hs-task-add' },
							el( 'input', {
								type: 'text',
								value: newTaskState[ 0 ].title,
								placeholder: t( 'taskTitle', 'Was ist zu tun?' ),
								'aria-label': t( 'taskTitle', 'Was ist zu tun?' ),
								onChange: function ( e ) { newTaskState[ 1 ]( { title: e.target.value, due: newTaskState[ 0 ].due } ); },
							} ),
							el( 'input', {
								type: 'date',
								value: newTaskState[ 0 ].due,
								'aria-label': t( 'taskDue', 'Faellig am' ),
								onChange: function ( e ) { newTaskState[ 1 ]( { title: newTaskState[ 0 ].title, due: e.target.value } ); },
							} ),
							el( 'button', { type: 'button', className: 'button', onClick: addTask }, t( 'add', 'Hinzufuegen' ) )
					  )
					: null
			);
		}

		function subStatusLabel( status ) {
			if ( 'confirmed' === status ) {
				return t( 'subConfirmed', 'Bestaetigt' );
			}
			if ( 'unsubscribed' === status ) {
				return t( 'subUnsubscribed', 'Abgemeldet' );
			}
			return t( 'subPending', 'Wartet auf Bestaetigung' );
		}

		function subscriptionsSection() {
			return el(
				'div',
				{ className: 'hs-contact-block' },
				el( 'h2', null, t( 'subscriptions', 'Newsletter-Abos' ) ),
				subsState[ 0 ].length === 0
					? el( 'p', { className: 'hs-muted' }, t( 'noSubscriptions', 'Keine Abos.' ) )
					: el(
							'ul',
							{ className: 'hs-sub-list' },
							subsState[ 0 ].map( function ( sub ) {
								return el(
									'li',
									{ key: sub.id, className: 'hs-sub' },
									el( 'span', { className: 'hs-sub-label' }, sub.list_label ),
									el(
										'span',
										{ className: 'hs-sub-status hs-sub-status--' + sub.status },
										subStatusLabel( sub.status )
									)
								);
							} )
					  )
			);
		}

		function bookingStatusLabel( status ) {
			if ( 'cancelled' === status ) {
				return t( 'bookingCancelled', 'Storniert' );
			}
			return t( 'bookingConfirmed', 'Bestaetigt' );
		}

		function bookingsSection() {
			return el(
				'div',
				{ className: 'hs-contact-block' },
				el( 'h2', null, t( 'bookings', 'Termine' ) ),
				bookingsState[ 0 ].length === 0
					? el( 'p', { className: 'hs-muted' }, t( 'noBookings', 'Keine Termine.' ) )
					: el(
							'ul',
							{ className: 'hs-sub-list' },
							bookingsState[ 0 ].map( function ( b ) {
								return el(
									'li',
									{ key: b.id, className: 'hs-sub' },
									el(
										'span',
										{ className: 'hs-sub-label' },
										( b.type_label || '' ) + ' - ' + formatDate( b.start_utc )
									),
									el(
										'span',
										{ className: 'hs-sub-status hs-sub-status--' + b.status },
										bookingStatusLabel( b.status )
									)
								);
							} )
					  )
			);
		}

		function timelineSection() {
			return el(
				'div',
				{ className: 'hs-contact-block' },
				el( 'h2', null, t( 'timeline', 'Verlauf' ) ),
				historyState[ 0 ].length === 0
					? el( 'p', { className: 'hs-muted' }, t( 'noHistory', 'Noch keine Stufenwechsel.' ) )
					: el(
							'ul',
							{ className: 'hs-timeline' },
							historyState[ 0 ].map( function ( h ) {
								// CP5: Der Verlauf traegt auch Notizen (type 'note').
								var text = h.note
									? h.note
									: ( h.from_label ? h.from_label + ' -> ' : '' ) + ( h.to_label || t( 'noStage', 'Ohne Stufe' ) );
								return el(
									'li',
									{ key: h.id, className: 'hs-timeline-item' },
									el( 'span', { className: 'hs-timeline-text' }, text ),
									el( 'span', { className: 'hs-timeline-date' }, formatDate( h.changed_at ) )
								);
							} )
					  )
			);
		}
	}

	function stageLabel( stages, id ) {
		for ( var i = 0; i < stages.length; i++ ) {
			if ( stages[ i ].id === id ) {
				return stages[ i ].label;
			}
		}
		return t( 'noStage', 'Ohne Stufe' );
	}

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