/* global React, Icon */
const { useState: useStateP, useEffect: useEffectP } = React;

// ==================== PROFILE ====================
function ProfileScreen({ t, lang, setLang }) {
  const [profile, setProfile] = useStateP(null);
  const [loading, setLoading] = useStateP(true);
  const [err, setErr]         = useStateP(null);

  // Form state
  const [fullName, setFullName] = useStateP("");
  const [locale,   setLocaleVal] = useStateP("fr");
  const [savingProfile, setSavingProfile] = useStateP(false);
  const [profileMsg, setProfileMsg]       = useStateP(null);

  // Password change
  const [pwd1, setPwd1] = useStateP("");
  const [pwd2, setPwd2] = useStateP("");
  const [savingPwd, setSavingPwd] = useStateP(false);
  const [pwdMsg,  setPwdMsg]      = useStateP(null);

  // Default display currency (via the same hook used by the topbar)
  const { currency, setCurrency, rates } = window.melr.useCurrency();

  useEffectP(() => {
    let cancelled = false;
    (async () => {
      try {
        const p = await window.melr.currentProfile();
        if (cancelled) return;
        if (!p) { setErr("not_logged_in"); setLoading(false); return; }
        setProfile(p);
        setFullName(p.full_name || "");
        setLocaleVal(p.locale || "fr");
      } catch (e) {
        if (!cancelled) setErr(e.message);
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  if (loading) return <div className="page"><div className="page-body" style={{ padding: 40 }}>{lang === "fr" ? "Chargement du profil…" : "Loading profile…"}</div></div>;
  if (err === "not_logged_in") return <div className="page"><div className="page-body" style={{ padding: 40, color: "#b91c1c" }}>{lang === "fr" ? "Connectez-vous pour accéder à votre profil." : "Sign in to access your profile."}</div></div>;

  const saveProfile = async (e) => {
    e.preventDefault();
    setProfileMsg(null); setSavingProfile(true);
    try {
      const patch = { full_name: fullName.trim(), locale };
      const updated = await window.melr.updateProfile(patch);
      setProfile(updated);
      // Sync the global language toggle if it changed
      if (setLang && locale !== lang) setLang(locale);
      setProfileMsg({ tone: "success", text: lang === "fr" ? "Profil mis à jour." : "Profile updated." });
    } catch (e2) {
      setProfileMsg({ tone: "danger", text: e2.message });
    } finally {
      setSavingProfile(false);
    }
  };

  const savePwd = async (e) => {
    e.preventDefault();
    setPwdMsg(null);
    if (pwd1.length < 6) { setPwdMsg({ tone: "danger", text: lang === "fr" ? "Min. 6 caractères." : "Min 6 characters." }); return; }
    if (pwd1 !== pwd2)   { setPwdMsg({ tone: "danger", text: lang === "fr" ? "Les deux mots de passe ne correspondent pas." : "Passwords don't match." }); return; }
    setSavingPwd(true);
    try {
      await window.melr.changePassword(pwd1);
      setPwd1(""); setPwd2("");
      setPwdMsg({ tone: "success", text: lang === "fr" ? "Mot de passe modifié." : "Password changed." });
    } catch (e2) {
      setPwdMsg({ tone: "danger", text: e2.message });
    } finally {
      setSavingPwd(false);
    }
  };

  const inp = { padding: "8px 10px", borderRadius: 6, border: "1px solid var(--line)", fontSize: 13, background: "var(--bg, white)", color: "var(--text, #111)" };
  const lbl = { fontSize: 11, opacity: 0.75 };

  return (
    <div className="page">
      <div className="page-header">
        <div className="page-eyebrow">{lang === "fr" ? "MON COMPTE" : "MY ACCOUNT"}</div>
        <div className="page-header-row">
          <div>
            <h1 className="page-title">{lang === "fr" ? "Mon profil" : "My profile"}</h1>
            <div className="page-sub">{profile && profile.email}</div>
          </div>
        </div>
      </div>

      <div className="page-body" style={{ display: "grid", gap: 18, gridTemplateColumns: "1fr 1fr" }}>

        {/* === Informations === */}
        <form onSubmit={saveProfile} className="card" style={{ padding: 20 }}>
          <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 12 }}>
            {lang === "fr" ? "Informations" : "Information"}
          </div>
          <div style={{ display: "grid", gap: 10 }}>
            <label style={{ display: "grid", gap: 4 }}>
              <span style={lbl}>{lang === "fr" ? "Nom complet" : "Full name"}</span>
              <input value={fullName} onChange={(e) => setFullName(e.target.value)} required style={inp} />
            </label>
            <label style={{ display: "grid", gap: 4 }}>
              <span style={lbl}>{lang === "fr" ? "Email" : "Email"}</span>
              <input value={profile.email || ""} disabled style={{ ...inp, opacity: 0.6, cursor: "not-allowed" }} />
            </label>
            <label style={{ display: "grid", gap: 4 }}>
              <span style={lbl}>{lang === "fr" ? "Langue par défaut" : "Default language"}</span>
              <select value={locale} onChange={(e) => setLocaleVal(e.target.value)} style={inp}>
                <option value="fr">Français</option>
                <option value="en">English</option>
              </select>
            </label>
            {profile.organization_id ? (
              <div className="text-faint" style={{ fontSize: 12 }}>
                <Icon.check className="xxs" /> {lang === "fr" ? "Membre de l'organisation REFT Africa" : "Member of REFT Africa"}
              </div>
            ) : (
              <div style={{ color: "#92400e", fontSize: 12 }}>
                <Icon.info className="xxs" /> {lang === "fr"
                  ? "Votre compte n'est pas encore rattaché à une organisation. Demandez à un administrateur de vous ajouter."
                  : "Your account is not yet assigned to an organization. Ask an admin to add you."}
              </div>
            )}
            {profileMsg && (
              <div style={{
                marginTop: 4, padding: "8px 10px", borderRadius: 6, fontSize: 12,
                background: profileMsg.tone === "success" ? "#dcfce7" : "#fee2e2",
                color:      profileMsg.tone === "success" ? "#166534" : "#991b1b",
              }}>{profileMsg.text}</div>
            )}
            <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 4 }}>
              <button type="submit" disabled={savingProfile}
                style={{ padding: "8px 14px", borderRadius: 6, border: 0, background: "#2563eb", color: "white", cursor: "pointer", fontWeight: 600 }}>
                {savingProfile ? "…" : (lang === "fr" ? "Enregistrer" : "Save")}
              </button>
            </div>
          </div>
        </form>

        {/* === Devise préférée === */}
        <div className="card" style={{ padding: 20 }}>
          <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 12 }}>
            {lang === "fr" ? "Devise d'affichage préférée" : "Preferred display currency"}
          </div>
          <div className="text-faint" style={{ fontSize: 12, marginBottom: 12 }}>
            {lang === "fr"
              ? "Choisissez la devise dans laquelle les montants sont affichés sur tous les écrans (Dashboard, Projets, Détail, etc.). Cette préférence est sauvegardée sur votre navigateur."
              : "Pick the currency for amounts shown across all screens. The choice is saved on your browser."}
          </div>
          <div style={{ display: "grid", gap: 6 }}>
            {Object.entries(rates).map(([code, meta]) => (
              <button key={code} type="button"
                onClick={() => setCurrency(code)}
                className={"btn sm" + (code === currency ? " primary" : "")}
                style={{ justifyContent: "flex-start", textAlign: "left" }}>
                <span className="mono" style={{ width: 50, fontWeight: 600 }}>{code}</span>
                <span style={{ flex: 1 }}>{meta.name}</span>
                <span className="text-faint" style={{ fontSize: 11 }}>1 EUR = {meta.rate} {meta.symbol}</span>
                {code === currency && <Icon.check className="xxs" />}
              </button>
            ))}
          </div>
          <div className="text-faint" style={{ fontSize: 11, marginTop: 10 }}>
            {lang === "fr" ? "Vous pouvez ajouter d'autres devises depuis le sélecteur dans la barre du haut." : "You can add more currencies from the topbar selector."}
          </div>
        </div>

        {/* === Mot de passe === */}
        <form onSubmit={savePwd} className="card" style={{ padding: 20 }}>
          <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 12 }}>
            {lang === "fr" ? "Changer le mot de passe" : "Change password"}
          </div>
          <div style={{ display: "grid", gap: 10 }}>
            <label style={{ display: "grid", gap: 4 }}>
              <span style={lbl}>{lang === "fr" ? "Nouveau mot de passe" : "New password"}</span>
              <input type="password" value={pwd1} onChange={(e) => setPwd1(e.target.value)}
                autoComplete="new-password" required minLength={6} style={inp} />
            </label>
            <label style={{ display: "grid", gap: 4 }}>
              <span style={lbl}>{lang === "fr" ? "Confirmer" : "Confirm"}</span>
              <input type="password" value={pwd2} onChange={(e) => setPwd2(e.target.value)}
                autoComplete="new-password" required minLength={6} style={inp} />
            </label>
            {pwdMsg && (
              <div style={{
                padding: "8px 10px", borderRadius: 6, fontSize: 12,
                background: pwdMsg.tone === "success" ? "#dcfce7" : "#fee2e2",
                color:      pwdMsg.tone === "success" ? "#166534" : "#991b1b",
              }}>{pwdMsg.text}</div>
            )}
            <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 4 }}>
              <button type="submit" disabled={savingPwd}
                style={{ padding: "8px 14px", borderRadius: 6, border: 0, background: "#7c3aed", color: "white", cursor: "pointer", fontWeight: 600 }}>
                {savingPwd ? "…" : (lang === "fr" ? "Modifier" : "Update")}
              </button>
            </div>
          </div>
        </form>

        {/* === Sécurité · 2FA === */}
        <SecuritySection lang={lang} />

        {/* === Notifications par email (D8 · digest) === */}
        <NotificationsSection lang={lang} />

        {/* === Session === */}
        <div className="card" style={{ padding: 20 }}>
          <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 12 }}>
            {lang === "fr" ? "Session" : "Session"}
          </div>
          <div style={{ display: "grid", gap: 8 }}>
            <div className="text-faint" style={{ fontSize: 12 }}>
              {lang === "fr" ? "Vous êtes connecté en tant que" : "Signed in as"} <b>{profile.email}</b>
            </div>
            <button type="button"
              onClick={async () => { await window.melr.supabase.auth.signOut(); }}
              style={{ padding: "8px 14px", borderRadius: 6, border: "1px solid #b91c1c", background: "#dc2626", color: "white", cursor: "pointer", marginTop: 8, alignSelf: "flex-start", fontWeight: 500 }}>
              <Icon.logout className="xxs" /> {lang === "fr" ? "Se déconnecter" : "Sign out"}
            </button>
          </div>
        </div>

      </div>
    </div>
  );
}

// ============================================================================
// SecuritySection · 2FA TOTP (C1)
// ----------------------------------------------------------------------------
// Liste les facteurs MFA actifs et permet d'en activer un nouveau via
// modal QR + vérification du code à 6 chiffres.
// ============================================================================
function SecuritySection({ lang }) {
  const T = (fr, en) => (lang === "fr" ? fr : en);
  const [factors, setFactors] = useStateP({ totp: [], all: [] });
  const [loading, setLoading] = useStateP(true);
  const [enrollOpen, setEnrollOpen] = useStateP(false);
  const [busy, setBusy] = useStateP(false);
  const [err, setErr] = useStateP(null);

  const refresh = async () => {
    setLoading(true); setErr(null);
    try {
      const f = await window.melr.mfaListFactors();
      setFactors(f);
    } catch (e) { setErr(e.message); }
    finally { setLoading(false); }
  };
  useEffectP(() => { refresh(); }, []);

  // Filtre les facteurs « verified » uniquement — les unverified sont
  // des enrollments abandonnés qu'on peut nettoyer.
  const verifiedTotp = (factors.totp || []).filter((f) => f.status === "verified");
  const unverifiedTotp = (factors.totp || []).filter((f) => f.status !== "verified");

  const onUnenroll = async (factorId) => {
    if (!window.confirm(T(
      "Désactiver la 2FA ? Vous pourrez vous reconnecter sans code, mais votre compte sera moins sécurisé.",
      "Disable 2FA? You'll be able to sign in without a code, but your account will be less secure."
    ))) return;
    setBusy(true); setErr(null);
    try { await window.melr.mfaUnenroll(factorId); await refresh(); }
    catch (e) { setErr(e.message); }
    finally { setBusy(false); }
  };

  const onCleanupUnverified = async (factorId) => {
    setBusy(true); setErr(null);
    try { await window.melr.mfaUnenroll(factorId); await refresh(); }
    catch (e) { setErr(e.message); }
    finally { setBusy(false); }
  };

  return (
    <div className="card" style={{ padding: 20 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }}>
        <div style={{ fontSize: 15, fontWeight: 600 }}>
          🔒 {T("Sécurité · Authentification à deux facteurs (2FA)", "Security · Two-factor authentication (2FA)")}
        </div>
        {verifiedTotp.length === 0 && !loading && (
          <button type="button" className="btn sm primary" onClick={() => setEnrollOpen(true)} disabled={busy}>
            <Icon.shieldCheck /> {T("Activer 2FA", "Enable 2FA")}
          </button>
        )}
      </div>

      <div className="text-faint" style={{ fontSize: 12, marginBottom: 12 }}>
        {T(
          "La 2FA ajoute un code à 6 chiffres généré par votre téléphone à chaque connexion. Recommandé pour les comptes ayant accès à des données sensibles (santé, finances).",
          "2FA adds a 6-digit code generated by your phone on each sign-in. Recommended for accounts with access to sensitive data (health, financial)."
        )}
      </div>

      {loading ? (
        <div className="text-faint" style={{ fontSize: 12 }}>{T("Chargement…", "Loading…")}</div>
      ) : verifiedTotp.length > 0 ? (
        <div>
          {verifiedTotp.map((f) => (
            <div key={f.id} style={{
              display: "flex", alignItems: "center", gap: 10,
              padding: "10px 12px", background: "#dcfce7",
              border: "1px solid #86efac", borderRadius: 6,
            }}>
              <span style={{ fontSize: 18 }}>✅</span>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 500, fontSize: 13 }}>
                  {T("2FA activée", "2FA enabled")}{f.friendly_name ? " · " + f.friendly_name : ""}
                </div>
                <div className="text-faint" style={{ fontSize: 11, marginTop: 2 }}>
                  {T("Activée le ", "Enabled on ")}{f.created_at ? new Date(f.created_at).toLocaleDateString() : "?"}
                </div>
              </div>
              <button className="btn xs ghost" onClick={() => onUnenroll(f.id)} disabled={busy}
                style={{ color: "#b91c1c" }}>
                {T("Désactiver", "Disable")}
              </button>
            </div>
          ))}
        </div>
      ) : (
        <div className="text-faint" style={{ fontSize: 12, padding: "10px 12px", background: "var(--bg-sunken)", borderRadius: 6 }}>
          {T(
            "Aucune authentification à deux facteurs configurée. Cliquez « Activer 2FA » pour démarrer.",
            "No two-factor authentication set up. Click 'Enable 2FA' to get started."
          )}
        </div>
      )}

      {/* Nettoyage des factors non-vérifiés (enrollment abandonné) */}
      {unverifiedTotp.length > 0 && (
        <div style={{ marginTop: 8, fontSize: 11, color: "var(--text-faint)" }}>
          {T("Enrollment(s) en attente : ", "Pending enrollment(s): ")}
          {unverifiedTotp.map((f) => (
            <button key={f.id} className="btn xs ghost" onClick={() => onCleanupUnverified(f.id)} disabled={busy}
              style={{ marginLeft: 4, fontSize: 10 }}>
              ✕ {T("nettoyer", "cleanup")}
            </button>
          ))}
        </div>
      )}

      {err && (
        <div style={{ marginTop: 10, padding: 8, background: "#fee2e2", color: "#991b1b", borderRadius: 5, fontSize: 12 }}>
          ⚠ {err}
        </div>
      )}

      {enrollOpen && (
        <Enable2FAModal lang={lang} onClose={() => setEnrollOpen(false)}
          onCompleted={async () => { setEnrollOpen(false); await refresh(); }} />
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Enable2FAModal · 2-step enrollment (QR scan + verify code)
// ─────────────────────────────────────────────────────────────────────
function Enable2FAModal({ lang, onClose, onCompleted }) {
  const Modal = window.Modal;
  const T = (fr, en) => (lang === "fr" ? fr : en);
  const [step, setStep] = useStateP("init"); // init → qr → success
  const [enrollment, setEnrollment] = useStateP(null); // { factorId, qrCode, secret, uri }
  const [code, setCode] = useStateP("");
  const [busy, setBusy] = useStateP(false);
  const [err, setErr] = useStateP(null);

  useEffectP(() => {
    // Au montage : démarre l'enrollment côté Supabase (génère QR + secret)
    let cancelled = false;
    (async () => {
      setBusy(true); setErr(null);
      try {
        const e = await window.melr.mfaEnroll();
        if (!cancelled) { setEnrollment(e); setStep("qr"); }
      } catch (ex) { if (!cancelled) setErr(ex.message); }
      finally { if (!cancelled) setBusy(false); }
    })();
    return () => { cancelled = true; };
  }, []);

  const verify = async () => {
    if (!code || code.length < 6) {
      setErr(T("Entrez le code à 6 chiffres affiché par votre app.", "Enter the 6-digit code shown by your app."));
      return;
    }
    setBusy(true); setErr(null);
    try {
      await window.melr.mfaVerify(enrollment.factorId, code);
      setStep("success");
      // Court délai pour montrer le succès, puis ferme.
      setTimeout(() => { onCompleted(); }, 1500);
    } catch (e) { setErr(e.message); setBusy(false); }
  };

  const copySecret = () => {
    if (enrollment && enrollment.secret) {
      try { navigator.clipboard.writeText(enrollment.secret); } catch (_) {}
    }
  };

  return (
    <Modal title={T("Activer la 2FA", "Enable 2FA")} onClose={busy && step !== "qr" ? null : onClose} size="md"
      footer={step === "qr" ? <>
        <button className="btn sm" onClick={onClose} disabled={busy}>{T("Annuler", "Cancel")}</button>
        <button className="btn sm primary" onClick={verify} disabled={busy || !code || code.length < 6}>
          {busy ? "…" : T("Vérifier", "Verify")}
        </button>
      </> : <button className="btn sm" onClick={onClose}>{T("Fermer", "Close")}</button>}>
      {step === "init" && (
        <div style={{ padding: 20, textAlign: "center", color: "var(--text-faint)" }}>
          {T("Génération du QR code…", "Generating QR code…")}
        </div>
      )}

      {step === "qr" && enrollment && (
        <div style={{ display: "grid", gap: 14, fontSize: 13 }}>
          <div>
            <strong>1. {T("Scannez ce QR code", "Scan this QR code")}</strong>
            <div className="text-faint" style={{ fontSize: 11.5, marginTop: 2 }}>
              {T(
                "Ouvrez une app d'authentification (Google Authenticator, Authy, 1Password, Microsoft Authenticator…) et scannez :",
                "Open an authenticator app (Google Authenticator, Authy, 1Password, Microsoft Authenticator…) and scan:"
              )}
            </div>
            <div style={{
              marginTop: 10, padding: 16, background: "white",
              borderRadius: 8, border: "1px solid var(--line)",
              display: "flex", justifyContent: "center",
            }}>
              {/* enrollment.qrCode est un data:image/svg+xml;... */}
              <img src={enrollment.qrCode} alt="QR code 2FA"
                style={{ width: 200, height: 200 }} />
            </div>
            <details style={{ marginTop: 8, fontSize: 11 }}>
              <summary style={{ cursor: "pointer", color: "var(--text-faint)" }}>
                {T("Vous ne pouvez pas scanner ? Entrer le code manuellement", "Can't scan? Enter the code manually")}
              </summary>
              <div style={{ marginTop: 6, padding: 8, background: "var(--bg-sunken)", borderRadius: 4, fontFamily: "monospace", fontSize: 12, wordBreak: "break-all" }}>
                {enrollment.secret}
                <button className="btn xs ghost" onClick={copySecret} style={{ marginLeft: 8 }}>
                  {T("Copier", "Copy")}
                </button>
              </div>
            </details>
          </div>

          <div>
            <strong>2. {T("Entrez le code à 6 chiffres", "Enter the 6-digit code")}</strong>
            <div className="text-faint" style={{ fontSize: 11.5, marginTop: 2, marginBottom: 6 }}>
              {T(
                "Une fois le QR scanné, votre app affiche un code qui change toutes les 30 s.",
                "Once the QR is scanned, your app shows a code that changes every 30s."
              )}
            </div>
            <input type="text" inputMode="numeric" pattern="\d{6}" maxLength={6} autoFocus
              value={code} onChange={(e) => setCode(e.target.value.replace(/\D/g, ""))}
              placeholder="123456"
              style={{
                fontSize: 24, fontFamily: "monospace", letterSpacing: "0.3em",
                textAlign: "center", padding: "10px 12px", width: "100%",
                borderRadius: 6, border: "1px solid var(--line)",
                background: "var(--bg, white)", color: "var(--text)",
                boxSizing: "border-box",
              }}
              onKeyDown={(e) => { if (e.key === "Enter" && code.length === 6) verify(); }} />
          </div>

          {err && (
            <div style={{ padding: 8, background: "#fee2e2", color: "#991b1b", borderRadius: 5, fontSize: 12 }}>
              ⚠ {err}
            </div>
          )}

          <div style={{ padding: 10, background: "#fef3c7", color: "#a16207", borderRadius: 6, fontSize: 11.5 }}>
            ⚠ <strong>{T("Important :", "Important:")}</strong> {T(
              "Conservez le code secret ou les codes de récupération de votre app. Sans accès à votre téléphone, vous ne pourrez plus vous connecter.",
              "Keep the secret or recovery codes from your app safe. Without access to your phone, you won't be able to sign in."
            )}
          </div>
        </div>
      )}

      {step === "success" && (
        <div style={{ padding: 30, textAlign: "center" }}>
          <div style={{ fontSize: 48 }}>✅</div>
          <div style={{ fontSize: 18, fontWeight: 600, marginTop: 8 }}>
            {T("2FA activée !", "2FA enabled!")}
          </div>
          <div className="text-faint" style={{ fontSize: 12, marginTop: 6 }}>
            {T(
              "À votre prochaine connexion, après le mot de passe, votre app vous demandera un code.",
              "On your next sign-in, after your password, your app will ask for a code."
            )}
          </div>
        </div>
      )}

      {err && step === "init" && (
        <div style={{ padding: 8, background: "#fee2e2", color: "#991b1b", borderRadius: 5, fontSize: 12, marginTop: 10 }}>
          ⚠ {err}
        </div>
      )}
    </Modal>
  );
}

// ============================================================================
// NotificationsSection · D8 · préférences digest email
// ----------------------------------------------------------------------------
// L'utilisateur choisit :
//   - fréquence (off / quotidien / hebdomadaire)
//   - catégories (cases à cocher)
//   - heure locale d'envoi (slider 0-23)
//   - timezone (auto-détectée, modifiable)
// Bouton "Tester maintenant" : appelle l'Edge Function send-digest pour
// l'utilisateur courant. Bouton "Aperçu" : montre le payload jsonb que
// la RPC build_user_digest générerait sur les 7 derniers jours.
// ============================================================================
const ALL_CATEGORIES = [
  { id: "new_projects",         fr: "Nouveaux projets",                en: "New projects" },
  { id: "new_indicators",       fr: "Nouveaux indicateurs",            en: "New indicators" },
  { id: "new_activities",       fr: "Nouvelles activités",             en: "New activities" },
  { id: "validations_pending",  fr: "Validations en attente",          en: "Pending validations" },
  { id: "mentions",             fr: "Mentions (@vous)",                en: "Mentions (@you)" },
];

function NotificationsSection({ lang }) {
  const T = (fr, en) => (lang === "fr" ? fr : en);
  const { data: prefs, loading } = window.melr.useNotificationPrefs();
  const [freq,     setFreq]     = useStateP("off");
  const [cats,     setCats]     = useStateP([]);
  const [hour,     setHour]     = useStateP(8);
  const [tz,       setTz]       = useStateP("UTC");
  const [busy,     setBusy]     = useStateP(false);
  const [msg,      setMsg]      = useStateP(null);
  const [previewOpen, setPreviewOpen] = useStateP(false);
  const [preview,  setPreview]  = useStateP(null);

  // Hydrate depuis le hook quand les prefs arrivent
  useEffectP(() => {
    if (!prefs) return;
    setFreq(prefs.email_digest_frequency || "off");
    setCats(Array.isArray(prefs.email_digest_categories) ? prefs.email_digest_categories : []);
    setHour(typeof prefs.email_digest_hour === "number" ? prefs.email_digest_hour : 8);
    setTz(prefs.timezone || "UTC");
  }, [prefs]);

  const toggleCat = (id) => {
    setCats((cur) => cur.includes(id) ? cur.filter((c) => c !== id) : [...cur, id]);
  };

  const onSave = async () => {
    setMsg(null); setBusy(true);
    try {
      await window.melr.notificationPrefsCrud.save({
        email_digest_frequency: freq,
        email_digest_categories: cats,
        email_digest_hour: Number(hour) || 8,
        timezone: tz || "UTC",
      });
      setMsg({ tone: "success", text: T("Préférences enregistrées.", "Preferences saved.") });
    } catch (e) { setMsg({ tone: "danger", text: e.message }); }
    finally { setBusy(false); }
  };

  const onPreview = async () => {
    setMsg(null); setBusy(true);
    try {
      const p = await window.melr.notificationPrefsCrud.previewDigest();
      setPreview(p);
      setPreviewOpen(true);
    } catch (e) { setMsg({ tone: "danger", text: e.message }); }
    finally { setBusy(false); }
  };

  const onSendTest = async () => {
    if (!window.confirm(T(
      "Envoyer un digest de test à votre adresse email ?",
      "Send a test digest to your email address?"
    ))) return;
    setMsg(null); setBusy(true);
    try {
      await window.melr.notificationPrefsCrud.sendTestNow();
      setMsg({ tone: "success", text: T("Digest de test envoyé. Vérifiez votre boîte.", "Test digest sent. Check your inbox.") });
    } catch (e) { setMsg({ tone: "danger", text: e.message }); }
    finally { setBusy(false); }
  };

  const inp = { padding: "8px 10px", borderRadius: 6, border: "1px solid var(--line)", fontSize: 13, background: "var(--bg, white)", color: "var(--text, #111)" };

  return (
    <div className="card" style={{ padding: 20, gridColumn: "1 / -1" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }}>
        <div style={{ fontSize: 15, fontWeight: 600 }}>
          📧 {T("Notifications par email · digest", "Email notifications · digest")}
        </div>
        {prefs && prefs.last_sent_at && (
          <div className="text-faint" style={{ fontSize: 11 }}>
            {T("Dernier envoi : ", "Last sent: ")}{new Date(prefs.last_sent_at).toLocaleString()}
          </div>
        )}
      </div>

      <div className="text-faint" style={{ fontSize: 12, marginBottom: 14 }}>
        {T(
          "Recevez un résumé périodique des nouveaux projets, indicateurs, activités et validations en attente. Aucun email instantané — uniquement un digest groupé pour éviter le spam.",
          "Get a periodic summary of new projects, indicators, activities, and pending validations. No instant emails — only a grouped digest to avoid spam."
        )}
      </div>

      {loading ? (
        <div className="text-faint" style={{ fontSize: 12 }}>{T("Chargement…", "Loading…")}</div>
      ) : (
        <div style={{ display: "grid", gap: 14 }}>
          {/* Fréquence */}
          <div style={{ display: "grid", gridTemplateColumns: "180px 1fr", gap: 12, alignItems: "center" }}>
            <label style={{ fontSize: 12, fontWeight: 500 }}>
              {T("Fréquence", "Frequency")}
            </label>
            <select value={freq} onChange={(e) => setFreq(e.target.value)} style={inp} disabled={busy}>
              <option value="off">{T("Désactivé (aucun email)", "Off (no emails)")}</option>
              <option value="daily">{T("Quotidien", "Daily")}</option>
              <option value="weekly">{T("Hebdomadaire (lundi matin)", "Weekly (Monday morning)")}</option>
            </select>
          </div>

          {freq !== "off" && (
            <>
              {/* Catégories */}
              <div style={{ display: "grid", gridTemplateColumns: "180px 1fr", gap: 12, alignItems: "start" }}>
                <label style={{ fontSize: 12, fontWeight: 500, paddingTop: 6 }}>
                  {T("Catégories incluses", "Included categories")}
                </label>
                <div style={{ display: "grid", gap: 6 }}>
                  {ALL_CATEGORIES.map((c) => (
                    <label key={c.id} style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, cursor: "pointer" }}>
                      <input type="checkbox" checked={cats.includes(c.id)}
                             onChange={() => toggleCat(c.id)} disabled={busy} />
                      {lang === "fr" ? c.fr : c.en}
                    </label>
                  ))}
                </div>
              </div>

              {/* Heure d'envoi */}
              <div style={{ display: "grid", gridTemplateColumns: "180px 1fr", gap: 12, alignItems: "center" }}>
                <label style={{ fontSize: 12, fontWeight: 500 }}>
                  {T("Heure d'envoi", "Send hour")}
                </label>
                <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  <input type="range" min="0" max="23" value={hour}
                         onChange={(e) => setHour(Number(e.target.value))}
                         disabled={busy} style={{ flex: 1 }} />
                  <span style={{ fontSize: 13, fontFamily: "monospace", minWidth: 60 }}>
                    {String(hour).padStart(2, "0")}:00
                  </span>
                </div>
              </div>

              {/* Timezone */}
              <div style={{ display: "grid", gridTemplateColumns: "180px 1fr", gap: 12, alignItems: "center" }}>
                <label style={{ fontSize: 12, fontWeight: 500 }}>
                  {T("Fuseau horaire", "Timezone")}
                </label>
                <input value={tz} onChange={(e) => setTz(e.target.value)} style={inp} disabled={busy}
                       placeholder="Africa/Dakar, Europe/Paris, UTC…" />
              </div>
            </>
          )}

          {/* Actions */}
          <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginTop: 4 }}>
            <button type="button" className="btn primary" onClick={onSave} disabled={busy}>
              {busy ? "…" : T("Enregistrer", "Save")}
            </button>
            <button type="button" className="btn ghost" onClick={onPreview} disabled={busy}>
              {T("Aperçu (7 derniers jours)", "Preview (last 7 days)")}
            </button>
            {freq !== "off" && (
              <button type="button" className="btn ghost" onClick={onSendTest} disabled={busy}>
                {T("Envoyer un test maintenant", "Send a test now")}
              </button>
            )}
          </div>

          {msg && (
            <div style={{
              padding: 8, fontSize: 12, borderRadius: 5,
              background: msg.tone === "success" ? "#dcfce7" : "#fee2e2",
              color: msg.tone === "success" ? "#166534" : "#991b1b",
            }}>{msg.text}</div>
          )}
        </div>
      )}

      {previewOpen && preview && (
        <PreviewDigestModal lang={lang} payload={preview} onClose={() => setPreviewOpen(false)} />
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// PreviewDigestModal · affiche le payload jsonb retourné par
// build_user_digest sous forme lisible. Utile pour vérifier que le
// digest contiendra bien ce que l'utilisateur attend avant de
// l'activer pour de vrai.
// ─────────────────────────────────────────────────────────────────────
function PreviewDigestModal({ lang, payload, onClose }) {
  const Modal = window.Modal;
  const T = (fr, en) => (lang === "fr" ? fr : en);
  const total = (payload && payload.summary && payload.summary.total) || 0;
  const section = (title, items, render) => {
    if (!Array.isArray(items) || items.length === 0) return null;
    return (
      <div style={{ marginTop: 14 }}>
        <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 6 }}>
          {title} <span className="text-faint" style={{ fontWeight: 400 }}>({items.length})</span>
        </div>
        <ul style={{ margin: 0, paddingLeft: 18, fontSize: 12, display: "grid", gap: 4 }}>
          {items.map((it, i) => <li key={it.id || i}>{render(it)}</li>)}
        </ul>
      </div>
    );
  };
  return (
    <Modal isOpen={true} onClose={onClose}
           title={T("Aperçu du digest", "Digest preview")}
           size="md">
      <div style={{ padding: 16 }}>
        <div className="text-faint" style={{ fontSize: 11, marginBottom: 8 }}>
          {T("Période : ", "Window: ")}
          {payload.since ? new Date(payload.since).toLocaleString() : "?"}
          {" → "}
          {payload.until ? new Date(payload.until).toLocaleString() : "?"}
        </div>
        {total === 0 ? (
          <div style={{ padding: 16, background: "var(--bg-sunken)", borderRadius: 6, fontSize: 12 }}>
            {T(
              "Aucune nouveauté sur cette fenêtre. Le digest ne serait pas envoyé.",
              "No news in this window. The digest wouldn't be sent."
            )}
          </div>
        ) : (
          <>
            <div style={{ fontSize: 12, marginBottom: 4 }}>
              <b>{T("Total : ", "Total: ")}{total}</b> {T("entrée(s)", "item(s)")}
            </div>
            {section(T("Nouveaux projets", "New projects"), payload.new_projects,
              (p) => <span><b>{p.code || ""}</b> — {p.name_fr || p.name_en || "?"}</span>)}
            {section(T("Nouveaux indicateurs", "New indicators"), payload.new_indicators,
              (i) => <span><b>{i.code || ""}</b> — {i.name_fr || i.name_en || "?"}</span>)}
            {section(T("Nouvelles activités", "New activities"), payload.new_activities,
              (a) => <span><b>{a.code || ""}</b> — {a.title || "?"}</span>)}
            {section(T("Validations en attente", "Pending validations"), payload.validations_pending,
              (v) => <span>{v.title || v.object_type} · {v.priority || ""}</span>)}
          </>
        )}
        <div style={{ marginTop: 16, paddingTop: 12, borderTop: "1px solid var(--line)", textAlign: "right" }}>
          <button className="btn" onClick={onClose}>{T("Fermer", "Close")}</button>
        </div>
      </div>
    </Modal>
  );
}

window.ProfileScreen = ProfileScreen;
