// ============================================================================
// SETUP → MOTEUR & MISE À JOUR (propriétaire, app locale uniquement)
//
// Deux gestes, séparés par leur COÛT — c'est tout l'intérêt :
//   🔄 Recharger le backend : quelques secondes, SANS couper les iPhones. Le geste de tous
//      les jours, faisable en pleine journée pendant que les VA travaillent.
//   ⚠️ Redémarrer le moteur : coupe les iPhones ~5 min (WDA remonte sur chaque téléphone).
//      Le geste RARE, à faire hors présence VA.
//
// Le moteur est lancé DÉTACHÉ : fermer l'app ne le coupe plus. Seul le bouton ci-dessous le
// redémarre. Ces commandes passent par window.electronSystem (pont Electron) : hors de l'app
// PhoneLabs, elles n'existent pas -> on l'affiche clairement au lieu de boutons morts.
// ============================================================================
// Formate des octets en Ko/Mo lisibles.
function koctets(n) {
  n = Number(n) || 0;
  if (n < 1024) return n + " o";
  if (n < 1024 * 1024) return (n / 1024).toFixed(0) + " Ko";
  return (n / 1024 / 1024).toFixed(1) + " Mo";
}
// Libellé + couleur selon ce qui a déclenché l'instantané.
function triggerInfo(t) {
  const m = {
    "manuel":        ["Manuel", "var(--accent)"],
    "avant-backend": ["Avant recharge backend", "#58a6ff"],
    "avant-moteur":  ["Avant redémarrage moteur", "#f0a020"],
    "avant-retour":  ["Avant un retour", "#a371f7"],
  };
  return m[t] || [t || "—", "var(--muted)"];
}

function SystemView() {
  const { useState, useEffect } = React;
  const SYS = (typeof window !== "undefined") ? window.electronSystem : null;
  const [etat, setEtat] = useState(null);
  const [busy, setBusy] = useState("");
  const [flash, setFlash] = useState(null);
  const [snaps, setSnaps] = useState(null);       // null = pas encore chargé ; [] = aucun
  const [snapBusy, setSnapBusy] = useState("");   // id en cours (création / restauration)

  const rafraichir = async () => {
    if (!SYS || !SYS.status) return;
    try { setEtat(await SYS.status()); } catch (e) { setEtat(null); }
  };
  // Les snapshots passent par le BACKEND LOCAL (same-origin 127.0.0.1), pas par le pont Electron :
  // ils protègent la donnée D1, et le backend a le secret agent pour /api/backup.
  const chargerSnaps = async () => {
    try {
      const r = await fetch("/api/snapshots", { cache: "no-store" });
      const j = await r.json();
      setSnaps(Array.isArray(j && j.snapshots) ? j.snapshots : []);
    } catch (e) { setSnaps([]); }
  };
  useEffect(() => {
    rafraichir(); chargerSnaps();
    const iv = setInterval(rafraichir, 5000);
    return () => clearInterval(iv);
  }, []);

  const dire = (ok, txt) => { setFlash({ ok, txt }); setTimeout(() => setFlash(null), 6000); };

  // Prend un instantané AVANT un geste risqué. Best-effort : renvoie le résumé, sans jamais lever.
  const snapAvant = async (trigger) => {
    try {
      const r = await fetch("/api/snapshots/create", { method: "POST",
        headers: { "Content-Type": "application/json" }, body: JSON.stringify({ trigger }) });
      return await r.json();
    } catch (e) { return { ok: false, error: String(e && e.message || e) }; }
  };

  const rechargerBackend = async () => {
    setBusy("backend");
    // Filet : instantané AVANT (le backend est encore vivant pour le prendre), puis on recharge.
    const snp = await snapAvant("avant-backend");
    const pre = snp && snp.ok ? "Instantané pris. " : "⚠️ Instantané non pris (" + ((snp && snp.error) || "?") + "). ";
    try {
      const r = await SYS.reloadBackend();
      dire(!!(r && r.ok), (r && r.ok) ? "✓ " + pre + "Backend rechargé — aucune coupure iPhone." : "⚠️ " + pre + "Le backend n'est pas revenu. Réessaie, ou regarde le journal.");
    } catch (e) { dire(false, "⚠️ Échec : " + (e && e.message || e)); }
    setBusy(""); rafraichir(); chargerSnaps();
  };
  const redemarrerMoteur = async () => {
    if (!window.confirm("Redémarrer le MOTEUR ?\n\n⚠️ Ça coupe les iPhones ~5 min (WDA remonte sur chaque téléphone). À faire hors présence des VA.\n\nUn instantané de sécurité est pris avant.\n\nContinuer ?")) return;
    setBusy("moteur");
    const snp = await snapAvant("avant-moteur");
    const pre = snp && snp.ok ? "Instantané pris. " : "⚠️ Instantané non pris (" + ((snp && snp.error) || "?") + "). ";
    try {
      const r = await SYS.restartEngine();
      dire(!!(r && r.ok), (r && r.ok) ? "✓ " + pre + "Moteur redémarré — les iPhones remontent." : "⚠️ " + pre + "Le moteur n'est pas revenu. Regarde le journal.");
    } catch (e) { dire(false, "⚠️ Échec : " + (e && e.message || e)); }
    setBusy(""); rafraichir(); chargerSnaps();
  };

  // Instantané manuel (bouton dédié).
  const snapMaintenant = async () => {
    setSnapBusy("create");
    const j = await snapAvant("manuel");
    dire(!!(j && j.ok), (j && j.ok) ? "✓ Instantané créé (" + j.count + " éléments, " + koctets(j.octets) + ")." : "⚠️ " + ((j && j.error) || "échec de l'instantané"));
    setSnapBusy(""); chargerSnaps();
  };

  // Revenir sur un instantané : réécrit la donnée D1 (un instantané de l'état courant est pris avant).
  const restaurer = async (s) => {
    if (!window.confirm(
      "Revenir sur l'instantané du " + s.at + " ?\n\n" +
      "⚠️ Ça RÉÉCRIT les données actuelles (comptes, conteneurs, pointages, facturation…) avec celles de cet instantané.\n\n" +
      "Un instantané de l'état ACTUEL est pris juste avant — donc ce retour est lui-même réversible.\n\nContinuer ?")) return;
    setSnapBusy("r" + s.id);
    try {
      const r = await fetch("/api/snapshots/restore", { method: "POST",
        headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: s.id }) });
      const j = await r.json();
      dire(!!(j && j.ok), (j && j.ok)
        ? "✓ Revenu sur l'instantané (" + j.count + " éléments réécrits). Recharge tes pages (Ctrl+Maj+R) pour voir les données restaurées."
        : "⚠️ " + ((j && j.error) || "échec de la restauration"));
    } catch (e) { dire(false, "⚠️ Échec : " + (e && e.message || e)); }
    setSnapBusy(""); chargerSnaps();
  };

  // Épingle / désépingle (un instantané épinglé n'est jamais purgé automatiquement).
  const epingler = async (s) => {
    try {
      await fetch("/api/snapshots/pin", { method: "POST",
        headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: s.id, garde: !s.garde }) });
    } catch (e) {}
    chargerSnaps();
  };

  const carte = { background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 14, padding: 18, marginBottom: 16 };
  const pastille = (on) => ({ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 12.5, fontWeight: 700,
    color: on ? "#3fb950" : "#f85149" });
  const pt = (on) => <span style={{ width: 9, height: 9, borderRadius: "50%", background: on ? "#3fb950" : "#f85149", boxShadow: on ? "0 0 6px #3fb95088" : "none" }} />;

  if (!SYS) {
    return (
      <div>
        <h1 style={{ margin: "0 0 4px", fontSize: 24, fontWeight: 700 }}>⚙️ Moteur & mise à jour</h1>
        <div style={{ ...carte, borderColor: "rgba(240,160,32,.4)", color: "var(--muted)", fontSize: 13, lineHeight: 1.6 }}>
          Ce panneau pilote le moteur et le backend de <b>cette machine</b>. Il n'est disponible que
          dans l'<b>application PhoneLabs</b> (le pont Electron), pas depuis un navigateur.
          Ouvre-le depuis l'app installée sur le PC qui pilote les iPhones.
        </div>
      </div>
    );
  }

  return (
    <div>
      <h1 style={{ margin: "0 0 4px", fontSize: 24, fontWeight: 700 }}>⚙️ Moteur & mise à jour</h1>
      <div style={{ fontSize: 12.5, color: "var(--muted)", marginBottom: 16 }}>
        Le moteur tourne <b>détaché</b> : fermer l'app ne coupe plus les iPhones. Redémarre-le seulement ici.
      </div>

      {flash && <div style={{ ...carte, marginBottom: 14, borderColor: flash.ok ? "rgba(63,185,80,.4)" : "rgba(248,81,73,.45)",
        color: flash.ok ? "#3fb950" : "#f85149", fontSize: 13, fontWeight: 600 }}>{flash.txt}</div>}

      {/* État */}
      <div style={carte}>
        <div style={{ fontSize: 12.5, fontWeight: 800, marginBottom: 12, color: "var(--muted)", letterSpacing: ".04em", textTransform: "uppercase" }}>État</div>
        <div style={{ display: "flex", gap: 26, flexWrap: "wrap" }}>
          <div style={pastille(etat && etat.backend)}>{pt(etat && etat.backend)} Backend {etat && etat.backend ? "en marche" : "arrêté"}</div>
          <div style={pastille(etat && etat.moteur)}>{pt(etat && etat.moteur)} Moteur {etat == null ? "…" : etat.moteur === null ? "(bac à sable)" : etat.moteur ? "en marche" : "arrêté"}</div>
        </div>
      </div>

      {/* Le geste de tous les jours */}
      <div style={carte}>
        <div style={{ display: "flex", alignItems: "flex-start", gap: 14, flexWrap: "wrap" }}>
          <div style={{ flex: 1, minWidth: 220 }}>
            <div style={{ fontSize: 14.5, fontWeight: 800 }}>🔄 Recharger le backend</div>
            <div style={{ fontSize: 12.5, color: "var(--muted)", marginTop: 4, lineHeight: 1.55 }}>
              Applique une mise à jour du backend. <b style={{ color: "#3fb950" }}>Sans coupure</b> : les iPhones
              restent pilotés, quelques secondes de blip API au pire. À faire en pleine journée.
            </div>
          </div>
          <button onClick={rechargerBackend} disabled={busy}
            style={{ background: "var(--accent)", border: "none", borderRadius: 10, padding: "11px 18px", color: "#04130c",
              fontSize: 13.5, fontWeight: 800, cursor: busy ? "default" : "pointer", opacity: busy ? .6 : 1, whiteSpace: "nowrap" }}>
            {busy === "backend" ? "Rechargement…" : "Recharger le backend"}</button>
        </div>
      </div>

      {/* Le geste lourd */}
      <div style={{ ...carte, borderColor: "rgba(248,81,73,.35)" }}>
        <div style={{ display: "flex", alignItems: "flex-start", gap: 14, flexWrap: "wrap" }}>
          <div style={{ flex: 1, minWidth: 220 }}>
            <div style={{ fontSize: 14.5, fontWeight: 800, color: "#f85149" }}>⚠️ Redémarrer le moteur</div>
            <div style={{ fontSize: 12.5, color: "var(--muted)", marginTop: 4, lineHeight: 1.55 }}>
              Pour une mise à jour du <b>moteur</b> (pilotage iPhone). <b style={{ color: "#f85149" }}>Coupe les iPhones ~5 min</b> —
              WDA remonte sur chaque téléphone. À faire <b>hors présence des VA</b>.
            </div>
          </div>
          <button onClick={redemarrerMoteur} disabled={busy || (etat && etat.moteur === null)}
            style={{ background: "rgba(248,81,73,.14)", border: "1px solid rgba(248,81,73,.5)", borderRadius: 10, padding: "11px 18px",
              color: "#f85149", fontSize: 13.5, fontWeight: 800, cursor: busy ? "default" : "pointer", opacity: busy ? .6 : 1, whiteSpace: "nowrap" }}>
            {busy === "moteur" ? "Redémarrage…" : "Redémarrer le moteur"}</button>
        </div>
      </div>

      {/* Points de retour (instantanés de données D1) */}
      <div style={carte}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12, marginBottom: 6, flexWrap: "wrap" }}>
          <div>
            <div style={{ fontSize: 14.5, fontWeight: 800 }}>💾 Points de retour</div>
            <div style={{ fontSize: 12.5, color: "var(--muted)", marginTop: 4, lineHeight: 1.55, maxWidth: 560 }}>
              Copie complète des données (comptes, conteneurs, pointages, facturation, textes…). Un instantané est
              pris <b>automatiquement avant</b> chaque recharge de backend et redémarrage de moteur. Les fichiers
              restent sur ce PC. « Revenir » réécrit les données — et prend d'abord un instantané de l'état actuel.
            </div>
          </div>
          <button onClick={snapMaintenant} disabled={snapBusy === "create"}
            style={{ background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: 10, padding: "10px 14px",
              color: "var(--text)", fontSize: 13, fontWeight: 700, cursor: snapBusy === "create" ? "default" : "pointer",
              opacity: snapBusy === "create" ? .6 : 1, whiteSpace: "nowrap" }}>
            {snapBusy === "create" ? "Instantané…" : "+ Instantané maintenant"}</button>
        </div>

        {snaps === null && <div style={{ fontSize: 12.5, color: "var(--faint)", padding: "10px 2px" }}>Chargement…</div>}
        {snaps && snaps.length === 0 && (
          <div style={{ fontSize: 12.5, color: "var(--faint)", padding: "10px 2px" }}>
            Aucun instantané pour l'instant. Le premier sera pris au prochain geste, ou clique « Instantané maintenant ».
          </div>
        )}
        {snaps && snaps.length > 0 && (
          <div style={{ display: "grid", gap: 8, marginTop: 8 }}>
            {snaps.map(s => {
              const [tl, tc] = triggerInfo(s.trigger);
              const busyR = snapBusy === "r" + s.id;
              return (
                <div key={s.id} style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap",
                  padding: "10px 12px", borderRadius: 10, background: "var(--surface-2)", border: "1px solid var(--border)" }}>
                  <div style={{ flex: 1, minWidth: 200 }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
                      <span style={{ fontSize: 13, fontWeight: 700 }}>{s.at}</span>
                      <span style={{ fontSize: 10.5, fontWeight: 800, padding: "1px 8px", borderRadius: 99,
                        color: tc, background: "color-mix(in srgb, " + tc + " 15%, transparent)", border: "1px solid color-mix(in srgb, " + tc + " 45%, transparent)" }}>{tl}</span>
                      {s.garde && <span title="Épinglé — jamais purgé" style={{ fontSize: 11 }}>📌</span>}
                    </div>
                    <div style={{ fontSize: 11, color: "var(--faint)", marginTop: 3 }}>
                      {s.count} éléments · {koctets(s.octets)}{s.commit ? " · " + s.commit : ""}{s.name ? " · " + s.name : ""}
                    </div>
                  </div>
                  <button onClick={() => epingler(s)} title={s.garde ? "Désépingler" : "Épingler (ne jamais purger)"}
                    style={{ background: "none", border: "1px solid var(--border)", borderRadius: 8, padding: "7px 10px",
                      color: s.garde ? "var(--accent)" : "var(--muted)", fontSize: 12, cursor: "pointer" }}>
                    {s.garde ? "📌 Épinglé" : "Épingler"}</button>
                  <button onClick={() => restaurer(s)} disabled={!!snapBusy}
                    style={{ background: "rgba(163,113,247,.14)", border: "1px solid rgba(163,113,247,.5)", borderRadius: 8,
                      padding: "7px 12px", color: "#a371f7", fontSize: 12.5, fontWeight: 800,
                      cursor: snapBusy ? "default" : "pointer", opacity: snapBusy ? .6 : 1, whiteSpace: "nowrap" }}>
                    {busyR ? "Retour…" : "↩ Revenir"}</button>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}

window.SystemView = SystemView;
