(function(){
  var ready=function(fn){document.readyState!=='loading'?fn():document.addEventListener('DOMContentLoaded',fn)};
  function base(){return (window.MJ_BASE_URL||'').replace(/\/$/,'')}
  function endpoint(){return window.MJ_LOCATION_FAST_ENDPOINT || (base() + '/api/location-fast.php')}
  var mem={};
  function cacheKey(url){return 'mjloc:'+url}
  function getCache(url){ if(mem[url]) return mem[url]; try{var raw=sessionStorage.getItem(cacheKey(url)); if(raw){var obj=JSON.parse(raw); if(obj.exp>Date.now()) return obj.data;}}catch(e){} return null; }
  function setCache(url,data,ttl){ mem[url]=data; try{sessionStorage.setItem(cacheKey(url),JSON.stringify({exp:Date.now()+(ttl||300000),data:data}))}catch(e){} }
  function debounce(fn,ms){var t;return function(){var a=arguments,s=this;clearTimeout(t);t=setTimeout(function(){fn.apply(s,a)},ms||300)}}
  function fetchJson(url,opts){var c=!opts&&getCache(url); if(c) return Promise.resolve(c); return fetch(url,opts||{headers:{'Accept':'application/json'}}).then(function(r){return r.text().then(function(t){try{return JSON.parse(t)}catch(e){throw new Error('Server returned non-JSON response. Please login again or check server error log.')}})}).then(function(d){if(!opts)setCache(url,d,600000);return d})}
  function escapeHtml(s){return String(s||'').replace(/[&<>"']/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]})}
  function field(form,sel){return form.querySelector(sel)}
  function countryField(form){return field(form,'[name="country_id"],[name="country"]')}
  function stateField(form){return field(form,'[name="state_id"],[name="province_id"],[name="state"],[name="province"]')}
  function cityField(form){return field(form,'[name="city_id"],[name="city"],[name="area_id"],[name="area"]')}
  function valueText(el){ if(!el)return''; if(el.tagName==='SELECT'){var o=el.options[el.selectedIndex];return o?o.textContent.trim():''} return (el.value||'').trim() }
  function setVal(el,val,text){ if(!el)return; if(el.tagName==='SELECT'){var found=false; for(var i=0;i<el.options.length;i++){if(String(el.options[i].value)===String(val)){found=true;break}} if(!found){el.add(new Option(text||val,val,true,true))} el.value=String(val||'');} else { el.value=String(text||val||''); } el.dispatchEvent(new Event('change',{bubbles:true})) }
  function enhanceSelect(original,type,form){
    if(!original || original.dataset.mjLocEnhanced==='1')return; original.dataset.mjLocEnhanced='1';
    var wrap=document.createElement('div'); wrap.className='mj-loc-fast'; wrap.dataset.type=type;
    var input=document.createElement('input'); input.type='text'; input.className='form-control mj-loc-fast-input'; input.autocomplete='off'; input.placeholder=type==='country'?'Search country':(type==='state'?'Search state / province':'Type city name'); input.value=valueText(original).replace(/^(Select|All|Country|State|City|No city|All cities).*$/i,'');
    var results=document.createElement('div'); results.className='mj-loc-fast-results'; results.style.display='none';
    var status=document.createElement('div'); status.className='mj-loc-fast-status'; status.textContent=type==='city'?'Type 2+ letters. We search DB first, then free live lookup, and manual add if missing.':'Start typing to search.';
    original.style.display='none'; original.parentNode.insertBefore(wrap, original.nextSibling); wrap.appendChild(input); wrap.appendChild(results); wrap.appendChild(status);
    var combo={original:original,type:type,form:form,input:input,results:results,status:status};
    input.addEventListener('focus',function(){runSearch(combo,input.value,true)});
    input.addEventListener('input',debounce(function(){runSearch(combo,input.value,false)},320));
    document.addEventListener('click',function(e){if(!wrap.contains(e.target))results.style.display='none'});
    if(type==='country' && !input.value) setTimeout(function(){runSearch(combo,'',true)},60);
  }
  function params(combo,term){var p=new URLSearchParams();p.set('action',combo.type==='country'?'countries':(combo.type==='state'?'states':'cities'));p.set('q',term||'');p.set('limit','18');var cf=countryField(combo.form),sf=stateField(combo.form); if(cf)p.set('country_id',cf.value||'0'); if(sf)p.set('state_id',sf.value||'0'); return p}
  function runSearch(combo,term,initial){
    if(combo.type==='city' && !initial && String(term||'').length<2){combo.results.style.display='block';combo.results.innerHTML='<div class="mj-loc-fast-empty">Type at least 2 letters to search city.</div>';return;}
    if(combo.type==='state' && !(countryField(combo.form)||{}).value){combo.results.style.display='block';combo.results.innerHTML='<div class="mj-loc-fast-empty">Select country first.</div>';return;}
    combo.results.style.display='block'; combo.results.innerHTML='<div class="mj-loc-fast-loading">'+(combo.type==='city'?'Searching cities...':'Loading...')+'</div>'; combo.status.textContent='Loading...';
    var url=endpoint()+'?'+params(combo,term).toString();
    fetchJson(url).then(function(data){if(!data.ok)throw new Error(data.error||'Unable to load'); render(combo,data.results||[],data.cached)}).catch(function(err){combo.results.innerHTML='<div class="mj-loc-fast-empty">'+escapeHtml(err.message||'Unable to load')+'</div>';combo.status.textContent='Unable to load.'})
  }
  function render(combo,items,cached){ combo.results.innerHTML=''; combo.status.textContent=(cached?'Loaded from cache. ':'')+(items.length?items.length+' result(s).':'No result.'); if(!items.length){combo.results.innerHTML='<div class="mj-loc-fast-empty">No result found.</div>';return} items.forEach(function(item){var b=document.createElement('button');b.type='button';b.className='mj-loc-fast-row'+(item.live?' is-live':'')+(item.manual?' is-manual':'')+(item.local?' is-local':''); b.innerHTML='<span>'+escapeHtml(item.text||item.name||'Location')+'</span>'+(item.local?'<em>DB</em>':'')+(item.live?'<em>Live</em>':'')+(item.manual?'<em>Add</em>':''); b.addEventListener('click',function(){select(combo,item)}); combo.results.appendChild(b)}) }
  function reset(form,type){var f=type==='state'?stateField(form):cityField(form); if(!f)return; setVal(f,'',''); var w=f.nextElementSibling; if(w&&w.classList.contains('mj-loc-fast')){var i=w.querySelector('input'); if(i)i.value=''}}
  function select(combo,item){combo.results.style.display='none'; combo.input.value=item.text||item.name||''; if(combo.type==='country'){setVal(combo.original,item.id,item.text); var tz=combo.form.querySelector('[name="timezone"]'); if(tz&&item.timezone)tz.value=item.timezone; var cur=combo.form.querySelector('[name="currency"],[name="currency_code"],[name="preferred_currency"]'); if(cur&&item.currency)cur.value=item.currency; reset(combo.form,'state');reset(combo.form,'city');return} if(combo.type==='state'){ if(String(item.id).indexOf('manual_state:')===0){setVal(combo.original,'',item.name||combo.input.value)}else{setVal(combo.original,item.id,item.text)} reset(combo.form,'city'); return } if(combo.type==='city'){ if(item.live||item.manual)saveCity(combo,item); else setVal(combo.original,item.id,item.text) } }
  function saveCity(combo,item){var fd=new FormData();fd.set('action',item.live?'save_live_city':'save_manual_city');fd.set('country_id',(countryField(combo.form)||{}).value||'0');fd.set('state_id',(stateField(combo.form)||{}).value||'0');fd.set('city_name',item.name||combo.input.value); if(item.payload)fd.set('payload',JSON.stringify(item.payload)); combo.input.classList.add('is-saving');combo.status.textContent='Saving city...'; fetchJson(endpoint(),{method:'POST',body:fd,headers:{'Accept':'application/json'}}).then(function(d){combo.input.classList.remove('is-saving'); if(!d.ok)throw new Error(d.error||'Unable to save city'); if(d.country_id&&countryField(combo.form))setVal(countryField(combo.form),d.country_id,(item.payload&&item.payload.country)||''); if(d.state_id&&stateField(combo.form))setVal(stateField(combo.form),d.state_id,(item.payload&&item.payload.state)||''); setVal(combo.original,d.city_id,d.city_name||item.name); combo.input.value=d.city_name||item.name||combo.input.value; combo.status.textContent='City saved.'}).catch(function(err){combo.input.classList.remove('is-saving'); combo.status.textContent=err.message||'Unable to save city'; alert(combo.status.textContent)}) }
  function enhance(){document.querySelectorAll('form').forEach(function(form){var cf=countryField(form),sf=stateField(form),cif=cityField(form); if(!cf&&!sf&&!cif)return; if(cf)enhanceSelect(cf,'country',form); if(sf)enhanceSelect(sf,'state',form); if(cif)enhanceSelect(cif,'city',form)})}
  ready(enhance);
})();
