// ============================================================================
// SÉCURITÉ — d'où se connecte chaque compte (propriétaire uniquement)
//
// POURQUOI CETTE PAGE EXISTE. Le 10/09/2026, quelqu'un a cree quatre comptes pour sonder
// l'app (Burp Collaborator + injection SQL). On n'a rien pu dire de lui : l'IP n'etait
// stockee nulle part. Depuis, chaque inscription et chaque connexion laisse une trace. Cette
// page repond a deux questions : « quelqu'un essaie-t-il d'entrer ? » et « mes VA se
// connectent-ils bien de chez eux, ou un compte a-t-il ete repris ailleurs ? ».
//
// CE QUE LA COULEUR NE DIT PAS. Un pays qui ne correspond pas n'est PAS une preuve : un VPN,
// un proxy (et vu le metier, les VA en utilisent), un voyage, suffisent. Le drapeau attire
// l'oeil, il n'accuse pas -- c'est a l'humain de trancher.
// ============================================================================
const PAYS_NOM = {
  FR: "France", MG: "Madagascar", BE: "Belgique", CH: "Suisse", CA: "Canada", US: "États-Unis",
  MA: "Maroc", DZ: "Algérie", TN: "Tunisie", CI: "Côte d'Ivoire", CM: "Cameroun", SN: "Sénégal",
  GB: "Royaume-Uni", DE: "Allemagne", ES: "Espagne", IT: "Italie", NL: "Pays-Bas", PT: "Portugal",
  RU: "Russie", UA: "Ukraine", IN: "Inde", PK: "Pakistan", NG: "Nigeria", RE: "La Réunion",
};
const paysNom = (c) => c ? (PAYS_NOM[c] || c) : "—";

function secAgo(iso) {
  if (!iso) return "jamais";
  const s = Math.floor((Date.now() - Date.parse(iso.replace(" ", "T") + "Z")) / 1000);
  if (isNaN(s)) return iso;
  if (s < 60) return "à l'instant";
  if (s < 3600) return Math.floor(s / 60) + " min";
  if (s < 86400) return Math.floor(s / 3600) + " h";
  return Math.floor(s / 86400) + " j";
}

function SecurityView() {
  const { useState, useEffect } = React;
  const [data, setData] = useState(null);
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);

  const charger = async () => {
    const r = await window.Backend.securityOverview();
    if (!r) { setErr("Accès refusé, ou aucune donnée encore."); setData({ comptes: [], recents: [] }); return; }
    setErr(""); setData(r);
  };
  useEffect(() => { charger(); const iv = setInterval(charger, 60000); return () => clearInterval(iv); }, []);

  const poserPays = async (id, val) => {
    setBusy(true);
    await window.Backend.patchUser(id, { expected_country: (val || "").toUpperCase().trim() || null });
    await charger(); setBusy(false);
  };
  // Rejeter un compte : le coupe A L'INSTANT (le worker refuse toute session « rejected »).
  // Reversible -- on peut le repasser « pending » ou l'accepter plus tard depuis Demandes.
  const rejeter = async (id, nom) => {
    if (!window.confirm("Rejeter « " + nom + " » ? Sa session est coupée immédiatement. Réversible.")) return;
    setBusy(true); await window.Backend.patchUser(id, { status: "rejected" }); await charger(); setBusy(false);
  };

  if (!data) return <div style={{ padding: 40, color: "var(--muted)" }}>Chargement…</div>;
  const comptes = data.comptes || [], recents = data.recents || [];
  const actifs = comptes.filter(c => c.status === "active");
  const enAttente = comptes.filter(c => c.status === "pending");

  // Un compte merite l'oeil si : plusieurs pays vus, OU un pays attendu non respecte.
  const suspect = (c) => (c.n_pays > 1) || (c.expected_country && c.last_country && c.expected_country !== c.last_country);

  const carte = { background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 12, padding: 14, marginBottom: 14 };
  const th = { textAlign: "left", fontSize: 10.5, fontWeight: 800, letterSpacing: ".05em", textTransform: "uppercase", color: "var(--muted)", padding: "6px 8px" };
  const td = { padding: "8px 8px", fontSize: 12.5, borderTop: "1px solid var(--border)", verticalAlign: "middle" };

  return (
    <div>
      <h1 style={{ margin: "0 0 4px", fontSize: 24, fontWeight: 700, letterSpacing: "-.01em" }}>🛡️ Sécurité</h1>
      <div style={{ fontSize: 12.5, color: "var(--muted)", marginBottom: 16 }}>
        D'où se connecte chaque compte. Le pays vient de Cloudflare (gratuit, sur chaque requête).
        Un pays qui ne colle pas <b>attire l'œil, il n'accuse pas</b> : VPN, proxy et voyages existent.
      </div>
      {err && <div style={{ ...carte, borderColor: "rgba(240,160,32,.45)", color: "#f0a020", fontSize: 12.5 }}>{err}</div>}

      {/* Comptes en attente : la porte d'entree d'un intrus. Mis en tete, avec le bouton Rejeter. */}
      {enAttente.length > 0 && (
        <div style={{ ...carte, borderColor: "rgba(248,81,73,.4)" }}>
          <div style={{ fontSize: 13, fontWeight: 800, color: "#f85149", marginBottom: 8 }}>
            ⚠️ {enAttente.length} compte(s) en attente — non validés, mais tracés</div>
          <table style={{ width: "100%", borderCollapse: "collapse" }}>
            <thead><tr><th style={th}>Compte</th><th style={th}>Inscrit depuis</th><th style={th}>Pays</th><th style={th}>IP</th><th style={th}></th></tr></thead>
            <tbody>
              {enAttente.map(c => (
                <tr key={c.id}>
                  <td style={td}><b>{c.name}</b><div className="mono" style={{ fontSize: 10.5, color: "var(--faint)" }}>{c.email}</div></td>
                  <td style={td}>{secAgo(c.last_seen)}</td>
                  <td style={td}>{paysNom(c.signup_country)}</td>
                  <td style={td}><span className="mono" style={{ fontSize: 11 }}>{c.last_ip || "—"}</span></td>
                  <td style={td}><button onClick={() => rejeter(c.id, c.name)} disabled={busy}
                    style={{ background: "rgba(248,81,73,.14)", border: "1px solid rgba(248,81,73,.45)", borderRadius: 8, padding: "5px 11px", color: "#f85149", fontSize: 12, fontWeight: 700, cursor: "pointer" }}>Rejeter</button></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* L'equipe : ou se connecte chacun, et est-ce coherent avec le pays attendu. */}
      <div style={carte}>
        <div style={{ fontSize: 13, fontWeight: 800, marginBottom: 8 }}>Équipe · {actifs.length} compte(s) actif(s)</div>
        <div style={{ overflowX: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 720 }}>
            <thead><tr>
              <th style={th}>Compte</th><th style={th}>Dernière connexion</th><th style={th}>Pays vu</th>
              <th style={th}>Pays attendu</th><th style={th}>Pays / IP</th><th style={th}>Dernière IP</th>
            </tr></thead>
            <tbody>
              {actifs.map(c => {
                const drapeau = suspect(c);
                return (
                  <tr key={c.id} style={drapeau ? { background: "rgba(240,160,32,.06)" } : null}>
                    <td style={td}>
                      {drapeau && <span title="À vérifier : plusieurs pays, ou pays différent de l'attendu">🚩 </span>}
                      <b>{c.name}</b> <span style={{ fontSize: 10.5, color: "var(--faint)" }}>· {c.role}</span>
                      <div className="mono" style={{ fontSize: 10.5, color: "var(--faint)" }}>{c.email}</div>
                    </td>
                    <td style={td}>{secAgo(c.last_seen)}</td>
                    <td style={td}>
                      {paysNom(c.last_country)}
                      {c.expected_country && c.last_country && c.expected_country !== c.last_country &&
                        <div style={{ fontSize: 10.5, color: "#f0a020" }}>≠ attendu</div>}
                    </td>
                    <td style={td}>
                      <input defaultValue={c.expected_country || ""} placeholder="—" maxLength={2}
                        onBlur={e => { const v = e.target.value.toUpperCase().trim(); if (v !== (c.expected_country || "")) poserPays(c.id, v); }}
                        style={{ width: 46, textAlign: "center", textTransform: "uppercase", background: "var(--surface-2)", color: "var(--text)", border: "1px solid var(--border)", borderRadius: 7, padding: "4px 6px", fontSize: 12 }}
                        title="Code pays à 2 lettres (FR, MG…). Laisse vide pour ne pas surveiller ce compte." />
                    </td>
                    <td style={td}>
                      <span style={{ color: c.n_pays > 1 ? "#f0a020" : "var(--muted)" }}>{c.n_pays || 0} pays</span>
                      {c.pays ? <span style={{ fontSize: 10.5, color: "var(--faint)" }}> · {c.pays}</span> : null}
                      <span style={{ color: "var(--muted)" }}> · {c.n_ip || 0} IP</span>
                    </td>
                    <td style={td}><span className="mono" style={{ fontSize: 11 }}>{c.last_ip || "—"}</span></td>
                  </tr>
                );
              })}
              {!actifs.length && <tr><td style={td} colSpan={6}>
                <span style={{ color: "var(--faint)" }}>Aucune connexion tracée pour l'instant — les traces se remplissent au fur et à mesure que l'équipe se connecte.</span></td></tr>}
            </tbody>
          </table>
        </div>
      </div>

      {/* Le journal brut : une vague d'inscriptions rapprochees du meme genre saute aux yeux ici. */}
      <div style={carte}>
        <div style={{ fontSize: 13, fontWeight: 800, marginBottom: 8 }}>Dernières connexions & inscriptions</div>
        <div style={{ overflowX: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 680 }}>
            <thead><tr><th style={th}>Quand</th><th style={th}>Type</th><th style={th}>Compte</th><th style={th}>Pays</th><th style={th}>IP</th><th style={th}>Opérateur / réseau</th></tr></thead>
            <tbody>
              {recents.map((e, i) => (
                <tr key={i} style={e.status === "pending" || e.status === "rejected" ? { background: "rgba(248,81,73,.05)" } : null}>
                  <td style={td}>{secAgo(e.at)}</td>
                  <td style={td}><span style={{ fontSize: 11, color: e.kind && e.kind.indexOf("register") === 0 ? "#f0a020" : "var(--muted)" }}>{e.kind}</span></td>
                  <td style={td}>{e.name || <span style={{ color: "var(--faint)" }}>compte supprimé</span>}<div className="mono" style={{ fontSize: 10, color: "var(--faint)" }}>{e.email || ""}</div></td>
                  <td style={td}>{paysNom(e.country)}{e.city ? <span style={{ fontSize: 10.5, color: "var(--faint)" }}> · {e.city}</span> : null}</td>
                  <td style={td}><span className="mono" style={{ fontSize: 11 }}>{e.ip || "—"}</span></td>
                  <td style={td}><span style={{ fontSize: 11, color: "var(--faint)" }}>{e.asn || ""}</span></td>
                </tr>
              ))}
              {!recents.length && <tr><td style={td} colSpan={6}><span style={{ color: "var(--faint)" }}>Rien encore.</span></td></tr>}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

window.SecurityView = SecurityView;
