<!doctype html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Wecker Remote</title>
  <style>
    :root {
      color-scheme: dark;
      --bg: #111827;
      --surface: #1f2937;
      --surface-2: #374151;
      --text: #f9fafb;
      --ok: #22c55e;
      --warn: #f59e0b;
      --error: #ef4444;
      --accent: #3b82f6;
    }
    * { box-sizing: border-box; }
    body {
      margin: 0;
      font-family: Arial, sans-serif;
      background: var(--bg);
      color: var(--text);
      padding: 16px;
    }
    .wrap {
      max-width: 980px;
      margin: 0 auto;
      display: grid;
      gap: 16px;
    }
    .card {
      background: var(--surface);
      border: 1px solid #4b5563;
      border-radius: 10px;
      padding: 14px;
    }
    h1, h2 {
      margin: 0 0 10px;
      font-weight: 700;
    }
    h1 { font-size: 1.4rem; }
    h2 { font-size: 1.1rem; }
    .row {
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
      align-items: center;
    }
    label {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      font-size: 0.95rem;
    }
    input, button {
      border-radius: 8px;
      border: 1px solid #6b7280;
      background: var(--surface-2);
      color: var(--text);
      padding: 8px 10px;
      font-size: 0.95rem;
    }
    input[type="number"] {
      width: 90px;
    }
    button {
      cursor: pointer;
      border-color: #4b5563;
    }
    button:hover {
      border-color: var(--accent);
    }
    .primary {
      background: var(--accent);
      border-color: transparent;
    }
    .danger {
      background: var(--error);
      border-color: transparent;
    }
    .status {
      font-size: 0.9rem;
      padding: 4px 10px;
      border-radius: 999px;
      border: 1px solid #4b5563;
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }
    .status-dot {
      width: 8px;
      height: 8px;
      border-radius: 999px;
      background: #9ca3af;
    }
    .status.connected .status-dot { background: var(--ok); }
    .status.connecting .status-dot { background: var(--warn); }
    .status.disconnected .status-dot { background: var(--error); }
    table {
      width: 100%;
      border-collapse: collapse;
      font-size: 0.95rem;
    }
    th, td {
      text-align: left;
      border-bottom: 1px solid #4b5563;
      padding: 8px 6px;
    }
    .mono {
      font-family: Consolas, monospace;
    }
    .muted {
      color: #9ca3af;
      font-size: 0.9rem;
    }
    #log {
      margin: 0;
      max-height: 200px;
      overflow: auto;
      background: #0b1220;
      border: 1px solid #4b5563;
      border-radius: 8px;
      padding: 10px;
      font-family: Consolas, monospace;
      font-size: 0.85rem;
      line-height: 1.4;
      white-space: pre-wrap;
    }
  </style>
</head>
<body>
  <main class="wrap">
    <section class="card">
      <h1>Wecker Remote Steuerung</h1>
      <div class="row" style="margin-bottom: 10px;">
        <span id="connState" class="status disconnected">
          <span class="status-dot"></span>
          <span id="connText">Getrennt</span>
        </span>
        <span class="muted">Steuert `/wecker/html` ueber WebSocket-Bruecke.</span>
      </div>
      <div class="row">
        <label>WebSocket URL:
          <input id="wsUrl" type="text" style="min-width: 360px;">
        </label>
        <button id="btnConnect" class="primary">Verbinden</button>
        <button id="btnRefresh">Aktualisieren</button>
      </div>
    </section>

    <section class="card">
      <h2>Aktiver Alarm</h2>
      <div class="row" style="margin-bottom: 10px;">
        <button id="btnStop" class="danger">Alarm stoppen</button>
        <label>Snooze (Minuten):
          <input id="snoozeMinutes" type="number" min="1" max="60" value="5">
        </label>
        <button id="btnSnooze">Snooze senden</button>
      </div>
      <div id="alarmInfo" class="muted">Noch keine Daten.</div>
    </section>

    <section class="card">
      <h2>Weckerliste</h2>
      <table>
        <thead>
          <tr>
            <th>ID</th>
            <th>Zeit</th>
            <th>Wiederholung</th>
            <th>Status</th>
            <th>Aktion</th>
          </tr>
        </thead>
        <tbody id="alarmTable">
          <tr><td colspan="5" class="muted">Keine Daten geladen.</td></tr>
        </tbody>
      </table>
    </section>

    <section class="card">
      <h2>Log</h2>
      <pre id="log"></pre>
    </section>
  </main>

  <script>
    const els = {
      wsUrl: document.getElementById('wsUrl'),
      connState: document.getElementById('connState'),
      connText: document.getElementById('connText'),
      btnConnect: document.getElementById('btnConnect'),
      btnRefresh: document.getElementById('btnRefresh'),
      btnStop: document.getElementById('btnStop'),
      btnSnooze: document.getElementById('btnSnooze'),
      snoozeMinutes: document.getElementById('snoozeMinutes'),
      alarmInfo: document.getElementById('alarmInfo'),
      alarmTable: document.getElementById('alarmTable'),
      log: document.getElementById('log')
    };

    const state = {
      socket: null,
      reconnectTimer: null,
      manualDisconnect: false,
      alarms: [],
      ringing: null
    };

    function defaultWsUrl() {
      const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
      const host = 'njs.piclock.cylone-network.com';
      return `${proto}//${host}:8080/ws`;
    }

    function appendLog(msg) {
      const ts = new Date().toLocaleTimeString('de-DE');
      els.log.textContent = `[${ts}] ${msg}\n` + els.log.textContent;
    }

    function setConnectionStatus(mode, text) {
      els.connState.className = `status ${mode}`;
      els.connText.textContent = text;
    }

    function send(type, payload = {}) {
      if (!state.socket || state.socket.readyState !== WebSocket.OPEN) {
        appendLog('Senden fehlgeschlagen: keine Verbindung');
        return;
      }
      state.socket.send(JSON.stringify({ type, ...payload }));
    }

    function renderAlarms() {
      const alarms = Array.isArray(state.alarms) ? state.alarms : [];
      if (alarms.length === 0) {
        els.alarmTable.innerHTML = '<tr><td colspan="5" class="muted">Keine Wecker gefunden.</td></tr>';
        return;
      }

      const rows = alarms.map((alarm) => {
        const id = Number(alarm.id || 0);
        const active = Number(alarm.aktiv || 0) === 1;
        const zeit = String(alarm.weckzeit || '').slice(0, 5);
        const wiederholung = String(alarm.wiederholung || '-');
        const statusText = active ? 'Aktiv' : 'Inaktiv';
        const btnText = active ? 'Deaktivieren' : 'Aktivieren';
        const nextActive = active ? 0 : 1;
        return `
          <tr>
            <td class="mono">${id}</td>
            <td class="mono">${zeit || '--:--'}</td>
            <td>${wiederholung}</td>
            <td>${statusText}</td>
            <td>
              <button data-toggle-id="${id}" data-toggle-active="${nextActive}">${btnText}</button>
            </td>
          </tr>
        `;
      }).join('');

      els.alarmTable.innerHTML = rows;
      els.alarmTable.querySelectorAll('button[data-toggle-id]').forEach((btn) => {
        btn.addEventListener('click', () => {
          const id = Number(btn.getAttribute('data-toggle-id'));
          const aktiv = Number(btn.getAttribute('data-toggle-active')) === 1;
          send('toggle', { id, aktiv });
        });
      });
    }

    function renderAlarmState() {
      const alarm = state.ringing;
      if (!alarm || !alarm.ok) {
        els.alarmInfo.textContent = 'Noch keine Daten.';
        return;
      }

      const ringing = alarm.ringing ? 'Ja' : 'Nein';
      const id = alarm.alarm_id ?? '-';
      const zeit = alarm.alarm_time ?? '-';
      const text = alarm.tts_text || '-';
      els.alarmInfo.innerHTML = `
        <div><strong>Klingelt:</strong> ${ringing}</div>
        <div><strong>Alarm-ID:</strong> <span class="mono">${id}</span></div>
        <div><strong>Zeit:</strong> <span class="mono">${zeit}</span></div>
        <div><strong>TTS:</strong> ${text}</div>
      `;
    }

    function connect() {
      const url = (els.wsUrl.value || '').trim();
      if (!url) {
        appendLog('Bitte WebSocket-URL angeben.');
        return;
      }

      if (state.socket && state.socket.readyState === WebSocket.OPEN) {
        state.manualDisconnect = true;
        state.socket.close();
      }

      setConnectionStatus('connecting', 'Verbinde...');
      appendLog(`Verbinde zu ${url}`);

      const ws = new WebSocket(url);
      state.socket = ws;
      state.manualDisconnect = false;

      ws.addEventListener('open', () => {
        setConnectionStatus('connected', 'Verbunden');
        appendLog('Verbindung hergestellt.');
        send('get_state');
      });

      ws.addEventListener('message', (event) => {
        let data;
        try {
          data = JSON.parse(event.data);
        } catch {
          appendLog(`Ungueltige Nachricht: ${event.data}`);
          return;
        }

        if (data.type === 'list') {
          state.alarms = data.payload?.wecker || [];
          renderAlarms();
          return;
        }

        if (data.type === 'alarm_state') {
          state.ringing = data.payload || null;
          renderAlarmState();
          return;
        }

        if (data.type === 'action_result') {
          appendLog(`Aktion "${data.action}" erfolgreich.`);
          return;
        }

        if (data.type === 'error') {
          appendLog(`Fehler: ${data.message || 'unbekannt'}`);
          return;
        }

        if (data.type === 'connected') {
          appendLog(`Server: ${data.payload?.message || 'verbunden'}`);
          return;
        }

        appendLog(`Info: ${JSON.stringify(data)}`);
      });

      ws.addEventListener('close', () => {
        setConnectionStatus('disconnected', 'Getrennt');
        appendLog('Verbindung geschlossen.');
        if (!state.manualDisconnect) {
          clearTimeout(state.reconnectTimer);
          state.reconnectTimer = setTimeout(connect, 2000);
        }
      });

      ws.addEventListener('error', () => {
        appendLog('WebSocket Fehler.');
      });
    }

    els.wsUrl.value = defaultWsUrl();

    els.btnConnect.addEventListener('click', connect);
    els.btnRefresh.addEventListener('click', () => send('get_state'));
    els.btnStop.addEventListener('click', () => send('stop_alarm'));
    els.btnSnooze.addEventListener('click', () => {
      const minutes = Number(els.snoozeMinutes.value || 5);
      send('snooze', { minutes });
    });

    connect();
  </script>
</body>
</html>
