(function(){
var ncCsrf='';
var ncSelectedSvc={};
var ncPendingPinAction=null;
var ncPinDigits=[];

function init(){
    var csrfMeta=document.querySelector('meta[name="csrf-token"]');
    ncCsrf=csrfMeta?csrfMeta.content:'';
    document.querySelectorAll('[id^="nc-svc-"]').forEach(function(grid){
        var first=grid.querySelector('.badge');
        if(first)ncSelectSvc(first);
    });
}

function ncSelectSvc(el){
    var node=el.dataset.node;
    ncSelectedSvc[node]=el.dataset.svc;
}

window.ncSelectSvcDropdown = function(node, svc) {
    ncSelectedSvc[node] = svc;
};

function ncGetSvc(node){return ncSelectedSvc[node]||'';}

function ncLog(node,text,cls){
    var modal=document.getElementById('fleet-terminal-modal');
    var out=document.getElementById('fleet-terminal-output');
    var title=document.getElementById('term-modal-title');
    if(!modal||!out)return;
    
    if (modal.style.display === 'none') {
        out.innerHTML = '';
        title.textContent = 'Terminal: ' + node;
        modal.style.display = 'flex';
    }
    
    var ts=new Date().toLocaleTimeString();
    var line=document.createElement('div');
    var d=document.createElement('div');
    d.textContent=text;
    var safe=d.innerHTML;
    
    var classStr = cls ? cls : 'term-result';
    if(cls === 'nc-ok') classStr = 'term-line';
    if(cls === 'nc-err') classStr = 'term-error';
    if(cls === 'nc-ts') classStr = 'term-result';
    
    line.innerHTML='<span style="color:var(--text-dim);">['+ts+']</span> '+(classStr?'<span class="'+classStr+'">':'')+safe+(classStr?'</span>':'');
    out.appendChild(line);
    out.scrollTop=out.scrollHeight;
}

function ncCmd(node,action,extra){
    var svc=ncGetSvc(node);
    var needsSvc=['service_status','service_restart','service_stop','service_start','logs_tail'].indexOf(action)!==-1;
    if(needsSvc&&!svc){ncLog(node,'Select a service first.','nc-err');return;}
    ncLog(node,'> executing: '+action+(svc?' -> '+svc:''),'');
    
    var fd=new FormData();
    fd.set('_csrf',ncCsrf);
    fd.set('action',action);
    fd.set('node',node);
    if(svc)fd.set('service',svc);
    if(extra){Object.keys(extra).forEach(function(k){fd.set(k,extra[k]);});}
    
    fetch('api/fleet/node_cmd.php',{method:'POST',body:fd,credentials:'same-origin'})
    .then(function(r){return r.json();})
    .then(function(data){
        if(data.needs_pin){
            ncLog(node,'Fleet PIN required for: '+action,'nc-err');
            ncPendingPinAction={node:node,action:action,extra:extra||{}};
            if(svc)ncPendingPinAction.extra.service=svc;
            ncShowPinModal(action);
            return;
        }
        if(data.ok){
            ncLog(node,data.output||'OK','nc-ok');
            var meta='-- completed in '+(data.elapsed||'?');
            if(data.route)meta+=' | route: '+data.route;
            ncLog(node,meta,'nc-ts');
        }else{
            ncLog(node,(data.output||data.error||'Command failed'),'nc-err');
            if(data.route)ncLog(node,'route: '+data.route,'nc-ts');
        }
        ncUpdateDot(node,data.ok);
    })
    .catch(function(e){ncLog(node,'Request failed: '+e.message,'nc-err');});
}

function ncShowPinModal(actionName){
    ncPinDigits=[];
    var label=document.getElementById('ncPinActionLabel');
    if(label) label.textContent='Authorize: '+actionName;
    document.querySelectorAll('.nc-pin-dot').forEach(function(d){d.classList.remove('filled');});
    var overlay=document.getElementById('ncFleetPinOverlay');
    if(overlay) overlay.style.display='flex';
    ncRenderPinGrid();
}

function ncClosePinModal(){
    var overlay=document.getElementById('ncFleetPinOverlay');
    if(overlay) overlay.style.display='none';
    ncPendingPinAction=null;
    ncPinDigits=[];
}

function ncRenderPinGrid(){
    var grid=document.getElementById('ncPinGrid');
    if(!grid)return;
    grid.innerHTML='';
    var digits=[0,1,2,3,4,5,6,7,8,9];
    for(var i=digits.length-1;i>0;i--){
        var j=Math.floor(Math.random()*(i+1));
        var tmp=digits[i];digits[i]=digits[j];digits[j]=tmp;
    }
    for(var i=0;i<9;i++){
        (function(d){
            var btn=document.createElement('button');
            btn.type='button';btn.className='nc-pin-key';btn.textContent=d;
            btn.addEventListener('click',function(){ncPinTap(d);});
            grid.appendChild(btn);
        })(digits[i]);
    }
    var clr=document.createElement('button');
    clr.type='button';clr.className='nc-pin-key';clr.textContent='C';
    clr.style.fontSize='14px';clr.style.color='#ff5252';
    clr.addEventListener('click',function(){ncPinDigits=[];document.querySelectorAll('.nc-pin-dot').forEach(function(d){d.classList.remove('filled');});ncRenderPinGrid();});
    grid.appendChild(clr);
    
    (function(d){
        var last=document.createElement('button');
        last.type='button';last.className='nc-pin-key';last.textContent=d;
        last.addEventListener('click',function(){ncPinTap(d);});
        grid.appendChild(last);
    })(digits[9]);
    
    var ok=document.createElement('button');
    ok.type='button';ok.className='nc-pin-key';ok.textContent='>';
    ok.style.color='#2d6a4f';ok.style.fontSize='18px';
    ok.addEventListener('click',ncPinSubmit);
    grid.appendChild(ok);
}

function ncPinTap(digit){
    if(ncPinDigits.length>=4)return;
    ncPinDigits.push(digit);
    document.querySelectorAll('.nc-pin-dot').forEach(function(d,i){d.classList.toggle('filled',i<ncPinDigits.length);});
    ncRenderPinGrid();
}

function ncPinSubmit(){
    if(ncPinDigits.length!==4||!ncPendingPinAction)return;
    var pin=ncPinDigits.join('');
    var p=ncPendingPinAction;
    ncClosePinModal();
    var merged={};
    if(p.extra){Object.keys(p.extra).forEach(function(k){merged[k]=p.extra[k];});}
    merged.fleet_pin=pin;
    ncCmd(p.node,p.action,merged);
}

function ncToggleSSH(node){
    var btn=document.getElementById('nc-ssh-'+node);
    if(!btn)return;
    ncLog(node,'Checking SSH port status...','');
    var fd=new FormData();
    fd.set('_csrf',ncCsrf);
    fd.set('action','ssh_status');
    fd.set('node',node);
    fetch('api/fleet/node_cmd.php',{method:'POST',body:fd,credentials:'same-origin'})
    .then(function(r){return r.json();})
    .then(function(data){
        var output=(data.output||'').trim();
        var isOpen=output.indexOf('OPEN')===0;
        ncLog(node,'SSH Status: '+output,isOpen?'nc-ok':'');
        var msg=isOpen?'CLOSE SSH access on '+node+'?':'OPEN SSH access on '+node+' for 30 minutes?';
        if(!confirm(msg))return;
        ncLog(node,(isOpen?'Closing':'Opening')+' SSH port...','');
        var fd2=new FormData();
        fd2.set('_csrf',ncCsrf);
        fd2.set('action',isOpen?'ssh_close':'ssh_open');
        fd2.set('node',node);
        if(!isOpen)fd2.set('fleet_pin','');
        fetch('api/fleet/node_cmd.php',{method:'POST',body:fd2,credentials:'same-origin'})
        .then(function(r){return r.json();})
        .then(function(data2){
            if(data2.needs_pin){
                ncPendingPinAction={node:node,action:'ssh_open',extra:{}};
                ncShowPinModal('ssh_open');
                return;
            }
            if(data2.ok){
                ncLog(node,data2.output||'Done','nc-ok');
            }else{
                ncLog(node,data2.output||data2.error||'Failed','nc-err');
            }
        });
    })
    .catch(function(e){ncLog(node,'Toggle failed: '+e.message,'nc-err');});
}

function ncUpdateDot(node,ok){
    var dot=document.getElementById('nc-dot-'+node);
    if(!dot)return;
    dot.className='badge badge-'+(ok?'ok':'danger');
    dot.textContent = ok ? 'online' : 'offline';
}

document.addEventListener('click',function(e){
    var el=e.target.closest('[data-nc]');
    if(!el)return;
    var nc=el.dataset.nc;
    switch(nc){
        case 'ssh':ncToggleSSH(el.dataset.node);break;
        case 'svc':ncSelectSvc(el);break;
        case 'cmd':ncCmd(el.dataset.node,el.dataset.cmd);break;
        case 'cmd-confirm':if(confirm(el.dataset.confirm))ncCmd(el.dataset.node,el.dataset.cmd);break;
        case 'pin-overlay':if(e.target===el)ncClosePinModal();break;
        case 'pin-close':ncClosePinModal();break;
    }
});

if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',init);}
else{init();}
})();
