'use strict';

const REFRESH_MS = (parseInt(localStorage.getItem('refresh_ms') || '1000', 10));

// Noms configurables — chargés depuis /api/names au démarrage
const noms = { relay1: 'Relais 1', relay2: 'Relais 2', di1: 'Entrée 1', di2: 'Entrée 2' };

async function chargerNoms() {
    try {
        const d = await (await fetch('/api/names')).json();
        if (d.relay1) noms.relay1 = d.relay1;
        if (d.relay2) noms.relay2 = d.relay2;
        if (d.di1)    noms.di1    = d.di1;
        if (d.di2)    noms.di2    = d.di2;
    } catch {}
    appliquerNoms();
}

function appliquerNoms() {
    setText('label-relay1',  noms.relay1);
    setText('label-relay2',  noms.relay2);
    setText('label-di1',     noms.di1);
    setText('label-di2',     noms.di2);
    setText('cmd-label-r1',  noms.relay1);
    setText('cmd-label-r2',  noms.relay2);
    const r1 = document.getElementById('c-n-relay1'); if (r1) r1.value = noms.relay1;
    const r2 = document.getElementById('c-n-relay2'); if (r2) r2.value = noms.relay2;
    const d1 = document.getElementById('c-n-di1');    if (d1) d1.value = noms.di1;
    const d2 = document.getElementById('c-n-di2');    if (d2) d2.value = noms.di2;
}

async function sauvegarderNoms() {
    const payload = {
        relay1: document.getElementById('c-n-relay1').value.trim() || 'Relais 1',
        relay2: document.getElementById('c-n-relay2').value.trim() || 'Relais 2',
        di1:    document.getElementById('c-n-di1').value.trim()    || 'Entrée 1',
        di2:    document.getElementById('c-n-di2').value.trim()    || 'Entrée 2',
    };
    await fetch('/api/names', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
    });
    location.reload();
}

// --- Navigation onglets ---
function afficherOnglet(nom, bouton) {
    document.querySelectorAll('.onglet').forEach(s => s.classList.remove('actif'));
    document.querySelectorAll('.tab').forEach(b => b.classList.remove('active'));
    document.getElementById(nom).classList.add('actif');
    bouton.classList.add('active');
    if (nom === 'regles')     chargerRegles();
    if (nom === 'config')     { chargerSleep(); chargerWifi(); chargerPrefsUI(); chargerModbus(); }
    if (nom === 'historique') chargerHistorique();
    if (nom === 'debug')      chargerDebug();
}

// --- Rafraîchissement de l'état ---
async function rafraichir() {
    try {
        const res = await fetch('/api/state');
        if (!res.ok) throw new Error('HTTP ' + res.status);
        const d = await res.json();
        mettreAJourUI(d);
    } catch {
        const b = document.getElementById('rs485-badge');
        b.textContent = 'Hors ligne';
        b.className   = 'badge badge-err';
    }
}

function mettreAJourUI(d) {
    // PV & batterie
    setText('battery',   d.battery.toFixed(2)   + ' V');
    setText('pv',        d.pv.toFixed(2)         + ' V');
    setText('pvCurrent', d.pvCurrent.toFixed(2)  + ' A');
    setText('sun',       d.sun ? '☀ Jour' : '🌙 Nuit');
    setText('epeverTime', d.epeverTime || '--');
    setText('epeverClockOk', d.epeverClockOk ? 'OK' : 'ERR');
    setText('header-clock', d.espClockOk ? d.espTime : (d.epeverTime || '--'));
    // Batterie détaillée
    setText('batSOC',    d.batSOC + ' %');
    setText('batTemp',   d.batTemperature.toFixed(1) + ' °C');
    setText('batStatut', ['Arrêt','Float','Boost','Égalisation'][d.batStatut] || '--');
    // Load & énergie
    setText('loadVoltage',     d.loadVoltage.toFixed(2)  + ' V');
    setText('loadCurrent',     d.loadCurrent.toFixed(2)  + ' A');
    setText('loadPower',       d.loadPower.toFixed(1)    + ' W');
    setText('energieGenJour',  d.energieGenJour.toFixed(2)  + ' kWh');
    setText('energieConJour',  d.energieConJour.toFixed(2)  + ' kWh');
    setText('energieGenTotal', d.energieGenTotal.toFixed(2) + ' kWh');
    setText('energieConTotal', d.energieConTotal.toFixed(2) + ' kWh');
    // Relais & boutons
    setRelais('relay1-etat', 'carte-relay1', 'led-r1', 'btn-r1-on', 'btn-r1-off', d.relay1);
    setRelais('relay2-etat', 'carte-relay2', 'led-r2', 'btn-r2-on', 'btn-r2-off', d.relay2);
    setBouton('di1-etat', d.di1);
    setBouton('di2-etat', d.di2);

    const badge = document.getElementById('rs485-badge');
    badge.textContent = d.rs485_ok ? 'RS485 OK' : 'RS485 ERR';
    badge.className   = 'badge ' + (d.rs485_ok ? 'badge-ok' : 'badge-err');


    document.getElementById('pied-page').textContent =
        'Mise à jour : ' + new Date().toLocaleTimeString('fr-FR');
}

function setBouton(id, etat) {
    const el = document.getElementById(id);
    if (!el) return;
    el.textContent = etat ? '● Appuyé' : '○ Relâché';
    el.className   = 'valeur ' + (etat ? 'val-on' : 'val-off');
}

function setRelais(id, carteId, ledId, btnOnId, btnOffId, etat) {
    const el = document.getElementById(id);
    if (el) { el.textContent = etat ? '● ON' : '○ OFF'; el.className = 'valeur ' + (etat ? 'val-on' : 'val-off'); }

    const carte = document.getElementById(carteId);
    if (carte) carte.classList.toggle('carte-on', etat);

    const led = document.getElementById(ledId);
    if (led) led.className = 'led ' + (etat ? 'led-on' : 'led-off');

    const btnOn  = document.getElementById(btnOnId);
    const btnOff = document.getElementById(btnOffId);
    if (btnOn)  btnOn.className  = 'btn btn-vert'  + (etat  ? ' btn-glow-vert'  : ' btn-dim');
    if (btnOff) btnOff.className = 'btn btn-rouge' + (!etat ? ' btn-glow-rouge' : ' btn-dim');
}

function setText(id, val) {
    const el = document.getElementById(id);
    if (el) el.textContent = val;
}

// --- Relais / Mode ---
async function relay(n, cmd) {
    const res = await fetch('/api/relay/' + n + '/' + cmd, { method: 'POST' });
    if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        afficherToast(d.err || 'Commande refusée');
    }
    rafraichir();
}

function afficherToast(msg) {
    let t = document.getElementById('toast');
    if (!t) {
        t = document.createElement('div');
        t.id = 'toast';
        document.body.appendChild(t);
    }
    t.textContent = msg;
    t.classList.add('visible');
    clearTimeout(t._timer);
    t._timer = setTimeout(() => t.classList.remove('visible'), 2800);
}

async function rebootESP() {
    if (!confirm('Redémarrer l\'ESP32 ?')) return;
    await fetch('/api/reboot', { method: 'POST' });
    afficherToast('Redémarrage en cours…');
    setTimeout(() => location.reload(), 5000);
}

// --- Règles ---
async function chargerRegles() {
    try {
        const res  = await fetch('/api/rules');
        const data = await res.json();
        afficherRegles(data);
    } catch {
        document.getElementById('liste-regles').innerHTML =
            '<p style="color:var(--muted);text-align:center">Erreur chargement</p>';
    }
}

function afficherRegles(regles) {
    const el = document.getElementById('liste-regles');
    if (!regles.length) {
        el.innerHTML = '<p style="color:var(--muted);text-align:center;padding:1rem">Aucune règle</p>';
        return;
    }
    el.innerHTML = regles.map(r => {
        const cond  = construireDescription(r);
        const cls   = r.enabled ? '' : ' regle-desactivee';
        return `<div class="regle-item${cls}">
            <div class="regle-desc">
                <div class="regle-id">Règle #${r.id}</div>
                ${cond}
            </div>
            <button class="btn btn-sm" onclick="toggleRegle(${r.id})">${r.enabled ? 'OFF' : 'ON'}</button>
            <button class="btn btn-sm btn-rouge" onclick="supprimerRegle(${r.id})">✕</button>
        </div>`;
    }).join('');
}

function construireDescription(r) {
    const dec = [];
    if (r.sun !== undefined) dec.push(r.sun ? '☀ Jour' : '🌙 Nuit');
    if (r.di1 !== undefined) dec.push('DI1 ' + (r.di1 ? 'fermé' : 'ouvert'));
    if (r.di2 !== undefined) dec.push('DI2 ' + (r.di2 ? 'fermé' : 'ouvert'));

    const cond = [];
    if (r.battery_min) cond.push('Bat ≥ ' + r.battery_min + 'V');
    if (r.battery_max) cond.push('Bat ≤ ' + r.battery_max + 'V');
    if (r.pv_min)      cond.push('PV ≥ '  + r.pv_min + 'V');
    if (r.pv_max)      cond.push('PV ≤ '  + r.pv_max + 'V');

    const extras = [];
    if (r.delay)      extras.push('délai ' + r.delay + 's');
    if (r.hysteresis) extras.push('hyst. ±' + r.hysteresis + 'V');

    const c = '<span style="color:var(--accent);font-size:0.72rem">▶</span>';
    const lines = [];
    if (dec.length)  lines.push(c + ' <em>Si</em> '  + dec.join(' + '));
    if (cond.length) lines.push(c + ' <em>Et</em> '  + cond.join(' + '));
    lines.push(c + ' → Relais ' + r.relay + ' <strong>' + (r.state ? 'ON' : 'OFF') + '</strong>'
        + (extras.length ? ' <span style="color:var(--muted);font-size:0.78rem">(' + extras.join(', ') + ')</span>' : ''));
    return lines.join('<br>');
}

async function toggleRegle(id) {
    await fetch('/api/rules/toggle?id=' + id, { method: 'POST' });
    chargerRegles();
}

async function supprimerRegle(id) {
    await fetch('/api/rules/delete?id=' + id, { method: 'POST' });
    chargerRegles();
}

async function ajouterRegle() {
    const sun    = document.getElementById('f-sun').value;
    const di1    = document.getElementById('f-di1').value;
    const di2    = document.getElementById('f-di2').value;
    const batMin = parseFloat(document.getElementById('f-batmin').value) || 0;
    const batMax = parseFloat(document.getElementById('f-batmax').value) || 0;
    const pvMin  = parseFloat(document.getElementById('f-pvmin').value)  || 0;
    const pvMax  = parseFloat(document.getElementById('f-pvmax').value)  || 0;
    const relay  = parseInt(document.getElementById('f-relay').value);
    const state  = document.getElementById('f-state').value === 'true';
    const delay  = parseInt(document.getElementById('f-delay').value) || 0;
    const hyst   = parseFloat(document.getElementById('f-hysteresis').value) || 0;

    const regle = { enabled: true, relay, state, delay };
    if (sun  !== '') regle.sun         = sun  === 'true';
    if (di1  !== '') regle.di1         = di1  === 'true';
    if (di2  !== '') regle.di2         = di2  === 'true';
    if (batMin > 0)  regle.battery_min = batMin;
    if (batMax > 0)  regle.battery_max = batMax;
    if (pvMin  > 0)  regle.pv_min      = pvMin;
    if (pvMax  > 0)  regle.pv_max      = pvMax;
    if (hyst   > 0)  regle.hysteresis  = hyst;

    const res = await fetch('/api/rules', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(regle)
    });
    if (res.ok) chargerRegles();
}

// --- Préférences UI (stockées en localStorage) ---
function getRefreshMs() {
    return parseInt(localStorage.getItem('refresh_ms') || '1000', 10);
}

function chargerPrefsUI() {
    const r = document.getElementById('c-refresh');
    if (r) r.value = Math.round(getRefreshMs() / 1000);
    const lp = document.getElementById('c-longpress2');
    if (lp) lp.value = getLongPressMs();
}

function sauvegarderInterface() {
    const s  = parseInt(document.getElementById('c-refresh').value) || 1;
    const lp = parseInt(document.getElementById('c-longpress2').value) || 500;
    localStorage.setItem('refresh_ms',   Math.min(60000, Math.max(1000, s * 1000)));
    localStorage.setItem('longpress_ms', Math.min(3000,  Math.max(200, lp)));
    location.reload();
}

// --- WiFi info ---
async function chargerWifi() {
    try {
        const d = await (await fetch('/api/wifi')).json();
        setText('wifi-ssid', d.ssid || '--');
        setText('wifi-pwd', d.password || '(vide)');
    } catch { /* silencieux */ }
}

// --- Sleep / Config ---
async function chargerSleep() {
    try {
        const d = await (await fetch('/api/sleep')).json();
        document.getElementById('c-sleep-actif').value      = String(d.actif);
        document.getElementById('c-sleep-intervalle').value = Math.round(d.intervalle / 60);
        document.getElementById('c-sleep-seuil').value      = d.seuil;
    } catch { /* silencieux */ }
}

async function sauvegarderSleep() {
    const actif     = document.getElementById('c-sleep-actif').value === 'true';
    const intervalle = parseInt(document.getElementById('c-sleep-intervalle').value) * 60;
    const seuil     = parseFloat(document.getElementById('c-sleep-seuil').value);
    await fetch('/api/sleep', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ actif, intervalle, seuil })
    });
}

// --- Intervalles Modbus ---
async function chargerModbus() {
    try {
        const d = await (await fetch('/api/modbus')).json();
        const j = document.getElementById('c-mb-jour'); if (j) j.value = Math.round(d.jour / 1000);
        const n = document.getElementById('c-mb-nuit'); if (n) n.value = Math.round(d.nuit / 1000);
    } catch { /* silencieux */ }
}

async function sauvegarderModbus() {
    const jour = (parseInt(document.getElementById('c-mb-jour').value) || 5) * 1000;
    const nuit = (parseInt(document.getElementById('c-mb-nuit').value) || 30) * 1000;
    await fetch('/api/modbus', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ jour, nuit })
    });
    afficherToast('Intervalles Modbus sauvegardés');
}

// --- Horloge EPEVER ---
function toDatetimeLocalValue(date) {
    const pad = n => String(n).padStart(2, '0');
    return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate()) +
        'T' + pad(date.getHours()) + ':' + pad(date.getMinutes()) + ':' + pad(date.getSeconds());
}

function remplirHeureNavigateur() {
    const input = document.getElementById('c-epever-time');
    if (input) input.value = toDatetimeLocalValue(new Date());
}

async function sauvegarderHeureEpever() {
    const input = document.getElementById('c-epever-time');
    if (!input || !input.value) {
        afficherToast('Date/heure manquante');
        return;
    }

    const d = new Date(input.value);
    if (Number.isNaN(d.getTime())) {
        afficherToast('Date/heure invalide');
        return;
    }

    const payload = {
        year: d.getFullYear(),
        month: d.getMonth() + 1,
        day: d.getDate(),
        hour: d.getHours(),
        minute: d.getMinutes(),
        second: d.getSeconds()
    };

    const res = await fetch('/api/epever/time', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
    });

    afficherToast(res.ok ? 'Horloge EPEVER réglée' : 'Réglage refusé, réessaie dans quelques secondes');
    rafraichir();
}

// --- Debug série / RS485 ---
async function chargerDebug() {
    const consoleEl = document.getElementById('debug-console');
    const metaEl = document.getElementById('debug-meta');
    if (!consoleEl || !metaEl) return;

    try {
        const d = await (await fetch('/api/debug/logs')).json();
        metaEl.textContent = d.lines.length + ' lignes en mémoire, compteur ' + d.count;
        consoleEl.textContent = d.lines.map(l => {
            const s = Math.floor((l.t || 0) / 1000);
            return '[' + s.toString().padStart(6, ' ') + 's] ' + l.m;
        }).join('\n') || 'Aucun message.';
        consoleEl.scrollTop = consoleEl.scrollHeight;
    } catch {
        metaEl.textContent = 'Erreur lecture journal';
        consoleEl.textContent = 'Impossible de lire /api/debug/logs';
    }
}

async function viderDebug() {
    await fetch('/api/debug/clear', { method: 'POST' });
    chargerDebug();
}

// --- Historique ---
let histMode = 'hires';

function setHistMode(mode) {
    histMode = mode;
    document.getElementById('btn-hires').classList.toggle('active-mode', mode === 'hires');
    document.getElementById('btn-lores').classList.toggle('active-mode', mode === 'lores');
    chargerHistorique();
}

async function chargerHistorique() {
    try {
        const url = histMode === 'hires' ? '/api/history/hires' : '/api/history';
        const res = await fetch(url);
        if (!res.ok) throw new Error('HTTP ' + res.status);
        const d = await res.json();
        await chargerHistoriqueStatus(d);
        const ids = [
            { id: 'chart-battery', data: d.b, couleur: '#00b894', unite: 'V' },
            { id: 'chart-pv',      data: d.p, couleur: '#e94560', unite: 'V' },
            { id: 'chart-load',    data: d.l, couleur: '#fdcb6e', unite: 'W' },
            { id: 'chart-soc',     data: d.s, couleur: '#74b9ff', unite: '%' },
        ];
        ids.forEach(({ id, data, couleur, unite }) => {
            const canvas = document.getElementById(id);
            if (canvas) dessinerGraphe(canvas, data, couleur, unite, d.step);
        });
        afficherDerniersPoints(d);
    } catch (e) {
        setText('hist-debug', 'Erreur chargement historique: ' + e.message);
    }
}

async function chargerHistoriqueStatus(hist) {
    try {
        const s = await (await fetch('/api/history/status')).json();
        hist = hist || {};
        const mode = hist.mode || histMode;
        const n = hist.n !== undefined ? hist.n : 0;
        const nbBat = hist.b ? hist.b.length : 0;
        const nbPv = hist.p ? hist.p.length : 0;
        const nbLoad = hist.l ? hist.l.length : 0;
        const nbSoc = hist.s ? hist.s.length : 0;
        const nextH = Math.ceil((s.next_hires_ms || 0) / 1000);
        const nextL = Math.ceil((s.next_lores_ms || 0) / 1000);
        setText('hist-debug',
            'Mode ' + mode +
            ' | points affichés: ' + n +
            ' | séries b/p/l/s: ' + nbBat + '/' + nbPv + '/' + nbLoad + '/' + nbSoc +
            ' | hires: ' + s.hires_n + '/' + s.hires_max +
            ' | lores: ' + s.lores_n + '/' + s.lores_max +
            ' | acc: ' + s.acc_n +
            ' | RS485: ' + (s.rs485_ok ? 'OK' : 'ERR') +
            ' | prochain 1min: ' + nextH + 's' +
            ' | prochain 5min: ' + nextL + 's'
        );
    } catch {
        setText('hist-debug', 'Debug historique indisponible');
    }
}

function afficherDerniersPoints(hist) {
    const el = document.getElementById('hist-last');
    if (!el) return;

    const b = (hist.b || []).map(Number);
    const p = (hist.p || []).map(Number);
    const l = (hist.l || []).map(Number);
    const s = (hist.s || []).map(Number);
    const n = Math.min(b.length, p.length, l.length, s.length);
    if (!n) {
        el.textContent = 'Aucun point historique reçu depuis l’API.';
        return;
    }

    const debut = Math.max(0, n - 5);
    const lignes = [];
    for (let i = debut; i < n; i++) {
        lignes.push(
            '#' + (i + 1) +
            ' bat=' + b[i].toFixed(2) + 'V' +
            ' pv=' + p[i].toFixed(2) + 'V' +
            ' load=' + l[i].toFixed(1) + 'W' +
            ' soc=' + s[i].toFixed(0) + '%'
        );
    }
    el.textContent = 'Derniers points: ' + lignes.join(' | ');
}

function dessinerGraphe(canvas, data, couleur, unite, stepSec) {
    stepSec = stepSec || 300;
    data = (data || []).map(Number).filter(Number.isFinite);
    const ctx = canvas.getContext('2d');
    const W = canvas.width, H = canvas.height;
    const pad = { top: 12, right: 8, bottom: 28, left: 38 };
    const w = W - pad.left - pad.right;
    const h = H - pad.top - pad.bottom;

    ctx.clearRect(0, 0, W, H);

    if (!data.length) {
        ctx.fillStyle = '#a0aec0';
        ctx.font = '14px system-ui';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText('Pas encore de données', W / 2, H / 2);
        return;
    }

    const min = Math.min(...data);
    const max = Math.max(...data);
    const marge = Math.max((max - min) * 0.15, unite === '%' ? 2 : 0.2);
    const yMin = min === max ? min - marge : min - marge;
    const yMax = min === max ? max + marge : max + marge;
    const range = yMax - yMin || 1;

    // grille horizontale
    ctx.lineWidth = 1;
    for (let i = 0; i <= 4; i++) {
        const y = pad.top + (h / 4) * i;
        ctx.strokeStyle = '#0f3460';
        ctx.beginPath(); ctx.moveTo(pad.left, y); ctx.lineTo(pad.left + w, y); ctx.stroke();
        const val = yMax - (range / 4) * i;
        ctx.fillStyle = '#a0aec0';
        ctx.font = '10px system-ui';
        ctx.textAlign = 'right';
        ctx.textBaseline = 'middle';
        ctx.fillText(val.toFixed(1) + unite, pad.left - 4, y);
    }

    if (data.length === 1) {
        const x = pad.left + w / 2;
        const y = pad.top + h - ((data[0] - yMin) / range) * h;
        ctx.fillStyle = couleur;
        ctx.beginPath();
        ctx.arc(x, y, 4, 0, Math.PI * 2);
        ctx.fill();
        ctx.fillStyle = '#a0aec0';
        ctx.font = '11px system-ui';
        ctx.textAlign = 'center';
        ctx.fillText(data[0].toFixed(1) + unite, x, Math.max(12, y - 8));
        return;
    }

    // courbe
    ctx.strokeStyle = couleur;
    ctx.lineWidth = 2;
    ctx.lineJoin = 'round';
    ctx.beginPath();
    data.forEach((v, i) => {
        const x = pad.left + (i / (data.length - 1)) * w;
        const y = pad.top + h - ((v - yMin) / range) * h;
        i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
    });
    ctx.stroke();

    // remplissage sous la courbe
    ctx.lineTo(pad.left + w, pad.top + h);
    ctx.lineTo(pad.left, pad.top + h);
    ctx.closePath();
    ctx.fillStyle = couleur + '22';
    ctx.fill();

    // labels temps (axe X — ~5 labels)
    const now = Date.now();
    const step = Math.max(1, Math.floor(data.length / 5));
    ctx.fillStyle = '#a0aec0';
    ctx.font = '10px system-ui';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'alphabetic';
    for (let i = 0; i < data.length; i += step) {
        const x = pad.left + (i / (data.length - 1)) * w;
        const t = new Date(now - (data.length - 1 - i) * stepSec * 1000);
        ctx.fillText(
            t.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }),
            x, H - 5
        );
    }
}

// --- Long press relais dashboard ---
function getLongPressMs() {
    return parseInt(localStorage.getItem('longpress_ms') || '500', 10);
}

function setupLongPress(carteId, relayNum) {
    const el = document.getElementById(carteId);
    if (!el) return;
    let timer = null;

    const start = (e) => {
        e.preventDefault();
        el.classList.add('press-hold');
        timer = setTimeout(async () => {
            timer = null;
            el.classList.remove('press-hold');
            el.classList.add('press-done');
            setTimeout(() => el.classList.remove('press-done'), 500);
            const res = await fetch('/api/relay/' + relayNum + '/toggle', { method: 'POST' });
            if (!res.ok) {
                const d = await res.json().catch(() => ({}));
                afficherToast(d.err || 'Commande refusée');
            } else {
                afficherToast((relayNum === 1 ? noms.relay1 : noms.relay2) + ' basculé et sauvegardé');
            }
            rafraichir();
        }, getLongPressMs());
    };

    const cancel = () => {
        clearTimeout(timer);
        timer = null;
        el.classList.remove('press-hold');
    };

    el.addEventListener('pointerdown', start);
    el.addEventListener('pointerup',   cancel);
    el.addEventListener('pointerleave', cancel);
    el.addEventListener('contextmenu', e => e.preventDefault());
}

function setupSunLongPress() {
    const el = document.getElementById('carte-sun');
    if (!el) return;
    let timer = null;

    const start = (e) => {
        e.preventDefault();
        el.classList.add('press-hold');
        timer = setTimeout(() => {
            timer = null;
            el.classList.remove('press-hold');
            ouvrirSunPopup();
        }, 2000);
    };

    const cancel = () => {
        clearTimeout(timer);
        timer = null;
        el.classList.remove('press-hold');
    };

    el.addEventListener('pointerdown', start);
    el.addEventListener('pointerup', cancel);
    el.addEventListener('pointerleave', cancel);
    el.addEventListener('contextmenu', e => e.preventDefault());
}

function formatSunHistoryTime(value) {
    if (!value || value.indexOf('uptime') === 0) return value || '--';
    const parts = value.split(' ');
    if (parts.length !== 2) return value;
    const d = parts[0].split('-');
    const t = parts[1].split(':');
    if (d.length !== 3 || t.length < 2) return value;
    return t[0] + ':' + t[1] + ' ' + d[2] + '/' + d[1];
}

async function ouvrirSunPopup() {
    const modal = document.getElementById('sun-modal');
    const list = document.getElementById('sun-history-list');
    if (!modal || !list) return;

    modal.classList.remove('hidden');
    list.textContent = 'Chargement...';

    try {
        const d = await (await fetch('/api/sun/history')).json();
        const changes = d.changes || [];
        if (!changes.length) {
            list.innerHTML = '<div class="modal-empty">Aucun changement enregistré depuis le boot.</div>';
            return;
        }
        list.innerHTML = changes.slice().reverse().map(c =>
            '<div class="modal-row"><span>' + formatSunHistoryTime(c.time) + '</span><strong>' + c.label + '</strong></div>'
        ).join('');
    } catch {
        list.innerHTML = '<div class="modal-empty">Erreur lecture historique jour/nuit.</div>';
    }
}

function fermerSunPopup() {
    const modal = document.getElementById('sun-modal');
    if (modal) modal.classList.add('hidden');
}

// --- Démarrage ---
chargerNoms();
rafraichir();
setInterval(rafraichir, REFRESH_MS);
setInterval(() => {
    const debugEl = document.getElementById('debug');
    const debugActif = debugEl && debugEl.classList.contains('actif');
    if (debugActif) chargerDebug();
}, 2000);
setInterval(() => {
    const histEl = document.getElementById('historique');
    const histActif = histEl && histEl.classList.contains('actif');
    if (histActif) chargerHistorique();
}, 5000);
setupLongPress('carte-relay1', 1);
setupLongPress('carte-relay2', 2);
setupSunLongPress();
