// ============================================================================
// BUG REPORT — petit bouton flottant (haut-droite), sur toutes les pages.
//
// But : quand quelque chose casse dans l'app, l'owner clique, obtient un rapport
// DEJA REMPLI avec la PROVENANCE de l'erreur (page, version, role, et surtout les
// dernieres erreurs JS captees en direct : message + fichier + ligne + stack), le
// copie, et me le colle. On gagne l'aller-retour « c'est quoi l'erreur exacte ? ».
//
// Rien n'est envoye nulle part : c'est du presse-papier, point. (Aucune donnee de
// compte n'est incluse — que du diagnostic technique.)
//
// LE BUFFER D'ERREURS s'installe AU CHARGEMENT du script (tout en bas), donc il
// attrape les erreurs meme survenues avant que le panneau soit ouvert.
// ============================================================================

const BUG_VERSION = "v1.2.0";
const BUG_MAX = 25;   // on ne garde que les 25 dernieres erreurs (buffer glissant)

// ---- Buffer global : window.__BUG_LOG = [{ at, type, msg, src, stack }] ----
function installBugBuffer() {
  if (typeof window === "undefined" || window.__BUG_LOG_INSTALLED) return;
  window.__BUG_LOG_INSTALLED = true;
  window.__BUG_LOG = window.__BUG_LOG || [];
  const pousser = (e) => {
    try {
      window.__BUG_LOG.push(e);
      if (window.__BUG_LOG.length > BUG_MAX) window.__BUG_LOG.splice(0, window.__BUG_LOG.length - BUG_MAX);
    } catch (_) {}
  };
  const hhmmss = () => { try { return new Date().toTimeString().slice(0, 8); } catch (_) { return ""; } };

  // 1) erreurs JS non rattrapees
  window.addEventListener("error", (ev) => {
    // ev.error peut manquer (erreurs cross-origin) : on retombe sur message/filename
    const err = ev && ev.error;
    pousser({
      at: hhmmss(), type: "error",
      msg: (err && err.message) || (ev && ev.message) || "erreur inconnue",
      src: (ev && ev.filename ? shortSrc(ev.filename) + ":" + ev.lineno + ":" + ev.colno : ""),
      stack: (err && err.stack) ? String(err.stack).split("\n").slice(0, 6).join("\n") : "",
    });
  });
  // 2) promesses rejetees sans catch
  window.addEventListener("unhandledrejection", (ev) => {
    const r = ev && ev.reason;
    pousser({
      at: hhmmss(), type: "promesse",
      msg: (r && r.message) || String(r || "rejet sans raison"),
      src: "", stack: (r && r.stack) ? String(r.stack).split("\n").slice(0, 6).join("\n") : "",
    });
  });
  // 3) console.error (souvent la ou React/notre code signale un souci sans throw)
  try {
    const orig = console.error;
    console.error = function (...a) {
      pousser({ at: hhmmss(), type: "console", msg: a.map(x => safeStr(x)).join(" ").slice(0, 500), src: "", stack: "" });
      return orig.apply(console, a);
    };
  } catch (_) {}
}
function shortSrc(u) { try { const i = u.indexOf("/app/"); return i >= 0 ? u.slice(i + 1).split("?")[0] : u.split("/").pop().split("?")[0]; } catch (_) { return u; } }
function safeStr(x) { try { return typeof x === "string" ? x : (x instanceof Error ? (x.message + (x.stack ? "\n" + x.stack.split("\n").slice(0,4).join("\n") : "")) : JSON.stringify(x)); } catch (_) { return String(x); } }

// ---- Construit le texte du rapport (ce qui sera copie) ----
function construireRapport({ page, user, role, note }) {
  const now = (() => { try { return new Date().toISOString().slice(0, 19).replace("T", " "); } catch (_) { return ""; } })();
  const env = (typeof location !== "undefined" && (location.hostname === "localhost" || location.hostname === "127.0.0.1"))
    ? "app locale (" + location.hostname + ")" : "web (" + (typeof location !== "undefined" ? location.hostname : "?") + ")";
  const ecran = (typeof window !== "undefined") ? (window.innerWidth + "×" + window.innerHeight) : "?";
  const ua = (typeof navigator !== "undefined") ? navigator.userAgent : "?";
  const qui = (user && user.name ? user.name : "?") + (role ? " (" + role + ")" : "");
  const errs = (window.__BUG_LOG || []).slice().reverse();

  const L = [];
  L.push("=== PhoneLabs — Rapport de bug ===");
  L.push("Date        : " + now);
  L.push("Page        : " + (page || "?"));
  L.push("Version      : " + BUG_VERSION);
  L.push("Utilisateur : " + qui);
  L.push("Environnement: " + env);
  L.push("Écran        : " + ecran);
  L.push("Navigateur  : " + ua);
  if (note && note.trim()) { L.push(""); L.push("--- Ce que je faisais / le problème ---"); L.push(note.trim()); }
  L.push("");
  if (!errs.length) {
    L.push("--- Erreurs JS captées : aucune ---");
    L.push("(Si le bug est visuel/comportemental sans erreur console, décris-le ci-dessus.)");
  } else {
    L.push("--- Dernières erreurs JS captées (" + errs.length + ", plus récente en premier) ---");
    errs.forEach((e, i) => {
      L.push("[" + e.at + "] (" + e.type + ") " + e.msg);
      if (e.src) L.push("    → " + e.src);
      if (e.stack) L.push(e.stack.split("\n").map(s => "    " + s.trim()).join("\n"));
      if (i < errs.length - 1) L.push("");
    });
  }
  return L.join("\n");
}

function BugReport({ page, user, role }) {
  const { useState } = React;
  const [open, setOpen] = useState(false);
  const [note, setNote] = useState("");
  const [copied, setCopied] = useState(false);
  const nErr = (typeof window !== "undefined" && window.__BUG_LOG) ? window.__BUG_LOG.length : 0;

  const texte = () => construireRapport({ page, user, role, note });
  const copier = async () => {
    const t = texte();
    try { await navigator.clipboard.writeText(t); setCopied(true); setTimeout(() => setCopied(false), 2500); }
    catch (_) {
      // repli : selection dans un textarea temporaire
      try {
        const ta = document.createElement("textarea"); ta.value = t; document.body.appendChild(ta);
        ta.select(); document.execCommand("copy"); document.body.removeChild(ta);
        setCopied(true); setTimeout(() => setCopied(false), 2500);
      } catch (_) {}
    }
  };

  const btnFlottant = {
    position: "fixed", top: 14, right: 16, zIndex: 9000,
    display: "inline-flex", alignItems: "center", gap: 7, padding: "8px 12px",
    background: nErr ? "rgba(248,81,73,.14)" : "var(--surface-2)",
    border: "1px solid " + (nErr ? "rgba(248,81,73,.5)" : "var(--border)"),
    borderRadius: 10, color: nErr ? "#f85149" : "var(--muted)", fontSize: 12.5, fontWeight: 700,
    cursor: "pointer", boxShadow: "var(--shadow)", backdropFilter: "blur(6px)",
  };

  return (
    <>
      {!open && (
        <button style={btnFlottant} onClick={() => setOpen(true)} data-sfx="none"
          title="Signaler un bug — génère un rapport prêt à coller">
          🐛 <span>Bug</span>
          {nErr > 0 && <span style={{ fontSize: 10.5, fontWeight: 800, padding: "0 6px", borderRadius: 99,
            background: "#f85149", color: "#fff" }}>{nErr}</span>}
        </button>
      )}
      {open && (
        <div style={{ position: "fixed", inset: 0, zIndex: 9001, background: "rgba(0,0,0,.45)", display: "flex",
          alignItems: "flex-start", justifyContent: "flex-end", padding: 16 }}
          onClick={(e) => { if (e.target === e.currentTarget) setOpen(false); }}>
          <div style={{ width: 460, maxWidth: "94vw", maxHeight: "92vh", overflow: "auto", background: "var(--bg-2)",
            border: "1px solid var(--border)", borderRadius: 14, padding: 18, boxShadow: "var(--shadow)" }}>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 10 }}>
              <div style={{ fontSize: 16, fontWeight: 800 }}>🐛 Signaler un bug</div>
              <button onClick={() => setOpen(false)} title="Fermer" style={{ background: "none", border: "none",
                color: "var(--faint)", fontSize: 20, cursor: "pointer", lineHeight: 1 }}>×</button>
            </div>
            <div style={{ fontSize: 12, color: "var(--muted)", lineHeight: 1.55, marginBottom: 12 }}>
              {nErr > 0
                ? <><b style={{ color: "#f85149" }}>{nErr} erreur(s)</b> captée(s) sur cette session. Décris ce que tu faisais, puis copie — je récupère la provenance exacte.</>
                : <>Aucune erreur JS captée pour l'instant. Si le souci est visuel ou comportemental, décris-le ci-dessous puis copie.</>}
            </div>
            <textarea value={note} onChange={(e) => setNote(e.target.value)}
              placeholder="Ce que je faisais, ce qui devait se passer, ce qui s'est passé…"
              style={{ width: "100%", minHeight: 74, boxSizing: "border-box", padding: "9px 11px", borderRadius: 9,
                border: "1px solid var(--border)", background: "var(--surface-2)", color: "var(--text)",
                fontSize: 13, resize: "vertical", outline: "none", fontFamily: "inherit" }} />
            <div style={{ display: "flex", gap: 9, marginTop: 12 }}>
              <button onClick={copier} style={{ flex: 1, background: "var(--accent)", border: "none", borderRadius: 10,
                padding: "11px 14px", color: "#04130c", fontSize: 13.5, fontWeight: 800, cursor: "pointer" }}>
                {copied ? "✓ Copié — colle-le-moi" : "Copier le rapport"}</button>
              <button onClick={() => setOpen(false)} style={{ background: "var(--surface-2)", border: "1px solid var(--border)",
                borderRadius: 10, padding: "11px 14px", color: "var(--muted)", fontSize: 13, fontWeight: 700, cursor: "pointer" }}>
                Annuler</button>
            </div>
            {/* Aperçu du rapport : l'owner voit exactement ce qu'il copie (rien de caché). */}
            <div style={{ fontSize: 11, color: "var(--faint)", margin: "14px 0 5px", fontWeight: 700, letterSpacing: ".04em", textTransform: "uppercase" }}>Aperçu</div>
            <pre style={{ margin: 0, padding: 11, background: "var(--surface)", border: "1px solid var(--border)",
              borderRadius: 9, fontSize: 10.5, lineHeight: 1.5, color: "var(--muted)", whiteSpace: "pre-wrap",
              wordBreak: "break-word", maxHeight: 260, overflow: "auto" }}>{texte()}</pre>
          </div>
        </div>
      )}
    </>
  );
}

installBugBuffer();      // <- s'arme des le chargement du script
window.BugReport = BugReport;
window.__bugConstruireRapport = construireRapport;   // exposé pour le banc de test
