{% extends "tesm_core/base.html" %}
{% from "tesm_core/macros.html" import pill, empty_state, alert, search_box %}

{% block page_title %}Wartung{% endblock %}
{% block page_sub %}
  {{ devices | length }} Geraete mit Zugangsdaten der Kategorie
  &bdquo;Linux-Client&ldquo; oder &bdquo;Windows-Client&ldquo;
{% endblock %}

{% block topbar_extra %}{{ search_box('maintenance-table', 'Geraet suchen ...') }}{% endblock %}

{% block content %}
{% if devices | rejectattr('host_key_ready') | list %}
  {{ alert('Fuer mindestens ein Geraet ist der SSH-Host-Schluessel noch nicht freigegeben.
  Die Wartung bricht dort mit "Schluessel unbekannt" ab. Die Freigabe erfolgt auf der
  Detailseite des Geraets -- erst auslesen, Fingerprint pruefen, dann freigeben.',
  'warning', 'Host-Schluessel offen') }}
{% endif %}

{% if windows_tool_missing %}
  {# Die Meldung im Auftrag nennt das fehlende Paket -- ohne diesen Knopf waere sie
     eine Sackgasse. #}
  <div class="alert alert--warning">
    {{ icon('alert', size=18) }}
    <div class="alert__body">
      <strong>Windows-Neustart nicht moeglich</strong>
      Auf diesem Server fehlt das Paket <code>{{ windows_package }}</code>. Es bringt
      <code>net</code> mit, ueber das der Neustart eines Windows-Geraetes laeuft.
    </div>
    <form method="post" action="{{ url_for('maintenance.install_windows_tool') }}">
      <input type="hidden" name="{{ csrf_field_name }}" value="{{ csrf_token() }}">
      <button class="btn btn--sm" type="submit"
              data-confirm="Paket {{ windows_package }} jetzt installieren?"
              data-confirm-title="Paket nachinstallieren" data-confirm-ok="Installieren">
        Nachinstallieren
      </button>
    </form>
  </div>
{% endif %}

{{ alert('Welche Geraete hier erscheinen und was mit ihnen moeglich ist, entscheidet die
Kategorie ihrer Zugangsdaten. Linux-Clients werden ueber SSH aktualisiert und neu gestartet.
Windows-Clients werden nur neu gestartet, und zwar ueber RPC (wie "shutdown /m") -- sie
brauchen dafuer weder SSH noch einen Host-Schluessel, sondern die offene Datei- und
Druckerfreigabe. Der PoE-Neustart ist davon getrennt: er schaltet den Switch-Port.',
'info') }}

<form method="post" id="maintenance-form" action="{{ url_for('maintenance.start_update') }}">
  <input type="hidden" name="{{ csrf_field_name }}" value="{{ csrf_token() }}">
  <section class="card">
    <div class="table-toolbar">
      <label class="check">
        <input type="checkbox" id="select-all">
        <span>Alle auswaehlen</span>
      </label>
      <span class="table-toolbar__spacer"></span>
      {% if current_user.has('maintenance.execute') %}
        <button class="btn btn--sm btn--primary" type="submit"
                formaction="{{ url_for('maintenance.start_update') }}"
                title="Nur fuer Linux-Clients -- Windows-Geraete werden dabei uebersprungen." 
                data-confirm="Paketaktualisierung auf den ausgewaehlten Geraeten starten?"
                data-confirm-title="Aktualisieren" data-confirm-ok="Starten" data-confirm-style="primary">
          {{ icon('download', size=15) }} Aktualisieren
        </button>
        <button class="btn btn--sm btn--danger" type="submit"
                formaction="{{ url_for('maintenance.start_reboot') }}"
                data-confirm="Die ausgewaehlten Geraete jetzt neu starten? Sie sind dabei kurzzeitig nicht erreichbar."
                data-confirm-title="Neustarten" data-confirm-ok="Neu starten">
          {{ icon('refresh', size=15) }} Neustarten
        </button>
      {% endif %}
    </div>

    <div class="table-wrap">
      <table class="table" id="maintenance-table" data-behavior="sortable">
        <thead>
          <tr>
            <th style="width:44px"></th>
            <th class="sortable">Geraet</th>
            <th class="sortable">IP</th>
            <th class="sortable">Zustand</th>
            <th class="sortable">Zugangsdaten</th>
            <th class="sortable">Host-Schluessel</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {% for device in devices %}
            <tr data-filter-text="{{ device.name }} {{ device.ip }} {{ device.credential_name }}">
              <td>
                <label class="check">
                  <input type="checkbox" name="device_ids" value="{{ device.id }}"
                         class="device-select" data-category="{{ device.category }}"
                         {% if not current_user.has('maintenance.execute') %}disabled{% endif %}>
                  <span class="sr-only">{{ device.name }} auswaehlen</span>
                </label>
              </td>
              <td class="fw-600">{{ device.name }}</td>
              <td class="mono fs-sm">{{ device.ip }}</td>
              <td>
                {% if device.state == 'online' %}{{ pill('online', 'online') }}
                {% elif device.state == 'offline' %}{{ pill('offline', 'offline') }}
                {% else %}{{ pill('unbekannt', 'warning') }}{% endif %}
              </td>
              <td class="fs-sm">
                {{ device.credential_name }}
                <div class="fs-xs faint">{{ category_labels.get(device.category, device.category) }}</div>
              </td>
              <td>
                {% if not device.ssh_managed %}
                  <span class="faint fs-xs" title="Windows wird ueber RPC verwaltet, nicht ueber SSH">
                    nicht noetig
                  </span>
                {% elif device.host_key_ready %}{{ pill('freigegeben', 'online') }}
                {% else %}
                  <a href="{{ url_for('devices.detail', device_id=device.id) }}"
                     title="Ohne freigegebenen Schluessel bricht die Wartung ab">
                    {{ pill('offen', 'danger') }}
                  </a>
                {% endif %}
              </td>
              <td class="nowrap">
                {% if terminal_enabled and device.ssh_managed
                      and current_user.has('maintenance.execute') %}
                  <a class="btn btn--sm btn--ghost"
                     href="{{ url_for('terminal.device_console', device_id=device.id) }}">
                    {{ icon('terminal', size=14) }} Konsole
                  </a>
                {% endif %}
              </td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
    {% if not devices %}
      {{ empty_state('Keine passenden Geraete',
                     'Setzen Sie bei den Zugangsdaten die Kategorie "Linux-Client" und ordnen Sie
                     sie einem Geraet zu.', 'wrench') }}
    {% endif %}
  </section>
</form>

{# Kein data-refresh-url: die Schleife in app.js schreibt die Antwort in
   innerHTML. Hier zeigte sie auf die Seite selbst -- die komplette
   Wartungsseite landete damit in dieser Karte, mitsamt Seitenleiste und
   Suchfeld. Aktualisiert wird ueber die Abfrage unten, die bei laufenden
   Auftraegen die ganze Seite neu laedt. #}
<section class="card" id="jobs">
  <div class="card__header">
    <div class="flex-1">
      <div class="card__title">{{ icon('clock', size=17) }} Auftraege</div>
      <div class="card__sub">
        Zustand liegt in der Datenbank -- ein Dienst-Neustart verliert ihn nicht mehr
      </div>
    </div>
  </div>
  {% if jobs %}
    <div class="table-wrap">
      <table class="table table--compact">
        <thead><tr><th>Gestartet</th><th>Geraet</th><th>Art</th><th>Zustand</th><th>Fortschritt</th><th>Meldung</th></tr></thead>
        <tbody>
          {% for job in jobs %}
            <tr>
              <td class="fs-sm nowrap">{{ job.created_at | dt }}</td>
              <td class="fs-sm fw-600">
                <a href="{{ url_for('maintenance.job_detail', job_id=job.id) }}">{{ job.subject }}</a>
              </td>
              <td class="fs-sm">{{ 'Aktualisierung' if job.kind.endswith('update') else 'Neustart' }}</td>
              <td>
                {% if job.state == 'succeeded' %}{{ pill('erfolgreich', 'online') }}
                {% elif job.state == 'failed' %}{{ pill('fehlgeschlagen', 'danger') }}
                {% elif job.state == 'running' %}{{ pill('laeuft', 'info') }}
                {% elif job.state == 'unknown' %}{{ pill('unklar', 'warning') }}
                {% else %}{{ pill('wartet', '') }}{% endif %}
              </td>
              <td style="min-width:120px">
                <div class="progress {{ 'progress--success' if job.state == 'succeeded' else ('progress--danger' if job.state == 'failed' else '') }}">
                  <div class="progress__bar" style="width: {{ job.progress }}%"></div>
                </div>
              </td>
              <td class="fs-xs muted">{{ job.message }}</td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
  {% else %}
    {{ empty_state('Keine Auftraege', 'Es wurde noch keine Wartung gestartet.', 'clock') }}
  {% endif %}
</section>
{% endblock %}

{% block scripts %}
<script type="module" nonce="{{ csp_nonce }}">
  // Auswahl beim Laden bewusst zuruecksetzen: Browser stellen den Checked-Zustand
  // sonst aus dem Verlauf wieder her -- und dann wird bei "Neustarten"
  // versehentlich das falsche Geraet erwischt.
  const boxes = Array.from(document.querySelectorAll(".device-select"));
  boxes.forEach((box) => (box.checked = false));

  const all = document.getElementById("select-all");
  all?.addEventListener("change", () => {
    boxes.filter((box) => !box.disabled && !box.closest("tr").hidden)
         .forEach((box) => (box.checked = all.checked));
  });

  // Auftragsliste nachladen, solange etwas laeuft.
  async function poll() {
    try {
      const state = await window.tesm.api("{{ url_for('maintenance.status') }}");
      if (state.running) window.setTimeout(() => location.reload(), state.poll_ms);
    } catch {
      /* stumm bleiben -- die Seite ist auch ohne Aktualisierung nutzbar */
    }
  }
  poll();
</script>
{% endblock %}
