function qs(name) {
  return new URLSearchParams(location.search).get(name);
}

function card(label, value) {
  return `<div class="card"><div class="label">${escapeHtml(label)}</div><div class="value">${escapeHtml(String(value))}</div></div>`;
}

function sevName(s) {
  if (s === 2 || s === 'Critical') return 'Critical';
  if (s === 1 || s === 'Warning') return 'Warning';
  return 'Normal';
}

function sevClass(s) {
  const n = sevName(s);
  return n === 'Critical' ? 'crit' : n === 'Warning' ? 'warn' : 'ok';
}

/** Formats a whole number of seconds as "Xd Yh Zm" (drops leading zero units). */
function fmtUptime(seconds) {
  if (seconds == null || seconds < 0) return '—';
  const s = Math.floor(seconds);
  const days = Math.floor(s / 86400);
  const hours = Math.floor((s % 86400) / 3600);
  const minutes = Math.floor((s % 3600) / 60);
  const parts = [];
  if (days) parts.push(days + 'd');
  if (days || hours) parts.push(hours + 'h');
  parts.push(minutes + 'm');
  return parts.join(' ');
}

function avStatusClass(av) {
  if (av.enabled === false) return 'crit';
  if (av.upToDate === false) return 'warn';
  if (av.enabled == null && av.upToDate == null) return 'muted';
  return 'ok';
}

function avStatusLabel(av) {
  if (av.enabled === false) return 'Deaktiviert';
  if (av.upToDate === false) return 'Veraltet';
  if (av.enabled == null && av.upToDate == null) return 'Unbekannt';
  return 'Aktiv';
}

let lastSnapshot = null;

function render(s) {
  lastSnapshot = s;
  document.getElementById('title').textContent = s.displayName || s.hostName || s.deviceId;
  document.getElementById('subtitle').textContent =
    `${s.hostName || ''} · Agent ${s.agentVersion || ''} · ${s.updatedUtc ? new Date(s.updatedUtc).toLocaleString() : ''}`;

  const q = s.quicklook || {};
  document.getElementById('quicklook').innerHTML =
    card('CPU', fmt(q.cpuLoad, '%')) +
    card('RAM', fmt(q.memoryLoad, '%')) +
    card('Temp', fmt(q.cpuTempCelsius, '°C')) +
    card('Disk', fmt(q.worstDiskUsedPercent, '%')) +
    card('SSD Wear', fmt(q.maxSsdWearPercent, '%'));

  const inv = s.inventory || {};
  const disks = (s.disks || []).map(d =>
    `<tr><td>${escapeHtml(d.name)}</td><td>${escapeHtml(d.label)}</td><td>${escapeHtml(d.driveType || '')}</td><td>${escapeHtml(d.fileSystem || '')}</td><td>${d.totalGb ? fmt(d.totalGb, ' GB') : '—'}</td><td>${fmt(d.usedPercent, '%')}</td><td>${fmt(d.freeGb, ' GB')}</td></tr>`
  ).join('');

  const ssdWearRows = (s.ssdWear || []).map(w =>
    `<tr><td>${escapeHtml(w.deviceName)}</td><td>${w.driveIndex}</td><td>${fmt(w.wearPercent, '%')}</td></tr>`
  ).join('');

  const services = (s.services || []).slice(0, 40).map(svc =>
    `<tr><td>${escapeHtml(svc.displayName)}</td><td>${escapeHtml(svc.serviceName)}</td><td>${escapeHtml(svc.status)}</td><td>${escapeHtml(svc.startMode)}</td></tr>`
  ).join('');

  const findings = (s.healthFindings || []).map(f =>
    `<li class="${sevClass(f.severity)}"><strong>${escapeHtml(f.headline)}</strong><div class="muted">${escapeHtml(f.detail)}</div></li>`
  ).join('');

  const errors = (s.recentErrors || []).slice(0, 25).map(e =>
    `<tr><td>${escapeHtml(e.logName)}</td><td>${escapeHtml(e.source)}</td><td>${e.eventId}</td><td>${escapeHtml(e.message)}</td></tr>`
  ).join('');

  const wu = s.windowsUpdate || {};
  const titles = (wu.pendingTitles || []).map(t => `<li>${escapeHtml(t)}</li>`).join('');

  const netRows = (s.networkAdapters || []).map(n =>
    `<tr><td>${escapeHtml(n.name)}</td><td>${escapeHtml(n.description || '')}</td><td class="mono">${escapeHtml(n.macAddress || '')}</td><td>${escapeHtml(n.status || '')}</td><td>${n.speedMbps ? n.speedMbps + ' Mbit/s' : '—'}</td><td>${escapeHtml((n.ipv4Addresses || []).join(', '))}</td></tr>`
  ).join('');

  const processRows = (s.topProcesses || []).map(p =>
    `<tr><td>${escapeHtml(p.name)}</td><td>${p.pid}</td><td>${p.workingSetMb != null ? fmt(p.workingSetMb, ' MB') : '—'}</td></tr>`
  ).join('');

  const avRows = (s.antivirus || []).map(av =>
    `<tr><td>${escapeHtml(av.productName)}</td><td class="${avStatusClass(av)}">${avStatusLabel(av)}</td><td>${av.definitionsUtc ? new Date(av.definitionsUtc).toLocaleString() : '—'}</td></tr>`
  ).join('');

  document.getElementById('content').innerHTML = `
    <div class="panel">
      <div class="page-header page-header-compact">
        <h3 style="margin:0;">Inventar</h3>
        <button id="btnCopyInventory" type="button">Inventar als JSON kopieren</button>
      </div>
      <div class="cards">
        ${card('Betriebssystem', inv.osCaption || '—')}
        ${card('Build', [inv.osVersion, inv.osBuild].filter(Boolean).join(' · ') || '—')}
        ${card('Laufzeit', fmtUptime(inv.uptimeSeconds))}
        ${card('Letzter Neustart', inv.lastBootUtc ? new Date(inv.lastBootUtc).toLocaleString() : '—')}
        ${card('Domäne/Arbeitsgruppe', (inv.domainOrWorkgroup || '—') + (inv.isDomainJoined ? ' (Domäne)' : ''))}
        ${card('Hersteller / Modell', [inv.manufacturer, inv.model].filter(Boolean).join(' · ') || '—')}
        ${card('RAM', inv.totalRamGb ? fmt(inv.totalRamGb, ' GB') : '—')}
        ${card('CPUs (logisch)', inv.logicalProcessors ?? '—')}
        ${card('Angemeldeter Benutzer', inv.loggedOnUser || '—')}
        ${card('Primäre IP', inv.primaryIp || '—')}
        ${card('Agent-Version', s.agentVersion || '—')}
      </div>
    </div>
    <div class="panel">
      <h3>Verlauf</h3>
      <div class="form-actions" style="margin-top:0;margin-bottom:10px;">
        <button type="button" class="btn-range${historyRangeHours === 24 ? ' active' : ''}" data-hours="24">24h</button>
        <button type="button" class="btn-range${historyRangeHours === 168 ? ' active' : ''}" data-hours="168">7 Tage</button>
        <button type="button" class="btn-range${historyRangeHours === 720 ? ' active' : ''}" data-hours="720">30 Tage</button>
      </div>
      <canvas id="historyChart" width="900" height="220" style="width:100%;max-height:240px;"></canvas>
      <p class="muted" id="historyHint">Lade Verlauf…</p>
    </div>
    <div class="panel">
      <h3>Standort / Gruppe</h3>
      <form id="metaForm" class="form-grid">
        <label class="field">Standort<input id="metaSite" /></label>
        <label class="field">Gruppe<input id="metaGroup" /></label>
        <label class="field" style="grid-column:1/-1;">Tags<input id="metaTags" placeholder="prod, sql, floor2" /></label>
        <div class="actions"><button type="submit">Meta speichern</button>
          <button id="btnRemotePing" type="button">Remote-Aktion (Ping)</button></div>
      </form>
    </div>
    <div class="grid-2">
      <div class="panel">
        <h3>Gesundheit · ${sevName(s.overallSeverity)}</h3>
        <ul class="alerts">${findings || '<li class="muted">Keine Befunde</li>'}</ul>
      </div>
      <div class="panel">
        <h3>Windows Updates</h3>
        <p>${escapeHtml(wu.statusText || '')}</p>
        <p class="muted">Pending: ${wu.pendingCount ?? 0}${wu.rebootRequired ? ' · Reboot erforderlich' : ''}</p>
        <ul>${titles}</ul>
      </div>
    </div>
    <div class="panel">
      <h3>Speicherplatz</h3>
      <div class="table-wrap"><table><thead><tr><th>Laufwerk</th><th>Label</th><th>Typ</th><th>Dateisystem</th><th>Gesamt</th><th>Belegt</th><th>Frei</th></tr></thead><tbody>${disks || '<tr><td colspan=7 class=muted>—</td></tr>'}</tbody></table></div>
    </div>
    ${(s.ssdWear || []).length ? `
    <div class="panel">
      <h3>SSD-Verschleiß</h3>
      <div class="table-wrap"><table><thead><tr><th>Laufwerk</th><th>Index</th><th>Wear</th></tr></thead><tbody>${ssdWearRows}</tbody></table></div>
    </div>` : ''}
    <div class="panel">
      <h3>Netzwerkadapter</h3>
      <div class="table-wrap"><table><thead><tr><th>Name</th><th>Beschreibung</th><th>MAC</th><th>Status</th><th>Geschwindigkeit</th><th>IPv4</th></tr></thead><tbody>${netRows || '<tr><td colspan=6 class=muted>—</td></tr>'}</tbody></table></div>
    </div>
    <div class="panel">
      <h3>Top-Prozesse (Arbeitsspeicher)</h3>
      <div class="table-wrap"><table><thead><tr><th>Name</th><th>PID</th><th>Arbeitsspeicher</th></tr></thead><tbody>${processRows || '<tr><td colspan=3 class=muted>—</td></tr>'}</tbody></table></div>
    </div>
    <div class="panel">
      <h3>Antivirus</h3>
      <div class="table-wrap"><table><thead><tr><th>Produkt</th><th>Status</th><th>Definitionen</th></tr></thead><tbody>${avRows || '<tr><td colspan=3 class=muted>Kein Produkt gefunden</td></tr>'}</tbody></table></div>
    </div>
    <div class="panel">
      <h3>Dienste</h3>
      <div class="table-wrap"><table><thead><tr><th>Anzeigename</th><th>Name</th><th>Status</th><th>Start</th></tr></thead><tbody>${services || '<tr><td colspan=4 class=muted>—</td></tr>'}</tbody></table></div>
    </div>
    <div class="panel">
      <h3>Ereignisprotokolle (Fehler)</h3>
      <div class="table-wrap"><table><thead><tr><th>Log</th><th>Quelle</th><th>ID</th><th>Meldung</th></tr></thead><tbody>${errors || '<tr><td colspan=4 class=muted>—</td></tr>'}</tbody></table></div>
    </div>`;

  document.getElementById('metaForm').addEventListener('submit', saveMeta);
  document.getElementById('btnRemotePing').addEventListener('click', remotePing);
  const copyBtn = document.getElementById('btnCopyInventory');
  if (copyBtn) copyBtn.addEventListener('click', copyInventorySummary);
  document.querySelectorAll('.btn-range').forEach(btn => {
    btn.addEventListener('click', () => {
      historyRangeHours = Number(btn.getAttribute('data-hours')) || 24;
      document.querySelectorAll('.btn-range').forEach(b => b.classList.toggle('active', b === btn));
      loadHistory();
    });
  });
  loadHistory();
}

let historyRangeHours = 24;

function rangeLabel(hours) {
  if (hours <= 24) return '24h';
  if (hours <= 168) return '7 Tage';
  return '30 Tage';
}

async function loadHistory() {
  const id = qs('id');
  const hint = document.getElementById('historyHint');
  if (hint) hint.textContent = 'Lade Verlauf…';
  const res = await api('/api/devices/' + encodeURIComponent(id) + '/history?hours=' + historyRangeHours);
  if (!res.ok) {
    if (hint) hint.textContent = 'Kein Verlauf verfügbar.';
    return;
  }
  const points = await res.json();
  if (!hint) return;
  if (!points.length) {
    hint.textContent = 'Noch keine Verlaufspunkte für ' + rangeLabel(historyRangeHours) + '.';
    SpCharts.drawLineChart(document.getElementById('historyChart'), [], {});
    return;
  }
  hint.textContent = `${points.length} Messpunkte (${rangeLabel(historyRangeHours)}) · CPU / RAM / Temp`;
  drawHistory(document.getElementById('historyChart'), points);
}

function drawHistory(canvas, points) {
  if (!canvas) return;
  const showTime = historyRangeHours <= 24;
  const labels = points.map(p => {
    const d = new Date(p.recordedUtc);
    return showTime
      ? d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })
      : d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' });
  });

  SpCharts.drawLineChart(canvas, [
    { label: 'CPU %', color: SpCharts.cssVar('--accent', '#3d8bfd'), values: points.map(p => p.cpuLoad) },
    { label: 'RAM %', color: SpCharts.cssVar('--ok', '#3ecf8e'), values: points.map(p => p.memoryLoad) },
    { label: 'Temp °C', color: SpCharts.cssVar('--warn', '#e6a23c'), values: points.map(p => p.cpuTempCelsius) }
  ], { labels, unit: '', points: false });
}

async function copyInventorySummary() {
  if (!lastSnapshot) return;
  const inv = lastSnapshot.inventory || {};
  const summary = {
    deviceId: lastSnapshot.deviceId,
    displayName: lastSnapshot.displayName,
    hostName: lastSnapshot.hostName,
    agentVersion: lastSnapshot.agentVersion,
    osCaption: inv.osCaption,
    osVersion: inv.osVersion,
    osBuild: inv.osBuild,
    uptimeSeconds: inv.uptimeSeconds,
    lastBootUtc: inv.lastBootUtc,
    domainOrWorkgroup: inv.domainOrWorkgroup,
    isDomainJoined: inv.isDomainJoined,
    manufacturer: inv.manufacturer,
    model: inv.model,
    logicalProcessors: inv.logicalProcessors,
    totalRamGb: inv.totalRamGb,
    loggedOnUser: inv.loggedOnUser,
    primaryIp: inv.primaryIp,
    disks: (lastSnapshot.disks || []).map(d => ({ name: d.name, totalGb: d.totalGb, usedPercent: d.usedPercent })),
    networkAdapters: (lastSnapshot.networkAdapters || []).map(n => ({ name: n.name, mac: n.macAddress, ipv4: n.ipv4Addresses })),
    antivirus: (lastSnapshot.antivirus || []).map(av => ({ product: av.productName, enabled: av.enabled, upToDate: av.upToDate }))
  };

  try {
    await navigator.clipboard.writeText(JSON.stringify(summary, null, 2));
    alert('Inventar wurde in die Zwischenablage kopiert.');
  } catch (e) {
    alert('Kopieren fehlgeschlagen: ' + e.message);
  }
}

async function saveMeta(e) {
  e.preventDefault();
  const id = qs('id');
  const body = {
    site: document.getElementById('metaSite').value.trim() || null,
    groupName: document.getElementById('metaGroup').value.trim() || null,
    tags: document.getElementById('metaTags').value.trim() || null
  };
  const res = await api('/api/devices/' + encodeURIComponent(id) + '/meta', {
    method: 'PUT', body: JSON.stringify(body)
  });
  alert(res.ok ? 'Meta gespeichert.' : 'Speichern fehlgeschlagen.');
}

async function remotePing() {
  const id = qs('id');
  const res = await api('/api/devices/' + encodeURIComponent(id) + '/actions/ping-local', { method: 'POST' });
  const data = await res.json().catch(() => ({}));
  alert(res.ok ? (data.note || 'OK') : (data.error || 'Nicht erlaubt'));
}

async function refresh() {
  const id = qs('id');
  if (!id) {
    document.getElementById('content').innerHTML = '<p class="crit">Kein Gerät angegeben.</p>';
    return;
  }
  try {
    const res = await api('/api/devices/' + encodeURIComponent(id));
    if (!res.ok) throw new Error('Gerät nicht gefunden (' + res.status + ')');
    render(await res.json());
  } catch (e) {
    document.getElementById('content').innerHTML = `<p class="crit">${escapeHtml(e.message)}</p>`;
  }
}

async function removeDevice() {
  const id = qs('id');
  if (!id) return;
  const ok = await confirmDialog({
    title: 'Gerät entfernen',
    message: 'Gerät wirklich aus der Fleet entfernen?\nVerlauf und Alarme dieses Geräts werden mitgelöscht.',
    confirmLabel: 'Entfernen',
    danger: true
  });
  if (!ok) return;

  const res = await api('/api/devices/' + encodeURIComponent(id), { method: 'DELETE' });
  if (res.ok) {
    location.href = '/';
    return;
  }
  const data = await res.json().catch(() => ({}));
  alert(data.error || 'Entfernen fehlgeschlagen.');
}

async function init() {
  await initLocale();
  const nav = document.querySelector('.nav');
  if (nav) {
    const refreshBtn = document.getElementById('btnRefresh');
    const logoutBtn = document.getElementById('btnLogout');
    nav.innerHTML = chromeNav('fleet');
    if (refreshBtn) nav.appendChild(refreshBtn);
    if (logoutBtn) /* logout via chromeNav */
  }
  setActiveNav('fleet');
  document.getElementById('btnLogout').addEventListener('click', logout);
  document.getElementById('btnRefresh').addEventListener('click', refresh);
  document.getElementById('btnRemove').addEventListener('click', removeDevice);

  try {
    const me = await loadMe();
    if (me?.organizationName)
      document.getElementById('orgName').textContent = me.organizationName;
    if (me?.license) renderLicenseBanner(me.license);
    if (me?.role) applyRoleNav(me.role);
  } catch (_) {}

  await refresh();
}

init();
