// FOOTPASS v2 · GROWTH · application des gains rapides de l'audit captologie & rétention
//  R-01 attente KYC productive · R-02 checklist « 3 gestes » · R-03 invitation états vides
//  R-04 préférences de notifications · R-05 « Pendant votre absence » · R-06 actifs visibles
//  R-11 « X a rejoint » (écouteur dans FPShell, home.jsx)
// Règle de la maison (audit § À proscrire) : uniquement des faits dérivés des vrais stores,
// jamais de compteur gonflé, jamais de culpabilisation, sortie en 1 geste partout.
const { useState: useStateG, useEffect: useEffectG } = React;

const grTX = (s) => (typeof TX === 'function' ? TX(s) : s);
const GR_LINK = 'footpass.app/i/ADAC-2480';

const GrCheckIc = ({ s = 11 }) => (
  <svg width={s} height={s} viewBox="0 0 14 14" fill="none">
    <path d="M2.5 7.5L5.5 10.5L11.5 3.5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
  </svg>
);
const GrChev = ({ s = 13 }) => (
  <svg width={s} height={s} viewBox="0 0 14 14" fill="none">
    <path d="M5 2.8L9.4 7 5 11.2" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"></path>
  </svg>
);
const GrLinkIc = ({ s = 13 }) => (
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
    <path d="M9.5 14.5l5-5M8 10l-1.5 1.5a3.5 3.5 0 005 5L13 15M16 14l1.5-1.5a3.5 3.5 0 00-5-5L11 9" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"></path>
  </svg>
);

// ── Persistance légère ──
const grGet = (k, fb) => { try { const v = localStorage.getItem(k); return v === null ? fb : v; } catch (e) { return fb; } };
const grSet = (k, v) => { try { localStorage.setItem(k, v); } catch (e) { /* ignore */ } };
const grGetJSON = (k, fb) => { try { const v = JSON.parse(localStorage.getItem(k) || 'null'); return v === null ? fb : v; } catch (e) { return fb; } };
const grSetJSON = (k, v) => grSet(k, JSON.stringify(v));

// Re-render sur événement fp:growth (les Tweaks pilotent les simulations)
function useGrowthSignal() {
  const [, setN] = useStateG(0);
  useEffectG(() => {
    const f = () => setN((n) => n + 1);
    window.addEventListener('fp:growth', f);
    return () => window.removeEventListener('fp:growth', f);
  }, []);
}

// ═══════ R-05 · « Pendant votre absence » · récap factuel au retour ═══════
// Uniquement des faits dérivés des stores réels ; ni compteur rouge, ni dramatisation.
function FPAbsenceRecap({ onTab, onOpenSub }) {
  useGrowthSignal();
  const on = grGet('fp_growth_absence', '0') === '1';
  if (!on) return null;
  const dismiss = () => { grSet('fp_growth_absence', '0'); window.dispatchEvent(new CustomEvent('fp:growth', { detail: { kind: 'absence-off' } })); };

  const unread = (window.FP_CONVOS || []).reduce((s, c) => s + (c.unread || 0), 0);
  const requests = ((window.FP_AUTH && window.FP_AUTH.requests) || []).filter((r) => r.status === 'pending').length;
  const evPending = (window.FP_EVENTS || []).filter((e) => e.status === 'pending' && !(window.fpEvIsPast && window.fpEvIsPast(e))).length;
  const rows = [];
  if (unread) rows.push({ n: unread, label: grTX('messages reçus'), go: () => onTab('messages') });
  if (requests) rows.push({ n: requests, label: grTX('demande d\u2019accès en attente'), go: () => onOpenSub('mandates') });
  if (evPending) rows.push({ n: evPending, label: grTX('présence à confirmer'), go: () => onTab('agenda') });

  return (
    <div className="gr-card" data-screen-label="Accueil · Pendant votre absence">
      <div className="gr-head">
        <span className="gr-kicker">{grTX('PENDANT VOTRE ABSENCE')}</span>
        <b></b>
        <button className="gr-x" onClick={dismiss} aria-label={grTX('Masquer')}>
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2.5 2.5l7 7M9.5 2.5l-7 7" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"></path></svg>
        </button>
      </div>
      {rows.length ? rows.map((r) => (
        <button key={r.label} className="gr-abs-row" onClick={r.go}>
          <span className="gr-abs-n">{r.n}</span>
          <span>{r.n > 1 && r.label === grTX('demande d\u2019accès en attente') ? grTX('demandes d\u2019accès en attente') : r.label}</span>
          <em><GrChev s={11} /></em>
        </button>
      )) : (
        <div className="gr-done-line" style={{ borderTop: 0, paddingTop: 0 }}>
          <GrCheckIc /> {grTX('Rien ne s\u2019est accumulé. Tout est à jour.')}
        </div>
      )}
    </div>
  );
}

// ═══════ R-02 · Checklist « Bien démarrer » · les 3 gestes d'activation ═══════
// Apparaît après l'onboarding (semée par finishOnboarding) · refermable en 1 geste, jamais relancée.
const GR_STEPS_KEY = 'fp_growth_steps';
function grSteps() { return grGetJSON(GR_STEPS_KEY, { msg: false, invite: false, auth: false, off: true }); }
function FPStartChecklist({ onTab, onOpenSub }) {
  useGrowthSignal();
  const st = grSteps();
  if (st.off) return null;
  const save = (next) => { grSetJSON(GR_STEPS_KEY, next); window.dispatchEvent(new CustomEvent('fp:growth', { detail: { kind: 'checklist' } })); };
  const mark = (k) => save({ ...st, [k]: true });
  const hide = () => save({ ...st, off: true });
  const doneCount = ['msg', 'invite', 'auth'].filter((k) => st[k]).length;

  // Chaque geste ouvre le vrai flux, pas un simple onglet
  const openSheet = (sheet) => window.dispatchEvent(new CustomEvent('fp:growth', { detail: { kind: 'sheet', sheet } }));
  const steps = [
    { k: 'msg', t: grTX('Démarrer une conversation'), s: grTX('Choisissez un destinataire vérifié'), go: () => { mark('msg'); openSheet('newmsg'); } },
    { k: 'invite', t: grTX('Inviter vos contacts de confiance'), s: grTX('WhatsApp, mail ou lien vérifié'), go: () => { mark('invite'); openSheet('invite'); } },
    { k: 'auth', t: grTX('Créer votre première autorisation'), s: grTX('Représentation, accès ou délégation'), go: () => { mark('auth'); onOpenSub('mandates-new'); } },
  ];

  return (
    <div className="gr-card" data-screen-label="Accueil · Bien démarrer">
      <div className="gr-head">
        <b>{grTX('Bien démarrer')}</b>
        <span className="gr-kicker">{doneCount}/3</span>
        <button className="gr-x" onClick={hide} aria-label={grTX('Masquer')}>
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2.5 2.5l7 7M9.5 2.5l-7 7" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"></path></svg>
        </button>
      </div>
      <div className="gr-prog"><i style={{ width: `${Math.round((doneCount / 3) * 100)}%` }}></i></div>
      {steps.map((s) => (
        <button key={s.k} className={`gr-step ${st[s.k] ? 'done' : ''}`} onClick={s.go}>
          <span className="gr-check"><GrCheckIc /></span>
          <span className="gr-step-txt"><b>{s.t}</b><em>{s.s}</em></span>
          <span className="gr-step-chev"><GrChev /></span>
        </button>
      ))}
      {doneCount === 3 ? (
        <div className="gr-done-line">
          <GrCheckIc /> {grTX('Tout est prêt.')}
          <button onClick={hide}>{grTX('Masquer')}</button>
        </div>
      ) : null}
    </div>
  );
}

// ═══════ R-03 · Invitation vérifiée depuis un état vide ═══════
// La croissance se câble là où le besoin naît : un contact introuvable = une invitation.
function FPInviteEmpty({ term }) {
  const short = (term || '').trim().length > 18 ? (term || '').trim().slice(0, 18) + '…' : (term || '').trim();
  const doInvite = () => window.dispatchEvent(new CustomEvent('fp:growth', { detail: { kind: 'sheet', sheet: 'invite', name: short || null } }));
  return (
    <div className="gr-invite">
      <p>{grTX('Pas encore sur FOOTPASS ?')}</p>
      <button className="gr-invite-btn" onClick={doInvite}>
        <GrLinkIc />
        <span>{short ? grTX('Inviter') + ' « ' + short + ' » ' + grTX('avec un lien vérifié') : grTX('Inviter avec un lien vérifié')}</span>
      </button>
      <span className="gr-invite-note">{grTX('Chaque inscription via votre lien rejoint votre réseau vérifié.')}</span>
    </div>
  );
}

// ═══════ R-03 · Feuille d'invitation · l'endroit unique où l'on invite ═══════
function InviteSheet({ onClose, name }) {
  const [sent, setSent] = useStateG(null);
  const doShare = (via) => {
    if (sent) return;
    try { if (navigator.clipboard) navigator.clipboard.writeText('https://' + GR_LINK); } catch (e) { /* ignore */ }
    setSent(via === 'copy' ? grTX('Lien copié · à coller où vous voulez') : grTX('Brouillon prêt dans') + ' ' + via + ' · ' + grTX('votre lien vérifié est inclus'));
    setTimeout(() => { onClose && onClose(); }, 1500);
  };
  return (
    <PgSheet onClose={onClose} title={name ? grTX('Inviter') + ' « ' + name + ' »' : grTX('Inviter dans votre réseau')}>
      <p className="gr-inv-sub">{grTX('La personne s\u2019inscrit via votre lien, passe la vérification d\u2019identité, et arrive directement dans vos contacts vérifiés.')}</p>
      <div className="gr-inv-link">
        <code>{GR_LINK}</code>
        <button onClick={() => doShare('copy')}>{grTX('Copier')}</button>
      </div>
      <div className="gr-inv-pills">
        {['WhatsApp', 'Messages', 'Mail', 'LinkedIn'].map((n) => (
          <button key={n} onClick={() => doShare(n)}>{n}</button>
        ))}
      </div>
      {sent
        ? <div className="gr-inv-done"><GrCheckIc s={11} /> {sent}</div>
        : <p className="gr-np-note" style={{ margin: '0 0 6px' }}>{grTX('Invitation nominative, à usage unique · jamais de spam envoyé à votre place.')}</p>}
    </PgSheet>
  );
}

// ═══════ R-04 · Préférences de notifications par rôle ═══════
// L'urgent est immédiat, le reste attend le regroupement · heures calmes par défaut.
const GR_NP_KEY = 'fp_growth_notifprefs';
const GR_NP_ROWS = [
  { id: 'msg', label: 'Messages', sub: 'Conversations et documents reçus', def: 'now' },
  { id: 'call', label: 'Appels', sub: 'Entrants, manqués, salons', def: 'now' },
  { id: 'auth', label: 'Autorisations & signatures', sub: 'Demandes, accords, révocations', def: 'now' },
  { id: 'agenda', label: 'Agenda', sub: 'Rappels J−1 et confirmations', def: 'digest' },
  { id: 'network', label: 'Réseau', sub: 'Nouveaux membres via votre lien', def: 'digest' },
];
const GR_NP_MODES = [
  { v: 'now', label: 'Immédiat' },
  { v: 'digest', label: 'Regroupé' },
  { v: 'off', label: 'Coupé' },
];
function NotifPrefsSheet({ onClose }) {
  const [prefs, setPrefsRaw] = useStateG(() => grGetJSON(GR_NP_KEY, {
    modes: Object.fromEntries(GR_NP_ROWS.map((r) => [r.id, r.def])),
    quiet: true,
  }));
  const setPrefs = (next) => { setPrefsRaw(next); grSetJSON(GR_NP_KEY, next); };
  return (
    <PgSheet onClose={onClose} title={grTX('Préférences de notifications')}>
      <div className="gr-np-role">
        <FPIcon.Shield s={12} />
        {grTX('Profil Agent · réglages recommandés pour votre rôle')}
      </div>
      {GR_NP_ROWS.map((r) => (
        <div key={r.id} className="gr-np-row">
          <span className="gr-np-txt"><b>{grTX(r.label)}</b><em>{grTX(r.sub)}</em></span>
          <span className="gr-seg">
            {GR_NP_MODES.map((m) => (
              <button key={m.v} className={prefs.modes[r.id] === m.v ? 'on' : ''}
                onClick={() => setPrefs({ ...prefs, modes: { ...prefs.modes, [r.id]: m.v } })}>{grTX(m.label)}</button>
            ))}
          </span>
        </div>
      ))}
      <div className="gr-np-row">
        <span className="gr-np-txt"><b>{grTX('Heures calmes')}</b><em>{grTX('21 h – 8 h · seuls les appels passent')}</em></span>
        <PgToggle on={prefs.quiet} onChange={(v) => setPrefs({ ...prefs, quiet: v })} />
      </div>
      <p className="gr-np-note">{grTX('Le regroupé part une fois par jour à 18 h. FOOTPASS ne notifie que des faits réels · jamais de relance sans événement.')}</p>
    </PgSheet>
  );
}

// ═══════ R-06 · Actifs visibles · des faits, pas des trophées ═══════
// Compté depuis les stores réels : ce que vous avez construit ici, et qui vous suit.
function FPProfileFacts({ onOpenSub }) {
  const contacts = Object.keys(window.FP_PEERS || {}).length;
  const A = window.FP_AUTH || {};
  const autorisations = ['mandates', 'received', 'given'].reduce((s, k) => s + ((A[k] || []).filter((m) => m.status === 'active').length), 0);
  const docs = (window.FP_DOCS || []).length;
  const go = (dest) => { if (onOpenSub) onOpenSub(dest); };
  return (
    <React.Fragment>
      <div className="gr-facts">
        <button className="gr-fact" onClick={() => go('contacts')}><b>{contacts}</b><em>{grTX('contacts vérifiés')}</em></button>
        <button className="gr-fact" onClick={() => go('mandates')}><b>{autorisations}</b><em>{grTX('autorisations actives')}</em></button>
        <button className="gr-fact" onClick={() => go('vault')}><b>{docs}</b><em>{grTX('documents au coffre')}</em></button>
      </div>
    </React.Fragment>
  );
}

// ═══════ R-01 · Attente KYC productive (étape « wait » de l'onboarding) ═══════
// La certification humaine prend du temps réel : l'attente devient utile au lieu d'être morte.
function ObStepWait({ ctx }) {
  const [done, setDone] = useStateG({ profile: false, invites: false, network: false });
  const [issued, setIssued] = useStateG(false);
  useEffectG(() => {
    const t = setTimeout(() => setIssued(true), 9000);
    return () => clearTimeout(t);
  }, []);
  const mark = (k) => setDone((p) => ({ ...p, [k]: true }));
  const copyInvites = () => {
    try { if (navigator.clipboard) navigator.clipboard.writeText('https://' + GR_LINK); } catch (e) { /* ignore */ }
    mark('invites');
  };
  const steps = [
    { k: 'profile', t: grTX('Compléter mon profil'), s: done.profile ? grTX('Photo et langues enregistrées') : grTX('Photo, langues parlées'), go: () => mark('profile') },
    { k: 'invites', t: grTX('Préparer mes invitations'), s: done.invites ? grTX('Lien d\u2019invitation copié') : grTX('Votre lien vérifié personnel'), go: copyInvites },
    { k: 'network', t: grTX('Repérer mon réseau'), s: done.network ? grTX('3 contacts de vos clubs sont déjà membres') : grTX('Qui est déjà sur FOOTPASS ?'), go: () => mark('network') },
  ];
  return (
    <div className="ob-step" data-screen-label="Onboarding · Certification en cours">
      <div className="ob-body">
        <div>
          <div className="ob-kicker accent">{grTX('CERTIFICATION EN COURS')}</div>
          <h1 className="ob-h1">{grTX('Votre dossier est en vérification')}</h1>
          <p className="ob-sub">{grTX('Contrôle humain sous 2 h en moyenne. Vous serez notifié dès l\u2019émission de votre Pass ID · inutile d\u2019attendre ici.')}</p>
        </div>
        {issued ? (
          <div className="gr-issued">
            <span className="gr-abs-n"><GrCheckIc /></span>
            {grTX('Pass ID émis · votre identité est certifiée')}
          </div>
        ) : (
          <div className="gr-wait-status">
            <span className="gr-spin"></span>
            <span><b>{grTX('Vérification en cours')}</b> · {grTX('document + biométrie')}</span>
          </div>
        )}
        <div className="gr-wait-list">
          {steps.map((s) => (
            <button key={s.k} className={`gr-step ${done[s.k] ? 'done' : ''}`} onClick={s.go}>
              <span className="gr-check"><GrCheckIc /></span>
              <span className="gr-step-txt"><b>{s.t}</b><em>{s.s}</em></span>
              <span className="gr-step-chev"><GrChev /></span>
            </button>
          ))}
        </div>
        {!issued ? (
          <React.Fragment>
            <p className="gr-wait-note">{grTX('Pendant ce temps, votre compte se prépare : chaque geste ci-dessus rendra votre premier jour utile.')}</p>
            <button className="gr-wait-sim" onClick={() => setIssued(true)}>{grTX('Simuler l\u2019émission (démo)')}</button>
          </React.Fragment>
        ) : null}
      </div>
      {issued ? (
        <div className="ob-foot">
          <button className="ob-cta" onClick={ctx.next}>{grTX('Découvrir mon Pass ID')}</button>
        </div>
      ) : null}
    </div>
  );
}

Object.assign(window, {
  FPAbsenceRecap, FPStartChecklist, FPInviteEmpty, InviteSheet, NotifPrefsSheet, FPProfileFacts, ObStepWait,
});
