(function() {
	const root = document.getElementById('truebe-chatbot-widget');
	if (!root) return;

	const cfg = window.truebeChatbot || {};
	const t = cfg.theme || {};
	const accent = t.accent || '#0f6e56';
	const botColor = t.bot || '#f6f7f7';
	const fbColor = t.fallback || '#fff9e6';
	const width = t.width || 480;
	const showMic = !!t.audio;
	const showSugg = (t.suggestions !== false);
	const headerLabel = t.header || '';
	const greeting = t.greeting || '';
	const noMatchText = t.noMatchText || 'Try rephrasing your question.';
	const inputPlaceholder = showMic ? 'Type or speak…' : 'Type your question…';

	function hx(h){h=h.replace('#','');return [parseInt(h.substr(0,2),16),parseInt(h.substr(2,2),16),parseInt(h.substr(4,2),16)];}
	function toHex(r,g,b){return '#'+[r,g,b].map(v=>('0'+Math.round(v).toString(16)).slice(-2)).join('');}
	function mix(a,b,k){const x=hx(a),y=hx(b);return toHex(x[0]+(y[0]-x[0])*k,x[1]+(y[1]-x[1])*k,x[2]+(y[2]-x[2])*k);}
	function lum(h){const c=hx(h).map(v=>{v/=255;return v<=.03928?v/12.92:Math.pow((v+.055)/1.055,2.4);});return .2126*c[0]+.7152*c[1]+.0722*c[2];}
	function ink(bg){return lum(bg)>.5?'#1d2327':'#ffffff';}
	function esc(s){const d=document.createElement('div');d.textContent=(s==null?'':String(s));return d.innerHTML;}

	/* Auto-links any email address or US-style phone number found in escaped
	 * text, so contact info typed into settings (or auto-generated) is
	 * clickable in the chat without allowing arbitrary HTML through. */
	function linkify(text){
		let out = esc(text);
		out = out.replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, function(m){
			return '<a href="mailto:' + m + '" style="color:inherit;text-decoration:underline;">' + m + '</a>';
		});
		out = out.replace(/(\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g, function(m){
			const digits = m.replace(/[^\d+]/g, '');
			return '<a href="tel:' + digits + '" style="color:inherit;text-decoration:underline;">' + m + '</a>';
		});
		return out;
	}

	const userBg = mix(accent,'#ffffff',.86);
	const userText = mix(accent,'#000000',.15);
	const botText = ink(botColor);
	const fbText = ink(fbColor);
	const tileBg = mix(fbColor,'#000000',.07);

	root.style.maxWidth = width + 'px';

	const micHtml = showMic ? `
		<button class="truebe-chat-btn truebe-chat-btn-mic" aria-label="Microphone">
			<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
				<path d="M12 1a3 3 0 0 0-3 3v12a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
				<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
				<line x1="12" y1="19" x2="12" y2="23"/>
				<line x1="8" y1="23" x2="16" y2="23"/>
			</svg>
		</button>` : '';

	root.innerHTML = `
		<div class="truebe-chat-container">
			${headerLabel ? `<div class="truebe-chat-header">${esc(headerLabel)}</div>` : ''}
			<div class="truebe-messages" style="overflow-y:auto;"></div>
			<div class="truebe-chat-input-row">
				<input type="text" class="truebe-chat-input" placeholder="${esc(inputPlaceholder)}">
				<button class="truebe-chat-btn" aria-label="Send" style="color:${accent}">
					<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
						<path d="M22 2L11 13m11-11l-7 20-4-9-9-4 20-7z"/>
					</svg>
				</button>
				${micHtml}
			</div>
		</div>
	`;

	const messagesEl = root.querySelector('.truebe-messages');
	const inputEl = root.querySelector('.truebe-chat-input');
	const sendBtn = root.querySelector('[aria-label="Send"]');
	const micBtn = root.querySelector('[aria-label="Microphone"]');

	let inFlight = false;

	function setSending(state){
		inFlight = state;
		if (sendBtn) { sendBtn.disabled = state; sendBtn.style.opacity = state ? '0.5' : ''; sendBtn.style.cursor = state ? 'default' : ''; }
		if (inputEl) { inputEl.disabled = state; }
		if (micBtn) { micBtn.disabled = state; }
	}

	function appendNode(node){messagesEl.appendChild(node);messagesEl.scrollTop=messagesEl.scrollHeight;}

	function addUser(text){
		const m=document.createElement('div');m.className='truebe-chat-message';
		m.innerHTML=`<div class="truebe-chat-bubble truebe-chat-user" style="background:${userBg};color:${userText}">${esc(text)}</div>`;
		appendNode(m);
	}
function addBot(html){
		const m=document.createElement('div');m.className='truebe-chat-message';
		m.innerHTML=`<div class="truebe-chat-bubble truebe-chat-bot" style="background:${botColor};color:${botText}">${html}</div>`;
		appendNode(m);
	}
	function addHandoff(handoff){
		if(!handoff||!handoff.url||!handoff.label)return;
		const m=document.createElement('div');m.className='truebe-chat-message';
		const a=document.createElement('a');
		a.href=handoff.url;a.target='_blank';a.rel='noopener noreferrer';
		a.textContent=handoff.label;
		a.style.cssText='display:inline-block;margin:0 0 4px;padding:9px 14px;border-radius:10px;background:'+accent+';color:'+ink(accent)+';text-decoration:none;font-size:13px;font-weight:600;';
		m.appendChild(a);
		appendNode(m);
	}
	function addFallback(result){
		const m=document.createElement('div');m.className='truebe-chat-message';
		let inner=`<div class="truebe-fallback-title">${linkify(result.message)}</div>`;
		if(showSugg && result.suggestions && result.suggestions.length){
			inner+=`<div class="truebe-fallback-sub">You might find these helpful:</div><div class="truebe-fallback-suggestions">`;
			result.suggestions.forEach(s=>{inner+=`<div class="truebe-fallback-item" style="background:${tileBg};color:${fbText}">${esc(s.label)}</div>`;});
			inner+=`</div>`;
		}else if(!result.custom){
			inner+=`<div class="truebe-fallback-sub">${linkify(noMatchText)}</div>`;
		}
		m.innerHTML=`<div class="truebe-fallback" style="background:${fbColor};color:${fbText}">${inner}</div>`;
		appendNode(m);
	}

	if (greeting) addBot(esc(greeting));

	function sendQuery(presetQuery){
		if(inFlight)return;
		const query=(typeof presetQuery==='string'?presetQuery:inputEl.value).trim();
		if(!query)return;
		addUser(query);
		inputEl.value='';
		setSending(true);
		fetch(cfg.ajax_url,{
			method:'POST',
			headers:{'Content-Type':'application/x-www-form-urlencoded'},
			body:new URLSearchParams({action:'truebe_chat_query',query:query,_ajax_nonce:cfg.nonce})
		})
		.then(r=>r.json())
		.then(data=>{
			if(data.success){
				const result=data.data;
if(result.type==='answer'){
					addBot(esc(result.thesis));
					if(result.handoff){addHandoff(result.handoff);}
				}else{
					addFallback(result);
				}
			}
		})
		.catch(()=>addBot('Something went wrong. Please try again.'))
		.finally(()=>{setSending(false);inputEl.focus();});
	}

	sendBtn.addEventListener('click',()=>sendQuery());
	inputEl.addEventListener('keypress',e=>e.key==='Enter'&&sendQuery());
	messagesEl.addEventListener('click',e=>{const item=e.target.closest('.truebe-fallback-item');if(item)sendQuery(item.textContent.trim());});

	if (micBtn) {
		const SpeechRecognition=window.SpeechRecognition||window.webkitSpeechRecognition;
		const disableMic=reason=>{micBtn.disabled=true;micBtn.title=reason;};
		if(!SpeechRecognition){disableMic('Voice input not supported in this browser');}
		else if(!window.isSecureContext){disableMic('Voice input needs a secure (HTTPS) connection');}
		else{
			const recognition=new SpeechRecognition();
			recognition.lang='en-US';recognition.interimResults=true;recognition.continuous=false;
			let listening=false;
			recognition.addEventListener('result',e=>{let tr='';for(let i=0;i<e.results.length;i++){tr+=e.results[i][0].transcript;}inputEl.value=tr;});
			const stopUI=()=>{listening=false;micBtn.classList.remove('is-recording');};
			recognition.addEventListener('end',()=>{stopUI();inputEl.focus();});
			recognition.addEventListener('error',stopUI);
			micBtn.addEventListener('click',()=>{
				if(inFlight)return;
				if(listening){recognition.stop();return;}
				inputEl.value='';
				try{recognition.start();listening=true;micBtn.classList.add('is-recording');}catch(err){stopUI();}
			});
		}
	}
})();