/* Settings form stays mounted while status polling updates only status elements. */
let networkBusy=false, networkState=null;
async function networkRequest(action,body={}){
const response=await fetch('/api/v1/network'+(action?'/'+action:''),{method:action?'POST':'GET',headers:action?{'Content-Type':'application/json','X-Athena-Deck':'1'}:{},body:action?JSON.stringify(body):undefined,signal:AbortSignal.timeout(40000)});
const value=await response.json();if(response.status===401){location.reload();throw Error('Bitte erneut anmelden.')}if(!response.ok)throw Error(value.error||'Netzwerkaktion fehlgeschlagen.');return value;
}
async function networkAction(action,body={}){
if(networkBusy)return;networkBusy=true;networkButtons();
const output=document.querySelector('#network-message');output.textContent='Wird ausgeführt …';
try{await networkRequest(action,body);output.textContent=action==='import'?'Konfiguration geprüft und geschützt auf Athena gespeichert.':action==='install'?'Installation läuft. Der Status aktualisiert sich automatisch.':'Einstellung übernommen.';}
catch(e){output.textContent=e.message;}
finally{networkBusy=false;await networkPage();}
}
function networkButtons(){
if(!networkState)return;
const s=networkState;
document.querySelectorAll('#network-page button').forEach(b=>b.disabled=networkBusy||s.state==='installing');
const set=(id,disabled)=>{const b=document.getElementById(id);if(b)b.disabled=b.disabled||disabled;};
set('network-install',s.installed||s.install_supported===false);
set('network-import',!s.installed||s.enabled||s.mode!=='lan'||!!s.pending);
set('network-connect',!s.configured||s.enabled);
set('network-disconnect',!s.enabled);
set('network-delete',!s.configured||s.enabled||s.mode!=='lan'||!!s.pending);
set('network-apply',!s.installed||!!s.pending);
const needed=s.pending?.target==='lan'?'lan':'tunnel';
set('network-confirm',!s.pending||s.ingress!==needed);
set('network-cancel',!s.pending);
}
async function networkPage(){
const view=document.querySelector('#view');
if(!document.querySelector('#network-page')){
view.innerHTML=`
EINSTELLUNGEN / NETZWERK
Dein Weg zu Athena.
Ein eigener WireGuard-Zugang für Athena Deck und seine internen API-Endpunkte.
WireGuard-Modul
Wird geprüft …
Auf Athena einrichten
Installiert WireGuard und Deck in einem eigenen Container. Der vorhandene Gateway bleibt unverändert. Die erste Einrichtung startet im LAN-Modus auf Port 8110.
Vor der Installation kopieren und sicher speichern. Dieser Token gehört zur jeweiligen Server-Instanz.
Benötigt den vorhandenen SSH-Zugang und Docker auf Athena. LAN-Zugriff verwendet HTTP; für vertrauliche Eingaben WireGuard oder SSH-Tunnel verwenden.
Verwende einen eigenen Peer für Deck. Schlüssel werden nicht angezeigt. Ein Peer und IPv4 werden unterstützt; Shell-Hooks werden abgelehnt.
Aktivieren richtet den Tunnel ein. „Verbunden“ erscheint erst nach einem aktuellen Handshake.
Zugriff auf Deck und API
Öffne die angezeigte Zieladresse und bestätige dort innerhalb von 120 Sekunden. Ohne Bestätigung wird der vorige Modus wiederhergestellt.
Der SSH-Zugang zum Debian-Server bleibt als Verwaltungskanal erhalten. Produktionsendpunkte werden nicht umgestellt. Im Modus „Nur Tunnel“ gibt es bei Tunnelausfall keinen LAN-Fallback.
`;
document.querySelector('#network-install').onclick=()=>{const input=document.querySelector('#network-password'),password=input.value,token=document.querySelector('#network-api-token'),api_token=token.value;input.value='';token.value='';networkAction('install',{password,api_token});};
document.querySelector('#network-generate-token').onclick=()=>{document.querySelector('#network-api-token').value=accessToken();};
document.querySelector('#network-show-token').onclick=()=>{const input=document.querySelector('#network-api-token');input.type=input.type==='password'?'text':'password';document.querySelector('#network-show-token').textContent=input.type==='password'?'API-Token anzeigen':'API-Token verbergen';};
document.querySelector('#network-copy-token').onclick=async()=>{try{const token=document.querySelector('#network-api-token').value;if(!token)throw Error();await navigator.clipboard.writeText(token);document.querySelector('#network-message').textContent='API-Token kopiert. Bitte sicher speichern.';}catch{document.querySelector('#network-message').textContent='Kopieren nicht möglich. Bitte eigenen Token verwenden.'}};
document.querySelector('#network-import').onclick=async()=>{const input=document.querySelector('#network-file'),file=input.files[0];if(!file){document.querySelector('#network-message').textContent='Bitte zuerst eine .conf-Datei auswählen.';return}if(file.size>16384){document.querySelector('#network-message').textContent='Die Datei darf höchstens 16 KiB groß sein.';return}const config=await file.text();input.value='';await networkAction('import',{config});};
for(const action of ['connect','disconnect','delete','cancel'])document.querySelector('#network-'+action).onclick=()=>networkAction(action);
document.querySelector('#network-apply').onclick=()=>networkAction('mode',{mode:document.querySelector('#network-mode').value});
document.querySelector('#network-confirm').onclick=()=>networkAction('confirm',{trial_id:networkState?.pending?.id});
}
try{
const s=await networkRequest('');if(!document.querySelector('#network-page'))return;networkState=s;
const labels={'disabled-module':'Nicht angebunden',unavailable:'Nicht bereit',installing:'Installation läuft',disabled:'Deaktiviert',connecting:'Warte auf Handshake',connected:'Verbunden'};
document.querySelector('#network-state').textContent=labels[s.state]||'Nicht verfügbar';
const details=document.querySelector('#network-details');details.replaceChildren();
for(const [label,value] of [['Konfiguration',s.configured?'Gespeichert':'Keine'],['Letzter Handshake',s.latest_handshake?new Date(s.latest_handshake*1000).toLocaleString('de-DE'):'Noch keiner'],['Dieser Zugang',s.ingress==='management'?'SSH-Verwaltung':s.ingress==='tunnel'?'WireGuard-Tunnel':'LAN']]){const d=document.createElement('div'),small=document.createElement('small'),strong=document.createElement('strong');small.textContent=label;strong.textContent=value;d.append(small,strong);details.append(d);}
for(const [label,url] of [['LAN',s.lan_url],['Tunnel',s.tunnel_url]])if(url){const d=document.createElement('div'),a=document.createElement('a');a.href=url+'/#network';a.textContent=label+': '+url;a.target='_blank';a.rel='noopener';d.append(a);details.append(d);}
document.querySelector('#network-setup').hidden=!!s.installed;
document.querySelector('#network-config').hidden=false;
document.querySelector('#network-file').disabled=!s.installed||s.enabled||networkBusy;
document.querySelector('#network-access').hidden=false;
document.querySelector('#network-mode').disabled=!s.installed||!!s.pending||networkBusy;
document.querySelector('#network-notice').textContent=[s.error,s.job?.message,...(s.warnings||[])].filter(Boolean).join(' ');
document.querySelector('#network-current').textContent='Aktuell: '+({lan:'Nur lokales Netzwerk',tunnel:'Nur WireGuard-Tunnel',both:'Tunnel und LAN'}[s.mode]||'Noch nicht eingerichtet');
document.querySelector('#network-trial').hidden=!s.pending;
if(s.pending)document.querySelector('#network-countdown').textContent=`Test aktiv · ${s.pending.seconds_remaining} Sekunden bis zur automatischen Rücknahme. Bestätigung nötig über ${s.pending.target==='lan'?'LAN':'WireGuard'}.`;
networkButtons();
}catch(e){if(document.querySelector('#network-message'))document.querySelector('#network-message').textContent=e.message;}
}