(function(){'use strict';const base=window.projectsBaseUrl||'',csrf=window.projectsCsrfToken||'',el=document.getElementById('projectSchemaModal');if(!el)return;const modal=bootstrap.Modal.getOrCreateInstance(el);let card=null,data=null;async function read(r){const t=await r.text();try{return JSON.parse(t)}catch(_){throw new Error(t||`Request failed (${r.status}).`)}}async function post(path,payload){const r=await fetch(base+path,{method:'POST',headers:{'Content-Type':'application/json',Accept:'application/json'},body:JSON.stringify({...payload,_token:csrf})}),d=await read(r);if(!r.ok||!d.success)throw new Error(d.message||'Request failed.');return d}function busy(b,on,label){if(on){b.dataset.html=b.innerHTML;b.disabled=true;b.innerHTML=`<span class="spinner-border spinner-border-sm me-1"></span>${label}`}else{b.disabled=false;b.innerHTML=b.dataset.html||b.innerHTML}}
document.getElementById('projectsCollection')?.addEventListener('click',e=>{const a=e.target.closest('[data-project-action="schema"]');if(!a)return;e.preventDefault();card=a.closest('[data-project-card]');if(!card)return;document.getElementById('schemaProjectName').textContent=card.dataset.name;modal.show();load()});document.getElementById('schemaRefresh')?.addEventListener('click',load);
async function load(){if(!card)return;const b=document.getElementById('schemaRefresh');busy(b,true,'Loading…');try{const r=await fetch(`${base}/project/${encodeURIComponent(card.dataset.projectSlug)}/schema-sync`,{headers:{Accept:'application/json'}}),d=await read(r);if(!r.ok||!d.success)throw new Error(d.message);data=d.comparison;render()}catch(e){Swal.fire('Schema comparison failed',e.message,'error')}finally{busy(b,false)}}
function render(){Object.entries(data.counts).forEach(([k,v])=>{const n=document.querySelector(`[data-schema-count="${k}"]`);if(n)n.textContent=v});document.getElementById('schemaEngine').textContent=data.dialect?.label||data.dialect?.id||'Database';renderObjects('schemaDatabaseOnly',data.database_only,'database');renderObjects('schemaProjectOnly',data.project_only,'project');renderConflicts()}
function renderObjects(id,items,side){const root=document.getElementById(id);root.replaceChildren();if(!items.length){const x=document.createElement('div');x.className='schema-empty';x.textContent=side==='database'?'No untracked database objects.':'No project-only objects.';root.append(x);return}items.forEach(o=>{const label=document.createElement('label');label.className='schema-object';const check=document.createElement('input');check.type='checkbox';check.className='form-check-input';check.dataset.schemaSelect=side;check.value=o.name;if(side==='project'&&!o.blueprint_available)check.disabled=true;const copy=document.createElement('span'),strong=document.createElement('strong'),small=document.createElement('small');strong.textContent=o.name;small.textContent=side==='project'?(o.blueprint_available?'Portable blueprint available':'No portable blueprint available'):(o.type||'TABLE');copy.append(strong,small);const badge=document.createElement('span');badge.className='badge text-bg-light';badge.textContent=o.type||'TABLE';label.append(check,copy,badge);root.append(label)})}
function renderConflicts(){const root=document.getElementById('schemaConflicts');root.replaceChildren();const all=[...(data.changed||[]),...(data.needs_refresh||[]).map(x=>({...x,needsRefresh:true}))];if(!all.length){const x=document.createElement('div');x.className='schema-empty';x.textContent='Tracked project structures match the live database.';root.append(x);return}all.forEach(o=>{const row=document.createElement('article');row.className='schema-conflict';const head=document.createElement('div');head.className='schema-conflict-head';const h=document.createElement('h6');h.textContent=o.name;const badge=document.createElement('span');badge.className='badge '+(o.needsRefresh?'text-bg-secondary':'text-bg-warning');badge.textContent=o.needsRefresh?'Definition missing':'Field drift';head.append(h,badge);row.append(head);if(o.fields){const s=document.createElement('div');s.className='schema-conflict-summary';[['added',o.fields.added],['removed',o.fields.removed],['modified',o.fields.modified]].forEach(([k,v])=>{const x=document.createElement('span');x.textContent=`${v.length} ${k}`;s.append(x)});row.append(s);const ul=document.createElement('ul');ul.className='schema-field-details';o.fields.modified.slice(0,8).forEach(f=>{const li=document.createElement('li');li.textContent=`${f.name}: ${f.project.type} → ${f.database.type}`;ul.append(li)});row.append(ul)}root.append(row)})}
function selected(side){return Array.from(document.querySelectorAll(`[data-schema-select="${side}"]:checked`)).map(x=>x.value)}document.getElementById('schemaImport')?.addEventListener('click',async e=>{const tables=selected('database');if(!tables.length)return Swal.fire('Select tables','Choose at least one database object to import.','info');busy(e.currentTarget,true,'Importing…');try{const d=await post(`/project/${encodeURIComponent(card.dataset.projectSlug)}/schema-sync/import`,{tables});await load();Swal.fire('Imported',d.message,'success')}catch(err){Swal.fire('Import failed',err.message,'error')}finally{busy(e.currentTarget,false)}});
document.getElementById('schemaRebuild')?.addEventListener('click',async e=>{const remove=document.getElementById('schemaRemoveMissing').checked;const result=await Swal.fire({title:'Rebuild project structures?',text:remove?'Missing objects, positions, and affected relationships will be removed after a safety checkpoint.':'Live definitions will refresh; missing project objects will be preserved.',icon:'question',showCancelButton:true,confirmButtonText:'Rebuild'});if(!result.isConfirmed)return;busy(e.currentTarget,true,'Rebuilding…');try{const d=await post(`/project/${encodeURIComponent(card.dataset.projectSlug)}/schema-sync/rebuild`,{remove_missing:remove});await load();Swal.fire('Structures rebuilt',d.message,'success')}catch(err){Swal.fire('Rebuild failed',err.message,'error')}finally{busy(e.currentTarget,false)}});
document.getElementById('schemaCreateMissing')?.addEventListener('click',async e=>{const tables=selected('project');if(!tables.length)return Swal.fire('Select tables','Choose at least one project-only table with a blueprint.','info');const result=await Swal.fire({title:'Create missing database tables?',html:'<p class="small text-muted">Only new tables will be created. Existing tables are not altered.</p>',input:'text',inputLabel:`Type “${card.dataset.name}” to confirm`,showCancelButton:true,confirmButtonText:'Create tables',preConfirm:v=>{if(v!==card.dataset.name){Swal.showValidationMessage('Project name does not match.');return false}return v}});if(!result.isConfirmed)return;busy(e.currentTarget,true,'Creating…');try{const d=await post(`/project/${encodeURIComponent(card.dataset.projectSlug)}/schema-sync/create-missing`,{tables,confirm:result.value});await load();Swal.fire('Tables created',d.message,'success')}catch(err){Swal.fire('Creation failed',err.message,'error')}finally{busy(e.currentTarget,false)}});
})();
