(function(){'use strict';
const base=window.projectsBaseUrl||'',csrf=window.projectsCsrfToken||'';
const libraryEl=document.getElementById('templateLibraryModal'),saveEl=document.getElementById('saveTemplateModal'),useEl=document.getElementById('useTemplateModal');if(!libraryEl||!saveEl||!useEl)return;
const library=bootstrap.Modal.getOrCreateInstance(libraryEl),saveModal=bootstrap.Modal.getOrCreateInstance(saveEl),useModal=bootstrap.Modal.getOrCreateInstance(useEl);let sourceCard=null,activeCategory='All',slugManual=false;
const accessEl=document.getElementById('templateAccessModal'),accessModal=accessEl?bootstrap.Modal.getOrCreateInstance(accessEl):null;
// ── Per-template individual-user grants ──
let selectedUsers=new Map();      // id -> {id,username,email,role}
let lastUserResults=new Map();    // id -> user (from the last search, for click-to-add)
function escHtml(s){return String(s==null?'':s).replace(/[&<>"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));}
function roleTag(r){return '<span class="badge bg-secondary-subtle text-secondary-emphasis ms-1" style="font-size:.62rem;vertical-align:middle">'+escHtml(r)+'</span>';}
function renderUserChips(){
  const wrap=document.getElementById('templateUserChips'),empty=document.getElementById('templateUserEmpty');
  if(!wrap)return;
  wrap.innerHTML=Array.from(selectedUsers.values()).map(u=>'<span class="badge rounded-pill text-bg-primary d-inline-flex align-items-center gap-1" style="font-weight:500">'+escHtml(u.username)+'<button type="button" class="btn-close btn-close-white" style="font-size:.5rem;filter:none" data-remove-user="'+u.id+'" aria-label="Remove"></button></span>').join('');
  if(empty)empty.style.display=selectedUsers.size?'none':'';
}
function addUser(u){if(u&&u.id&&!selectedUsers.has(u.id)){selectedUsers.set(u.id,u);renderUserChips();}}
async function openAccess(card){
  if(!accessModal)return;
  const roles=(card.dataset.templateRoles||'').split(','),id=card.dataset.templateId;
  document.getElementById('templateAccessId').value=id;
  document.getElementById('templateAccessTitle').textContent=card.dataset.templateName;
  ['superadmin','developer','user'].forEach(r=>{const cb=accessEl.querySelector('[name="role_'+r+'"]');if(cb)cb.checked=roles.indexOf(r)>=0;});
  selectedUsers=new Map();
  const search=document.getElementById('templateUserSearch');if(search)search.value='';
  const results=document.getElementById('templateUserResults');if(results){results.style.display='none';results.innerHTML='';}
  renderUserChips();
  try{const res=await fetch(`${base}/projects/templates/${encodeURIComponent(id)}/users`,{headers:{Accept:'application/json'}}),data=await json(res);if(data&&data.success&&Array.isArray(data.users))data.users.forEach(addUser);}catch(e){}
  library.hide();accessModal.show();
}
let userSearchTimer=null;
async function runUserSearch(q){
  const results=document.getElementById('templateUserResults');if(!results)return;
  try{
    const res=await fetch(`${base}/projects/users-search?q=`+encodeURIComponent(q),{headers:{Accept:'application/json'}}),data=await json(res);
    if(!data||!data.success){results.style.display='none';return;}
    lastUserResults=new Map();(data.users||[]).forEach(u=>lastUserResults.set(u.id,u));
    const rows=(data.users||[]).filter(u=>!selectedUsers.has(u.id));
    results.innerHTML=rows.length?rows.map(u=>'<button type="button" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center py-2" data-add-user="'+u.id+'"><span>'+escHtml(u.username)+' <span class="text-muted small">'+escHtml(u.email)+'</span></span>'+roleTag(u.role)+'</button>').join(''):'<div class="list-group-item small text-muted">No matching users.</div>';
    results.style.display='';
  }catch(e){results.style.display='none';}
}
document.getElementById('templateUserSearch')?.addEventListener('input',function(){const q=this.value.trim();clearTimeout(userSearchTimer);userSearchTimer=setTimeout(()=>runUserSearch(q),220);});
document.getElementById('templateUserSearch')?.addEventListener('focus',function(){if(!this.value.trim())runUserSearch('');});
document.getElementById('templateUserResults')?.addEventListener('click',e=>{const btn=e.target.closest('[data-add-user]');if(!btn)return;addUser(lastUserResults.get(parseInt(btn.getAttribute('data-add-user'),10)));const s=document.getElementById('templateUserSearch');if(s)s.value='';const r=document.getElementById('templateUserResults');r.style.display='none';r.innerHTML='';});
document.getElementById('templateUserChips')?.addEventListener('click',e=>{const btn=e.target.closest('[data-remove-user]');if(!btn)return;selectedUsers.delete(parseInt(btn.getAttribute('data-remove-user'),10));renderUserChips();});
document.addEventListener('click',e=>{const results=document.getElementById('templateUserResults');if(results&&!e.target.closest('.template-user-picker'))results.style.display='none';});
document.getElementById('templatesOpenToUsers')?.addEventListener('change',async e=>{const on=e.target.checked;e.target.disabled=true;try{const res=await fetch(`${base}/projects/template-user-access`,{method:'POST',headers:{'Content-Type':'application/json',Accept:'application/json'},body:JSON.stringify({_token:csrf,open:on})}),data=await json(res);if(!res.ok||!data.success)throw new Error(data.message||'Could not save.');Swal.fire({icon:'success',title:on?'Templates opened to Users':'Templates limited to admins',text:data.message,timer:2200,showConfirmButton:false});}catch(err){e.target.checked=!on;Swal.fire('Could not save',err.message,'error');}finally{e.target.disabled=false;}});
document.getElementById('templateAccessForm')?.addEventListener('submit',async e=>{e.preventDefault();const btn=document.getElementById('templateAccessSubmit');busy(btn,true,'Saving…');const id=document.getElementById('templateAccessId').value,roles=['owner'];['superadmin','developer','user'].forEach(r=>{const cb=accessEl.querySelector('[name="role_'+r+'"]');if(cb&&cb.checked)roles.push(r);});const users=Array.from(selectedUsers.keys());try{const res=await fetch(`${base}/projects/templates/${encodeURIComponent(id)}/access`,{method:'POST',headers:{'Content-Type':'application/json',Accept:'application/json'},body:JSON.stringify({_token:csrf,roles,users})}),data=await json(res);if(!res.ok||!data.success)throw new Error(data.message||'Could not save access.');accessModal.hide();await Swal.fire('Access updated',data.message,'success');location.reload();}catch(err){Swal.fire('Could not update access',err.message,'error')}finally{busy(btn,false)}});
const slugify=v=>String(v||'').toLowerCase().trim().replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,'');
async function json(res){const text=await res.text();try{return JSON.parse(text)}catch(_){throw new Error(text||`Request failed (${res.status}).`)}}
function busy(btn,on,label){if(on){btn.dataset.html=btn.innerHTML;btn.disabled=true;btn.innerHTML=`<span class="spinner-border spinner-border-sm me-1"></span>${label}`}else{btn.disabled=false;btn.innerHTML=btn.dataset.html||btn.innerHTML}}
document.getElementById('openTemplateLibrary')?.addEventListener('click',()=>library.show());
document.getElementById('projectsCollection')?.addEventListener('click',e=>{const action=e.target.closest('[data-project-action="template"]');if(!action)return;e.preventDefault();sourceCard=action.closest('[data-project-card]');if(!sourceCard)return;document.getElementById('saveTemplateName').value=`${sourceCard.dataset.name} starter`;document.getElementById('saveTemplateSlug').value=`${sourceCard.dataset.projectSlug}-starter`;document.getElementById('saveTemplateDescription').value=sourceCard.dataset.description||'';slugManual=false;saveModal.show()});
document.getElementById('saveTemplateSlug')?.addEventListener('input',()=>slugManual=true);document.getElementById('saveTemplateName')?.addEventListener('input',e=>{if(!slugManual)document.getElementById('saveTemplateSlug').value=slugify(e.target.value)});
document.getElementById('saveTemplateForm')?.addEventListener('submit',async e=>{e.preventDefault();if(!sourceCard||!e.currentTarget.reportValidity())return;const btn=document.getElementById('saveTemplateSubmit');busy(btn,true,'Saving…');const payload=Object.fromEntries(new FormData(e.currentTarget).entries());payload._token=csrf;payload.include_custom=e.currentTarget.querySelector('[name="include_custom"]').checked;try{const res=await fetch(`${base}/project/${encodeURIComponent(sourceCard.dataset.projectSlug)}/template`,{method:'POST',headers:{'Content-Type':'application/json',Accept:'application/json'},body:JSON.stringify(payload)}),data=await json(res);if(!res.ok||!data.success)throw new Error(data.message||'Template save failed.');saveModal.hide();await Swal.fire('Template saved',data.message,'success');location.reload()}catch(err){Swal.fire('Could not save template',err.message,'error')}finally{busy(btn,false)}});
const grid=document.getElementById('templateGrid'),search=document.getElementById('templateSearch'),empty=document.getElementById('templateEmpty');function filter(){let shown=0;grid?.querySelectorAll('[data-template-card]').forEach(card=>{const matchCategory=activeCategory==='All'||card.dataset.templateCategory===activeCategory,matchSearch=!search?.value.trim()||card.dataset.templateSearch.includes(search.value.trim().toLowerCase()),show=matchCategory&&matchSearch;card.classList.toggle('d-none',!show);if(show)shown++});empty?.classList.toggle('show',shown===0)}search?.addEventListener('input',filter);document.querySelectorAll('[data-template-category]').forEach(btn=>btn.addEventListener('click',()=>{activeCategory=btn.dataset.templateCategory;document.querySelectorAll('[data-template-category]').forEach(item=>item.classList.toggle('active',item===btn));filter()}));
function openUse(card){document.getElementById('useTemplateId').value=card.dataset.templateId;document.getElementById('useTemplateTitle').textContent=card.dataset.templateName;document.getElementById('useTemplateProjectName').value=card.dataset.templateName.replace(/\s+(starter|template)$/i,'');(function(){const base=card.dataset.templateSlug.replace(/-(starter|template)$/,''),taken=new Set(Array.from(document.querySelectorAll('[data-project-card][data-project-slug]')).map(c=>c.dataset.projectSlug));let s=base,i=2;while(taken.has(s))s=base+'-'+(i++);document.getElementById('useTemplateProjectSlug').value=s;})();document.getElementById('useTemplateProjectDescription').value=card.dataset.templateDescription||'';const needs=Number(card.dataset.templateCodeCount)>0,check=document.getElementById('useTemplateCodeConfirmation');check.classList.toggle('d-none',!needs);check.querySelector('input').required=needs;
// Content (Full Restore) templates need a real MySQL/MariaDB database — guide the user there.
const wantsDb=card.dataset.templateContent==='1',form=document.getElementById('useTemplateForm'),hint=document.getElementById('useTemplateDbHint');
const tmNew=form.querySelector('input[name="target_mode"][value="new"]');if(tmNew){tmNew.checked=true;tmNew.dispatchEvent(new Event('change',{bubbles:true}));}
if(hint)hint.classList.toggle('d-none',!wantsDb);
const pick=wantsDb?(form.querySelector('input[name="connection_mode"][value="managed"]')||form.querySelector('input[name="connection_mode"][value="custom"]')):form.querySelector('input[name="connection_mode"][value="sqlite"]');
if(pick){pick.checked=true;pick.dispatchEvent(new Event('change',{bubbles:true}));}
library.hide();useModal.show()}
grid?.addEventListener('click',async e=>{const action=e.target.closest('[data-template-action]');if(!action)return;const card=action.closest('[data-template-card]');if(!card)return;const type=action.dataset.templateAction;if(type==='use')return openUse(card);if(type==='access')return openAccess(card);if(type==='export'){const form=document.getElementById('templateExportForm');form.action=`${base}/projects/templates/${card.dataset.templateId}/export`;return form.submit()}if(type==='delete'){const result=await Swal.fire({title:'Delete template?',text:'Existing projects created from it will not change.',icon:'warning',showCancelButton:true,confirmButtonText:'Delete template',confirmButtonColor:'#dc2626'});if(!result.isConfirmed)return;try{const res=await fetch(`${base}/projects/templates/${card.dataset.templateId}/delete`,{method:'POST',headers:{'Content-Type':'application/json',Accept:'application/json'},body:JSON.stringify({_token:csrf})}),data=await json(res);if(!res.ok||!data.success)throw new Error(data.message);card.remove();filter();Swal.fire('Template deleted',data.message,'success')}catch(err){Swal.fire('Could not delete template',err.message,'error')}}});
let useSlugManual=false;document.getElementById('useTemplateProjectSlug')?.addEventListener('input',()=>useSlugManual=true);document.getElementById('useTemplateProjectName')?.addEventListener('input',e=>{if(!useSlugManual)document.getElementById('useTemplateProjectSlug').value=slugify(e.target.value)});useEl.addEventListener('show.bs.modal',()=>useSlugManual=false);
document.getElementById('useTemplateForm')?.addEventListener('change',e=>{
  if(e.target.name==='connection_mode')document.getElementById('useTemplateSchemaOption').classList.toggle('d-none',e.target.value!=='sqlite');
  if(e.target.name==='target_mode'){const upd=e.target.value==='update';document.getElementById('useTemplateNewFields').classList.toggle('d-none',upd);document.getElementById('useTemplateUpdateFields').classList.toggle('d-none',!upd);['useTemplateProjectName','useTemplateProjectSlug'].forEach(id=>{const el=document.getElementById(id);if(el)el.required=!upd;});}
});
document.getElementById('useTemplateForm')?.addEventListener('submit',async e=>{e.preventDefault();if(!e.currentTarget.reportValidity())return;const btn=document.getElementById('useTemplateSubmit');busy(btn,true,'Creating…');const payload=Object.fromEntries(new FormData(e.currentTarget).entries()),id=payload.template_id;payload._token=csrf;payload.allow_code=e.currentTarget.querySelector('[name="allow_code"]').checked;payload.initialize_schema=e.currentTarget.querySelector('[name="initialize_schema"]').checked;try{const res=await fetch(`${base}/projects/templates/${encodeURIComponent(id)}/create`,{method:'POST',headers:{'Content-Type':'application/json',Accept:'application/json'},body:JSON.stringify(payload)}),data=await json(res);if(!res.ok||!data.success)throw new Error(data.message||'Project creation failed.');useModal.hide();const created=data.schema?.created?.length||0,copy=created?`${data.message} ${created} table${created===1?'':'s'} initialized.`:data.message;const result=await Swal.fire({title:'Project ready',text:copy,icon:'success',showCancelButton:true,confirmButtonText:'Open project',cancelButtonText:'Stay in Projects'});result.isConfirmed?location.href=data.open_url:location.reload()}catch(err){Swal.fire('Could not use template',err.message,'error')}finally{busy(btn,false)}});
})();
