( function () {
	'use strict';

	if ( typeof arcaiChat === 'undefined' ) {
		return;
	}

	var cfg = arcaiChat;
	var inlineHost = document.querySelector( '[data-arcai-inline]' );
	var root = inlineHost || document.getElementById( 'arcai-root' );
	var inline = !! inlineHost;
	if ( ! root ) {
		return;
	}

	var history = [];
	try {
		history = JSON.parse( sessionStorage.getItem( 'arcaiHistory' ) || '[]' );
	} catch ( e ) {
		history = [];
	}

	var open = false;
	var busy = false;

	var bubble = el( 'button', 'arcai-bubble' );
	bubble.setAttribute( 'aria-label', cfg.i18n.title );
	bubble.style.background = cfg.color;
	bubble.innerHTML = '<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 11.5a8.38 8.38 0 0 1-8.5 8.5 8.6 8.6 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 8.5-8.5 8.38 8.38 0 0 1 8.5 8.5z"/></svg>';

	var panel = el( 'div', inline ? 'arcai-panel arcai-panel-inline' : 'arcai-panel' );
	panel.hidden = ! inline;

	var header = el( 'div', 'arcai-header' );
	header.style.background = cfg.color;
	var headerTitle = el( 'span', 'arcai-title' );
	headerTitle.textContent = cfg.i18n.title;
	var closeBtn = el( 'button', 'arcai-close' );
	closeBtn.textContent = '×';
	closeBtn.setAttribute( 'aria-label', 'Close' );
	header.appendChild( headerTitle );
	header.appendChild( closeBtn );

	var messages = el( 'div', 'arcai-messages' );

	var form = el( 'form', 'arcai-form' );
	var input = el( 'input', 'arcai-input' );
	input.type = 'text';
	input.placeholder = cfg.i18n.placeholder;
	input.maxLength = 1000;
	var sendBtn = el( 'button', 'arcai-send' );
	sendBtn.type = 'submit';
	sendBtn.textContent = cfg.i18n.send;
	sendBtn.style.background = cfg.color;
	form.appendChild( input );
	form.appendChild( sendBtn );

	panel.appendChild( header );
	panel.appendChild( messages );
	panel.appendChild( form );
	root.appendChild( panel );
	if ( inline ) {
		open = true;
		closeBtn.hidden = true;
	} else {
		root.appendChild( bubble );
		bubble.addEventListener( 'click', toggle );
		closeBtn.addEventListener( 'click', toggle );
	}

	addMessage( 'assistant', cfg.greeting );
	history.forEach( function ( turn ) {
		addMessage( turn.role, turn.content, turn.sources || null );
	} );

	form.addEventListener( 'submit', onSubmit );

	function toggle() {
		open = ! open;
		panel.hidden = ! open;
		bubble.classList.toggle( 'arcai-bubble-open', open );
		if ( open ) {
			input.focus();
			scrollDown();
		}
	}

	function onSubmit( e ) {
		e.preventDefault();
		var text = input.value.trim();
		if ( ! text || busy ) {
			return;
		}
		if ( userTurns() >= cfg.maxTurns ) {
			addMessage( 'assistant', cfg.i18n.turnLimit );
			return;
		}

		input.value = '';
		addMessage( 'user', text );
		pushHistory( { role: 'user', content: text } );

		busy = true;
		var typing = addTyping();
		var payload = JSON.stringify( { message: text, history: history.slice( 0, -1 ).map( strip ) } );

		fetch( cfg.streamEndpoint, {
			method: 'POST',
			headers: cfg.nonce
				? { 'Content-Type': 'application/json', 'X-WP-Nonce': cfg.nonce }
				: { 'Content-Type': 'application/json' },
			body: payload
		} )
			.then( function ( res ) {
				var type = res.headers.get( 'Content-Type' ) || '';
				if ( type.indexOf( 'text/event-stream' ) === -1 || ! res.body || ! res.body.getReader ) {
					return res.json().then( function ( data ) {
						finishTurn( typing, null, res.ok && data.answer ? data.answer : '', data, res.ok );
					} );
				}
				return readStream( res, typing );
			} )
			.catch( function () {
				typing.remove();
				busy = false;
				addMessage( 'assistant', cfg.i18n.error );
			} );
	}

	function readStream( res, typing ) {
		var reader = res.body.getReader();
		var decoder = new TextDecoder();
		var buf = '';
		var answer = '';
		var sources = [];
		var failed = null;
		var msgWrap = null;
		var msgBody = null;

		function handleFrame( frame ) {
			var event = 'message';
			var raw = '';
			frame.split( '\n' ).forEach( function ( line ) {
				if ( line.indexOf( 'event:' ) === 0 ) {
					event = line.slice( 6 ).trim();
				} else if ( line.indexOf( 'data:' ) === 0 ) {
					raw += line.slice( 5 ).trim();
				}
			} );
			var data = null;
			try {
				data = JSON.parse( raw );
			} catch ( err ) {}

			if ( event === 'delta' && data && data.t ) {
				if ( ! msgWrap ) {
					typing.remove();
					msgWrap = addMessage( 'assistant', '' );
					msgBody = msgWrap.querySelector( '.arcai-msg-body' );
				}
				answer += data.t;
				msgBody.textContent = answer;
				scrollDown();
			} else if ( event === 'sources' && data ) {
				sources = data;
			} else if ( event === 'error' ) {
				failed = ( data && data.message ) || cfg.i18n.error;
			}
		}

		return reader.read().then( function process( result ) {
			if ( ! result.done ) {
				buf += decoder.decode( result.value, { stream: true } );
				var idx;
				while ( ( idx = buf.indexOf( '\n\n' ) ) !== -1 ) {
					handleFrame( buf.slice( 0, idx ) );
					buf = buf.slice( idx + 2 );
				}
				return reader.read().then( process );
			}

			busy = false;
			if ( failed || ! answer ) {
				typing.remove();
				if ( msgWrap ) {
					msgWrap.remove();
				}
				addMessage( 'assistant', failed || cfg.i18n.error );
				return;
			}
			if ( sources.length ) {
				appendSources( msgWrap, sources );
				scrollDown();
			}
			pushHistory( { role: 'assistant', content: answer, sources: sources } );
		} );
	}

	function finishTurn( typing, msgWrap, answer, data, ok ) {
		typing.remove();
		busy = false;
		if ( ! ok || ! answer ) {
			addMessage( 'assistant', ( data && data.message ) || cfg.i18n.error );
			return;
		}
		addMessage( 'assistant', answer, data.sources );
		pushHistory( { role: 'assistant', content: answer, sources: data.sources } );
	}

	function addMessage( role, text, sources ) {
		var wrap = el( 'div', 'arcai-msg arcai-msg-' + role );
		var body = el( 'div', 'arcai-msg-body' );
		body.textContent = text;
		if ( role === 'user' ) {
			body.style.background = cfg.color;
		}
		wrap.appendChild( body );

		if ( sources && sources.length ) {
			appendSources( wrap, sources );
		}

		messages.appendChild( wrap );
		scrollDown();
		return wrap;
	}

	function appendSources( wrap, sources ) {
		var box = el( 'div', 'arcai-sources' );
		var label = el( 'div', 'arcai-sources-label' );
		label.textContent = cfg.i18n.sources;
		box.appendChild( label );
		sources.forEach( function ( source ) {
			var link = document.createElement( 'a' );
			link.href = source.url;
			link.textContent = '[' + source.n + '] ' + source.title + ( source.date ? ' (' + source.date + ')' : '' );
			link.target = '_blank';
			link.rel = 'noopener';
			box.appendChild( link );
		} );
		wrap.appendChild( box );
	}

	function addTyping() {
		var wrap = el( 'div', 'arcai-msg arcai-msg-assistant arcai-typing' );
		var body = el( 'div', 'arcai-msg-body' );
		body.innerHTML = '<span></span><span></span><span></span>';
		wrap.appendChild( body );
		messages.appendChild( wrap );
		scrollDown();
		return wrap;
	}

	function pushHistory( turn ) {
		history.push( turn );
		if ( history.length > 12 ) {
			history = history.slice( -12 );
		}
		try {
			sessionStorage.setItem( 'arcaiHistory', JSON.stringify( history ) );
		} catch ( e ) {}
	}

	function strip( turn ) {
		return { role: turn.role, content: turn.content };
	}

	function userTurns() {
		return history.filter( function ( turn ) {
			return turn.role === 'user';
		} ).length;
	}

	function scrollDown() {
		messages.scrollTop = messages.scrollHeight;
	}

	function el( tag, className ) {
		var node = document.createElement( tag );
		node.className = className;
		return node;
	}
} )();
