'use strict';

// ── DOM-Referenzen ────────────────────────────────────────────────────────────

const btnRun       = document.getElementById('btn-homing-run');
const btnSend      = document.getElementById('btn-homing-send');
const statusBadge  = document.getElementById('homing-status');
const progressDiv  = document.getElementById('homing-progress');
const progressBar  = document.getElementById('homing-progress-bar');
const progressText = document.getElementById('homing-progress-text');
const logEl        = document.getElementById('log-homing');
const analysisEl   = document.getElementById('homing-analysis');
const resultJson   = document.getElementById('homing-result-json');
const resultTree   = document.getElementById('homing-result-tree');
const csvInfo      = document.getElementById('homing-csv-info');
const csvTable     = document.getElementById('homing-csv-table');
const snapshots    = document.getElementById('homing-snapshots');

let _lastState = null;   // letztes Homing-Ergebnis (zum Senden an Roboter)

// ── Hilfsfunktionen ───────────────────────────────────────────────────────────

function appendLog(text) {
  logEl.value += (text ?? '') + '\n';
  logEl.scrollTop = logEl.scrollHeight;
}

function appendAnalysis(key, value) {
  const line = key + ':\n' + JSON.stringify(value, null, 2);
  analysisEl.value += line + '\n\n';
  analysisEl.scrollTop = analysisEl.scrollHeight;
}

function setStatus(label, cls) {
  statusBadge.textContent = label;
  statusBadge.className   = `status-badge ${cls}`;
}

function setProgress(step, total, text) {
  progressDiv.style.display = 'block';
  const pct = total > 0 ? Math.round((step / total) * 100) : 0;
  progressBar.style.width  = pct + '%';
  progressText.textContent = text || `Schritt ${step} / ${total}`;
}

/** Zeigt { x_mm, y_deg, z_deg, a_deg, b_deg, c_deg, e_mm } im Result-Bereich. */
function showResult(state) {
  // Raw JSON
  resultJson.value = JSON.stringify(state, null, 2);

  // Tree View
  const LABELS = {
    x_mm:  'x (Slider)',
    y_deg: 'y (Arm1)',
    z_deg: 'z (Ellbow)',
    a_deg: 'a (Arm2)',
    b_deg: 'b (Hand)',
    c_deg: 'c (Palm)',
    e_mm:  'e (Greifer)',
  };
  const UNITS = {
    x_mm: 'mm', y_deg: '°', z_deg: '°',
    a_deg: '°', b_deg: '°', c_deg: '°', e_mm: 'mm',
  };

  let html = '';
  for (const [key, val] of Object.entries(state)) {
    const label  = LABELS[key] ?? key;
    const unit   = UNITS[key]  ?? '';
    const valStr = typeof val === 'number' ? val.toFixed(2) : String(val ?? '–');
    html += `<div style="display:flex;gap:8px;padding:2px 0">
      <span style="min-width:130px;color:var(--muted)">${label}</span>
      <span style="font-weight:600">${valStr}&thinsp;${unit}</span>
    </div>`;
  }
  resultTree.innerHTML = html || '<span style="color:var(--muted)">–</span>';
}

/** Baut die CSV-Tabelle aus aruco_marker_poses.json-Daten. */
function showMarkerTable(markers) {
  if (!markers || markers.length === 0) {
    csvInfo.textContent = 'Keine Marker-Daten vorhanden.';
    csvTable.innerHTML  = '';
    return;
  }
  csvInfo.textContent = `${markers.length} Marker trianguliert`;

  const hdrs = ['ID', 'Link', 'Set', 'x mm', 'y mm', 'z mm', 'Kameras'];
  const style = 'padding:4px 8px;border:1px solid var(--border);text-align:right';
  const styleL = 'padding:4px 8px;border:1px solid var(--border);text-align:left';

  let html = `<thead><tr>${hdrs.map(h =>
    `<th style="${h==='Link'||h==='Set'||h==='ID'?styleL:style}">${h}</th>`).join('')}</tr></thead><tbody>`;

  for (const m of markers) {
    const pos = m.position_mm ?? [null, null, null];
    const fmt = v => (v != null ? Number(v).toFixed(1) : '–');
    html += `<tr>
      <td style="${styleL}">${m.marker_id}</td>
      <td style="${styleL}">${m.link ?? '–'}</td>
      <td style="${styleL}">${m.set  ?? '–'}</td>
      <td style="${style}">${fmt(pos[0])}</td>
      <td style="${style}">${fmt(pos[1])}</td>
      <td style="${style}">${fmt(pos[2])}</td>
      <td style="${style}">${m.num_cameras ?? '–'}</td>
    </tr>`;
  }
  html += '</tbody>';
  csvTable.innerHTML = html;
}

/** Lädt Debug-Bilder und Marker-Tabelle für einen Homing-Run. */
async function loadRunData(runDir) {
  try {
    const res = await fetch(`/api/homing/run-data?run=${encodeURIComponent(runDir)}`);
    if (!res.ok) return;
    const data = await res.json();

    // Snapshots
    snapshots.innerHTML = '';
    for (const img of (data.images ?? [])) {
      const figure = document.createElement('figure');
      figure.style.cssText = 'margin:0;display:flex;flex-direction:column;gap:4px';
      const el = document.createElement('img');
      el.src   = `data:image/jpeg;base64,${img.contentBase64}`;
      el.style.cssText = 'max-width:400px;max-height:300px;border:1px solid var(--border);border-radius:4px';
      el.alt   = img.filename;
      const cap = document.createElement('figcaption');
      cap.textContent = img.filename;
      cap.style.cssText = 'font-size:11px;color:var(--muted);text-align:center';
      figure.appendChild(el);
      figure.appendChild(cap);
      snapshots.appendChild(figure);
    }
    if (!data.images?.length) {
      snapshots.innerHTML = '<span style="color:var(--muted);font-size:12px">Keine Bilder vorhanden.</span>';
    }
  } catch { /* nicht kritisch */ }
}

/** Lädt aruco_marker_poses.json für den Run und zeigt die Marker-Tabelle. */
async function loadArucoData(runDir) {
  try {
    // Rohdaten über Homing-Run-Data-Endpoint nicht direkt verfügbar,
    // daher holen wir uns die JSON über board/latest falls es der gleiche Run ist,
    // oder wir parsen es aus den Analysis-Daten.
    // Fürs erste: Marker aus dem finalState ableiten wenn vorhanden.
    csvInfo.textContent = '(Marker-CSV wird nach dem nächsten Homing-Run geladen)';
  } catch { /* ignorieren */ }
}

// ── Homing starten ────────────────────────────────────────────────────────────

async function runHoming() {
  // UI zurücksetzen
  logEl.value      = '';
  analysisEl.value = '';
  resultJson.value = '';
  resultTree.innerHTML = '<span style="color:var(--muted);font-size:12px">(Ergebnis erscheint hier)</span>';
  csvInfo.textContent  = '';
  csvTable.innerHTML   = '';
  snapshots.innerHTML  = '<span style="color:var(--muted);font-size:12px">…</span>';
  _lastState = null;

  btnRun.disabled  = true;
  btnSend.disabled = true;
  btnSend.style.opacity = '0.4';
  btnSend.style.cursor  = 'not-allowed';
  setStatus('● Läuft …', 'wip');
  progressDiv.style.display = 'block';
  progressBar.style.width   = '2%';
  progressText.textContent  = 'Verbinde …';

  try {
    const response = await fetch('/api/homing/run', { method: 'POST' });
    if (!response.ok || !response.body) throw new Error(`HTTP ${response.status}`);

    const reader  = response.body.getReader();
    const decoder = new TextDecoder();
    let buf     = '';
    let lastRunDir = null;
    let hasError   = false;

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buf += decoder.decode(value, { stream: true });
      const lines = buf.split('\n');
      buf = lines.pop();   // unvollständige letzte Zeile aufheben

      for (const line of lines) {
        if (!line.startsWith('data: ')) continue;
        let evt;
        try { evt = JSON.parse(line.slice(6)); } catch { continue; }

        switch (evt.type) {
          case 'log':
            appendLog(evt.text);
            break;

          case 'step':
            setProgress(evt.step, evt.total, evt.text);
            appendLog(`[${evt.step}/${evt.total}] ${evt.text || ''}`);
            break;

          case 'analysis':
            appendAnalysis(evt.key, evt.value);
            break;

          case 'error':
            appendLog(evt.text);
            hasError = true;
            break;

          case 'done':
            if (evt.state) {
              _lastState = evt.state;
              showResult(evt.state);
              btnSend.disabled = false;
              btnSend.style.opacity = '';
              btnSend.style.cursor  = '';
              setStatus('✓ Fertig', 'done');
              progressBar.style.width  = '100%';
              progressText.textContent = 'Homing abgeschlossen';
            } else {
              setStatus('✗ Fehler', 'open');
              progressBar.style.width  = '100%';
              progressText.textContent = hasError ? 'Fehler aufgetreten' : 'Abgebrochen';
            }
            if (evt.runDir) {
              lastRunDir = evt.runDir;
              await loadRunData(evt.runDir);
            }
            break;
        }
      }
    }

  } catch (err) {
    appendLog(`❌ Verbindungsfehler: ${err.message}`);
    setStatus('✗ Fehler', 'open');
    progressBar.style.width  = '100%';
    progressText.textContent = 'Verbindungsfehler';
  } finally {
    btnRun.disabled = false;
  }
}

// ── State an Roboter senden ───────────────────────────────────────────────────

async function sendToRobot() {
  if (!_lastState) return;

  btnSend.disabled = true;
  try {
    const res = await fetch('/api/homing/send-state', {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify({ state: _lastState }),
    });
    const data = await res.json();

    if (res.ok) {
      appendLog('✅ State erfolgreich an Roboter gesendet');
      setStatus('✓ Gesendet', 'done');
    } else {
      appendLog(`❌ Fehler beim Senden: ${data.error ?? JSON.stringify(data)}`);
      btnSend.disabled = false;
    }
  } catch (err) {
    appendLog(`❌ Netzwerkfehler: ${err.message}`);
    btnSend.disabled = false;
  }
}

// ── Event-Listener ────────────────────────────────────────────────────────────

btnRun.addEventListener('click',  runHoming);
btnSend.addEventListener('click', sendToRobot);
