// simple-screens.jsx — parcours d'achat connecté au backend

const { useState, useEffect, useRef } = React;
const C = window.__club || {};

// ── Helper context ───────────────────────────────────────────
function useCtx() {
  return React.useContext(window.AppCtx) || {};
}

// ── Gestion des erreurs 401 ───────────────────────────────────
function handleAuthErr(err, setAppState, goTo) {
  if (err && err.status === 401) {
    localStorage.removeItem('token');
    setAppState(s => ({ ...s, token: null, user: null }));
    goTo('login');
    return true;
  }
  return false;
}

// ── Icons (identiques à l'original) ──────────────────────────
const Ic = ({ name, size = 22, stroke = 1.8 }) => {
  const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none",
    stroke: "currentColor", strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "calendar":     return <svg {...p}><rect x="3.5" y="5" width="17" height="15.5" rx="2"/><path d="M3.5 10h17M8 3.5v3M16 3.5v3"/></svg>;
    case "pin":          return <svg {...p}><path d="M12 21s-7-7-7-12a7 7 0 0 1 14 0c0 5-7 12-7 12z"/><circle cx="12" cy="9" r="2.2"/></svg>;
    case "clock":        return <svg {...p}><circle cx="12" cy="12" r="8.5"/><path d="M12 7v5l3 2"/></svg>;
    case "ticket":       return <svg {...p}><path d="M3 9.5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v1.5a1.5 1.5 0 0 0 0 3V15.5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V14a1.5 1.5 0 0 0 0-3z"/></svg>;
    case "user":         return <svg {...p}><circle cx="12" cy="8.5" r="3.5"/><path d="M4.5 20c0-3.5 3.5-5.5 7.5-5.5s7.5 2 7.5 5.5"/></svg>;
    case "users":        return <svg {...p}><circle cx="9" cy="9" r="3"/><circle cx="17" cy="10" r="2.5"/><path d="M3 19c0-3 2.5-5 6-5s6 2 6 5"/><path d="M15 19c0-2 1.5-3.5 4-3.5s4 1.5 4 3.5"/></svg>;
    case "back":         return <svg {...p}><path d="M15 6l-6 6 6 6"/></svg>;
    case "help":         return <svg {...p}><circle cx="12" cy="12" r="9"/><path d="M9.5 9a2.5 2.5 0 0 1 5 0c0 1.5-2.5 2-2.5 3.5M12 16.5v.01"/></svg>;
    case "phone":        return <svg {...p}><path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2C9.5 21 3 14.5 3 6a2 2 0 0 1 2-2z"/></svg>;
    case "check":        return <svg {...p}><path d="M5 12l5 5 9-10"/></svg>;
    case "arrow":        return <svg {...p}><path d="M5 12h14m-5-5 5 5-5 5"/></svg>;
    case "info":         return <svg {...p}><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8v.01"/></svg>;
    case "cart":         return <svg {...p}><path d="M3.5 5h2l2 11h11l2-8H7"/><circle cx="9" cy="20" r="1.4"/><circle cx="17" cy="20" r="1.4"/></svg>;
    case "lock":         return <svg {...p}><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg>;
    case "download-pdf": return <svg {...p}><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/><path d="M12 12v6m0 0-2.5-2.5M12 18l2.5-2.5"/></svg>;
    case "mail":         return <svg {...p}><rect x="3.5" y="6" width="17" height="13" rx="2"/><path d="m4 8 8 6 8-6"/></svg>;
    case "download":     return <svg {...p}><path d="M12 4v12m0 0-4-4m4 4 4-4"/><path d="M5 20h14"/></svg>;
    default:             return null;
  }
};

// ── Shared chrome ─────────────────────────────────────────────
const TopBar = ({ showHelp = true }) => (
  <div className="topbar topbar--centered">
    <div className="topbar-brand">
      <div className="topbar-name">
        {C.name || "Club"}
        <span>{C.billetterieLabel || "Billetterie officielle"}</span>
      </div>
    </div>
    <img className="topbar-shield" src={C.logo || "assets/fcsm-logo.png"} alt={C.abbreviation || C.name || "Club"}/>
    {showHelp && (
      <button className="topbar-btn" aria-label="Aide">
        <Ic name="help" size={22}/>
      </button>
    )}
  </div>
);

const BackBar = ({ label = "Retour" }) => (
  <div className="backbar">
    <button className="back-btn">
      <Ic name="back" size={20} stroke={2.2}/>
      {label}
    </button>
    <div className="backbar-brand">
      {C.logo && <img src={C.logo} alt={C.name || ''} className="backbar-logo" />}
      {C.name && <span className="backbar-name">{C.name}</span>}
    </div>
    <button className="help-btn">
      <Ic name="help" size={18}/>
      Besoin d'aide&nbsp;?
    </button>
  </div>
);

const Steps = ({ step, total = 4, label }) => (
  <div className="steps">
    <div className="steps-text">Étape {step} sur {total} — {label}</div>
    <div className="steps-bar">
      {Array.from({ length: total }).map((_, i) => (
        <span key={i} className={i < step ? "on" : ""} />
      ))}
    </div>
  </div>
);

const Loading = () => (
  <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
    <p style={{ color: 'var(--ink-2)', fontSize: 15 }}>Chargement…</p>
  </div>
);

// Mini QR placeholder (affiche aussi le token sous le SVG)
const MiniQR = ({ size = 110, fg = "#133478", token }) => (
  <div style={{ textAlign: 'center' }}>
    <svg viewBox="0 0 60 60" width={size} height={size}>
      {Array.from({ length: 49 }).map((_, i) => {
        const x = (i % 7) * 8 + 4;
        const y = Math.floor(i / 7) * 8 + 4;
        const on = (i * 11 + 5) % 7 < 4;
        return on ? <rect key={i} x={x} y={y} width="6" height="6" fill={fg}/> : null;
      })}
      <rect x="4"  y="4"  width="14" height="14" fill="none" stroke={fg} strokeWidth="2"/>
      <rect x="42" y="4"  width="14" height="14" fill="none" stroke={fg} strokeWidth="2"/>
      <rect x="4"  y="42" width="14" height="14" fill="none" stroke={fg} strokeWidth="2"/>
      <rect x="7"  y="7"  width="8"  height="8"  fill={fg}/>
      <rect x="45" y="7"  width="8"  height="8"  fill={fg}/>
      <rect x="7"  y="45" width="8"  height="8"  fill={fg}/>
    </svg>
    {token && (
      <div style={{ fontFamily: 'monospace', fontSize: 10, color: fg === '#ffffff' ? 'rgba(255,255,255,0.6)' : 'var(--ink-2)', marginTop: 4, wordBreak: 'break-all', maxWidth: size }}>
        {token.slice(0, 16)}…
      </div>
    )}
  </div>
);

const AppleWalletIcon  = ({ size = 22 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
    <rect x="3" y="5" width="18" height="14" rx="3" fill="#fff" opacity="0.95"/>
    <rect x="3" y="9" width="18" height="4" fill="#FFCF21"/>
    <path d="M3 14h4.5a2 2 0 0 1 2 1.5l.4 1.2A1.5 1.5 0 0 0 11.4 18h1.2a1.5 1.5 0 0 0 1.5-1.3l.4-1.2a2 2 0 0 1 2-1.5H21" stroke="#000" strokeWidth="1.2" fill="none"/>
  </svg>
);
const GoogleWalletIcon = ({ size = 22 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
    <path d="M3 8a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3z" fill="#fff"/>
    <circle cx="16" cy="12" r="2.5" fill="#FFCF21"/>
    <circle cx="13.5" cy="12" r="2.5" fill="#4285F4" opacity="0.85"/>
  </svg>
);

const StadiumMini = ({ highlight = "kop" }) => {
  const dim = "rgba(255,255,255,0.10)"; const dimStroke = "rgba(255,255,255,0.18)";
  const onFill = "var(--yellow)"; const onStroke = "#FFCF21";
  const labelDim = "rgba(255,255,255,0.45)"; const labelOn = "#133478";
  const f  = id => highlight === id ? onFill    : dim;
  const s  = id => highlight === id ? onStroke  : dimStroke;
  const lc = id => highlight === id ? labelOn   : labelDim;
  return (
    <svg viewBox="0 0 320 200" xmlns="http://www.w3.org/2000/svg">
      <rect x="6" y="6" width="308" height="188" rx="36" fill="rgba(255,255,255,0.03)" stroke="rgba(255,255,255,0.1)" strokeWidth="1"/>
      <path d="M62 14 L258 14 Q278 14 286 30 L286 50 L34 50 L34 30 Q42 14 62 14 Z" fill={f("presi")} stroke={s("presi")} strokeWidth="1"/>
      <text x="160" y="35" textAnchor="middle" fontSize="10" fontWeight="700" fill={lc("presi")} letterSpacing="0.06em">PRÉSIDENTIELLE</text>
      <path d="M34 152 L286 152 L286 172 Q278 188 258 188 L62 188 Q42 188 34 172 Z" fill={f("offi")} stroke={s("offi")} strokeWidth="1"/>
      <text x="160" y="174" textAnchor="middle" fontSize="10" fontWeight="700" fill={lc("offi")} letterSpacing="0.06em">OFFICIELLE</text>
      <path d="M34 54 L96 54 L96 96 L34 96 Z" fill={f("fam")} stroke={s("fam")} strokeWidth="1"/>
      <text x="65" y="80" textAnchor="middle" fontSize="9" fontWeight="700" fill={lc("fam")} letterSpacing="0.04em">FAMILLE</text>
      <path d="M34 100 L96 100 L96 148 L34 148 Z" fill={f("ouest")} stroke={s("ouest")} strokeWidth="1"/>
      <text x="65" y="127" textAnchor="middle" fontSize="9" fontWeight="700" fill={lc("ouest")} letterSpacing="0.04em">V. OUEST</text>
      <path d="M224 54 L286 54 L286 148 L224 148 Z" fill={f("kop")} stroke={s("kop")} strokeWidth="1"/>
      <text x="255" y="100" textAnchor="middle" fontSize="10" fontWeight="700" fill={lc("kop")} letterSpacing="0.06em">VIRAGE EST</text>
      <text x="255" y="114" textAnchor="middle" fontSize="9"  fontWeight="600" fill={lc("kop")} opacity="0.85">LE KOP</text>
      <rect x="104" y="58" width="116" height="86" rx="3" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.18)" strokeWidth="0.6"/>
      <line x1="162" y1="58" x2="162" y2="144" stroke="rgba(255,255,255,0.18)" strokeWidth="0.4"/>
      <circle cx="162" cy="101" r="10" fill="none" stroke="rgba(255,255,255,0.18)" strokeWidth="0.4"/>
      <circle cx="162" cy="101" r="1.3" fill="rgba(255,255,255,0.3)"/>
    </svg>
  );
};

// ── SCREEN 1 — Accueil ────────────────────────────────────────
const ScrHome = () => {
  const { appState, setAppState, goTo } = useCtx();
  const [matches,      setMatches]      = useState([]);
  const [subscription, setSubscription] = useState(null);
  const [loading,      setLoading]      = useState(true);

  useEffect(() => {
    const fetchAll = async () => {
      try {
        const ms = await API.matches('upcoming');
        setMatches(ms);
      } catch {}
      if (appState.token) {
        try {
          const sub = await API.subscription();
          setSubscription(sub.subscription || null);
          setAppState(s => ({ ...s, subscription: sub.subscription || null }));
        } catch {}
      }
      setLoading(false);
    };
    fetchAll();
  }, []);

  const nextMatch     = matches[0] || null;
  const otherMatches  = matches.slice(1, 3);

  const goToMatch = (m) => {
    setAppState(s => ({ ...s, match: m }));
    goTo('zones');
  };

  return (
    <div className="scr" data-screen-label="01 Accueil">
      <TopBar />
      <div className="body">
        <div className="page-title">
          <h1>{appState.user?.name ? `Bonjour ${appState.user.name.split(' ')[0]}` : 'Bonjour'}</h1>
          <p>Voici le prochain match à {C.stadiumShort || C.stadium || "domicile"}.</p>
        </div>

        {loading ? <Loading/> : nextMatch ? (
          <div className="hero">
            <div className="hero-tag">★ Prochain match</div>
            <div className="hero-vs">
              <h2>{C.name || "Club"} <small>contre {nextMatch.away}</small></h2>
            </div>
            <div className="hero-info">
              <div className="hero-info-row">
                <Ic name="calendar" size={20}/>
                <b>{nextMatch.dateText}</b>
                <span>· {nextMatch.timeText}</span>
              </div>
              <div className="hero-info-row">
                <Ic name="pin" size={20}/>
                <b>{C.stadiumShort || C.stadium || "Stade"}</b>
                {C.city && <span>· {C.city}</span>}
              </div>
            </div>
            <button className="btn-primary" onClick={() => goToMatch(nextMatch)}>
              Acheter ma place
              <Ic name="arrow" size={20}/>
            </button>
          </div>
        ) : (
          <div className="hero" style={{ textAlign: 'center', padding: '32px 20px' }}>
            <p style={{ color: 'var(--ink-2)' }}>Aucun match à venir pour le moment.</p>
          </div>
        )}

        {subscription ? (
          <>
            <div className="section-h">Mon abonnement</div>
            <div style={{ padding: "0 16px" }}>
              <div
                onClick={() => goTo('wallet')}
                style={{
                  display: "flex", alignItems: "center", gap: 14,
                  padding: "16px 18px", background: "var(--navy)",
                  borderRadius: 16, color: "#fff", cursor: 'pointer',
                }}>
                <div style={{
                  width: 44, height: 44, borderRadius: 10,
                  background: "var(--yellow)", color: "var(--navy)",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  flexShrink: 0, fontWeight: 800, fontSize: 16,
                }}>★</div>
                <div style={{ flex: 1 }}>
                  <b style={{ display: "block", fontSize: 16, fontWeight: 700, marginBottom: 2 }}>
                    Carte abonné {subscription.season}
                  </b>
                  <span style={{ fontSize: 13, color: "rgba(255,255,255,0.75)" }}>
                    {subscription.zone}{subscription.row ? ` · Rang ${subscription.row}` : ''}{subscription.seat_number ? ` · place ${subscription.seat_number}` : ''}
                  </span>
                </div>
                <Ic name="arrow" size={20}/>
              </div>
            </div>
          </>
        ) : !appState.token && (
          <>
            <div className="section-h">Mon compte</div>
            <div style={{ padding: "0 16px" }}>
              <button className="btn-secondary" onClick={() => goTo('login')}>
                <Ic name="user" size={18}/>
                Se connecter / Créer un compte
              </button>
            </div>
          </>
        )}

        {otherMatches.length > 0 && (
          <>
            <div className="section-h">Autres matchs</div>
            <div className="matches">
              {otherMatches.map(m => (
                <div key={m.id} className="match-card" onClick={() => goToMatch(m)}>
                  <div className="match-date-block">
                    <b>{m.dayNum}</b>
                    <span>{m.monthText}</span>
                  </div>
                  <div className="match-body">
                    <b>{C.name || "Club"} — {m.away}</b>
                    <span>{m.dayText} · {m.timeText}</span>
                  </div>
                  <Ic name="arrow" size={20}/>
                </div>
              ))}
            </div>
          </>
        )}

        <div style={{ padding: "18px 16px 0" }}>
          <button className="btn-secondary" onClick={() => goTo('list')}>
            <Ic name="calendar" size={18}/>
            Voir tout le calendrier
          </button>
        </div>

        <div className="help-banner">
          <div className="help-banner-icon"><Ic name="phone" size={22}/></div>
          <div className="help-banner-text">
            <b>Une question&nbsp;?</b>
            On vous aide au <a href={`tel:${C.phone || ""}`}>{C.phone || "notre service billetterie"}</a> du lundi au vendredi, 9h–18h.
          </div>
        </div>
      </div>
    </div>
  );
};

// ── SCREEN 2 — Liste des matchs ───────────────────────────────
const ScrList = () => {
  const { setAppState, goTo } = useCtx();
  const [matches, setMatches] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error,   setError]   = useState(null);

  useEffect(() => {
    API.matches('upcoming')
      .then(ms => setMatches(ms))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }, []);

  const byMonth = matches.reduce((acc, m) => {
    const key = m.monthText + ' ' + new Date(m.date.slice(0, 10) + 'T12:00:00').getFullYear();
    if (!acc[key]) acc[key] = [];
    acc[key].push(m);
    return acc;
  }, {});

  const goToMatch = (m) => {
    setAppState(s => ({ ...s, match: m }));
    goTo('zones');
  };

  return (
    <div className="scr" data-screen-label="02 Choisir un match">
      <BackBar/>
      <Steps step={1} total={4} label="Choisir un match"/>
      <div className="body">
        <div className="page-title">
          <h1>Choisis ton match</h1>
          <p>{loading ? 'Chargement…' : `${matches.length} match${matches.length > 1 ? 's' : ''} à venir au ${C.stadiumShort || C.stadium || "stade"}.`}</p>
        </div>
        {loading && <Loading/>}
        {error && <p style={{ padding: '0 20px', color: 'var(--bad)' }}>{error}</p>}
        {Object.entries(byMonth).map(([month, ms]) => (
          <div key={month}>
            <div className="section-h">{month}</div>
            <div className="matches">
              {ms.map(m => {
                const sold    = m.status === 'sold';
                const limited = m.status === 'limited';
                return (
                  <div
                    key={m.id}
                    className={`match-card ${sold ? 'disabled' : ''}`}
                    onClick={() => !sold && goToMatch(m)}
                  >
                    <div className="match-date-block">
                      <b>{m.dayNum}</b>
                      <span>{m.monthShort}</span>
                    </div>
                    <div className="match-body">
                      <b>{C.name || "Club"} — {m.away}</b>
                      <span>{m.dayText} · {m.timeText}</span>
                      {sold    && <span className="match-status-line muted">Complet — plus de places</span>}
                      {limited && <span className="match-status-line bad">⚠ Peu de places restantes</span>}
                      {!sold && !limited && m.price_from != null && (
                        <span className="match-status-line ok">À partir de {m.price_from} €</span>
                      )}
                    </div>
                    {!sold && <span className="arrow"><Ic name="arrow" size={20}/></span>}
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

// ── SCREEN 3 — Choisir la tribune ─────────────────────────────
const ScrZones = () => {
  const { appState, setAppState, goTo } = useCtx();
  const [zones,    setZones]    = useState([]);
  const [selected, setSelected] = useState(null);
  const [loading,  setLoading]  = useState(true);

  const match = appState.match;

  useEffect(() => {
    if (!match?.id) { setLoading(false); return; }
    API.zones(match.id)
      .then(zs => {
        setZones(zs);
        const first = zs.find(z => z.status !== 'closed' && z.status !== 'sold');
        if (first) setSelected(first.id);
      })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, [match?.id]);

  const selectedZone = zones.find(z => z.id === selected) || null;

  const handleContinue = () => {
    if (!selectedZone) return;
    setAppState(s => ({ ...s, zone: selectedZone, selectedSeats: [], holdId: null }));
    goTo('seats');
  };

  return (
    <div className="scr" data-screen-label="03 Choisir une tribune">
      <BackBar/>
      <Steps step={2} total={4} label="Choisir une tribune"/>
      <div className="body">
        <div className="page-title">
          <h1>Où veux-tu t'asseoir&nbsp;?</h1>
          <p>{C.name || "Club"} — {match?.away || '…'} · {match?.dateText || ''} à {match?.timeText || ''}</p>
        </div>
        {loading ? <Loading/> : (
          <>
            <div className="section-h">Tribunes disponibles</div>
            <div className="zones">
              {zones.map(z => {
                const sold = z.status === 'sold' || z.status === 'closed';
                const on   = selected === z.id;
                return (
                  <div
                    key={z.id}
                    className={`zone ${on ? 'on' : ''} ${sold ? 'disabled' : ''}`}
                    onClick={() => !sold && setSelected(z.id)}
                  >
                    <div className="zone-side"/>
                    <div className="zone-body">
                      <div className="zone-info">
                        <b>{z.name}</b>
                        <span>{z.description || (z.standing ? 'Tribune debout' : 'Tribune assise')}</span>
                        {!sold && !z.standing && z.seats_free != null && (
                          <span style={{ fontSize: 12, color: z.seats_free < 20 ? 'var(--bad)' : 'var(--ok)' }}>
                            {z.seats_free} place{z.seats_free > 1 ? 's' : ''} disponible{z.seats_free > 1 ? 's' : ''}
                          </span>
                        )}
                      </div>
                      <div className="zone-price">
                        {sold ? (
                          <><b style={{ fontSize: 16, color: "var(--muted)" }}>—</b><span>Complet</span></>
                        ) : (
                          <><b>{z.price} €</b><span>par place</span></>
                        )}
                      </div>
                      <div className="zone-radio"/>
                    </div>
                  </div>
                );
              })}
            </div>

            <div className="help-banner" style={{ marginTop: 22 }}>
              <div className="help-banner-icon"><Ic name="info" size={22}/></div>
              <div className="help-banner-text">
                <b>Pas sûr du choix&nbsp;?</b>
                Le <b>Virage Est</b> est l'ambiance. La <b>Tribune Famille</b> est calme et adaptée aux enfants.
              </div>
            </div>
          </>
        )}
      </div>
      <div className="action-bar">
        <button className="btn-primary" disabled={!selectedZone} onClick={handleContinue}>
          Continuer
          <Ic name="arrow" size={20}/>
        </button>
      </div>
    </div>
  );
};

// ── SCREEN 4 — Places (grille assise ou sélecteur debout) ─────
const ScrSeats = () => {
  const { appState, setAppState, goTo } = useCtx();
  const [seatData, setSeatData] = useState(null);
  const [picked,   setPicked]   = useState([]);
  const [qty,      setQty]      = useState(1);
  const [loading,  setLoading]  = useState(true);
  const [busy,     setBusy]     = useState(false);
  const [error,    setError]    = useState(null);
  const MAX = 6;

  const { match, zone, token } = appState;
  const isStanding = zone?.standing;

  useEffect(() => {
    if (!match?.id || !zone?.id) { setLoading(false); return; }
    if (isStanding) { setLoading(false); return; }
    API.seats(match.id, zone.id)
      .then(d => setSeatData(d))
      .catch(() => {})
      .finally(() => setLoading(false));
  }, [match?.id, zone?.id, isStanding]);

  const handleContinue = async () => {
    if (busy) return;
    if (!token) {
      setAppState(s => ({ ...s, returnAfterAuth: 'seats' }));
      goTo('signup');
      return;
    }
    setBusy(true);
    setError(null);
    try {
      const result = await API.createHold(
        match.id, zone.id,
        isStanding ? [] : picked.map(s => s.id),
        isStanding ? qty : undefined
      );
      setAppState(s => ({
        ...s,
        holdId:        result.hold_id,
        holdExpiresAt: result.expires_at,
        selectedSeats: isStanding ? [] : picked,
        qty:           isStanding ? qty : picked.length,
      }));
      goTo('pay');
    } catch (err) {
      if (handleAuthErr(err, setAppState, goTo)) return;
      if (err.code === 'SEATS_UNAVAILABLE') { goTo('errSold'); return; }
      if (err.code === 'HOLD_EXPIRED' || err.code === 'HOLD_NOT_FOUND') { goTo('errSess'); return; }
      setError(err.message || 'Erreur lors de la réservation.');
    } finally {
      setBusy(false);
    }
  };

  const toggle = (seat) => {
    if (seat.status !== 'free') return;
    setPicked(p =>
      p.find(s => s.id === seat.id)
        ? p.filter(s => s.id !== seat.id)
        : p.length < MAX ? [...p, seat] : p
    );
  };

  const pricePer = zone?.price || 0;
  const total    = pricePer * (isStanding ? qty : picked.length);

  if (loading) return (
    <div className="scr">
      <BackBar/>
      <Steps step={3} total={4} label="Choisir ses places"/>
      <Loading/>
    </div>
  );

  // ── Zone debout : sélecteur de quantité ───────────────────
  if (isStanding) {
    return (
      <div className="scr" data-screen-label="04 Nombre de places">
        <BackBar/>
        <Steps step={3} total={4} label="Nombre de places"/>
        <div className="body">
          <div className="page-title">
            <h1>Combien de places&nbsp;?</h1>
            <p>{zone.name} · {pricePer} € par place · max {MAX}</p>
          </div>

          <div style={{ padding: '24px 20px' }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 24, marginBottom: 32 }}>
              <button
                onClick={() => setQty(q => Math.max(1, q - 1))}
                style={{ width: 52, height: 52, borderRadius: '50%', border: '2px solid var(--line)', background: '#fff', fontSize: 24, fontWeight: 700, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--navy)' }}
                disabled={qty <= 1}
              >−</button>
              <span style={{ fontSize: 48, fontWeight: 900, color: 'var(--navy)', minWidth: 60, textAlign: 'center' }}>{qty}</span>
              <button
                onClick={() => setQty(q => Math.min(MAX, q + 1))}
                style={{ width: 52, height: 52, borderRadius: '50%', border: '2px solid var(--line)', background: '#fff', fontSize: 24, fontWeight: 700, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--navy)' }}
                disabled={qty >= MAX}
              >+</button>
            </div>
            <div style={{ display: 'flex', justifyContent: 'center', gap: 8, flexWrap: 'wrap' }}>
              {[1,2,3,4,5,6].map(n => (
                <button
                  key={n}
                  onClick={() => setQty(n)}
                  style={{
                    width: 44, height: 44, borderRadius: 10,
                    border: qty === n ? '2px solid var(--navy)' : '1.5px solid var(--line)',
                    background: qty === n ? 'var(--navy)' : '#fff',
                    color: qty === n ? '#fff' : 'var(--ink)',
                    fontWeight: 700, fontSize: 16, cursor: 'pointer',
                  }}
                >{n}</button>
              ))}
            </div>
          </div>

          {error && <p style={{ padding: '0 20px', color: 'var(--bad)' }}>{error}</p>}

          <div className="help-banner" style={{ marginTop: 0 }}>
            <div className="help-banner-icon"><Ic name="info" size={20}/></div>
            <div className="help-banner-text">
              <b>Zone debout</b>
              Libres pour ce match. Pas de numéro de siège attribué — tu entres dans ta tribune.
            </div>
          </div>
        </div>
        <div className="action-bar">
          <div className="action-bar-summary">
            <span className="lbl">{qty} place{qty > 1 ? 's' : ''} × {pricePer} €</span>
            <b className="val">{total} €</b>
          </div>
          <button className="btn-primary" onClick={handleContinue} disabled={busy}>
            {busy ? 'Chargement…' : 'Continuer'}
            {!busy && <Ic name="arrow" size={20}/>}
          </button>
        </div>
      </div>
    );
  }

  // ── Zone assise : grille de sièges ────────────────────────
  const rows = seatData?.rows || [];
  const pickedLabel = picked.length === 0
    ? 'Aucune place sélectionnée'
    : picked.map(s => `Rang ${s.row}, place ${s.number}`).join(' · ');

  return (
    <div className="scr" data-screen-label="04 Choisir ses places">
      <BackBar/>
      <Steps step={3} total={4} label="Choisir ses places"/>
      <div className="body">
        <div className="page-title">
          <h1>Choisis tes places</h1>
          <p>{zone.name} · Tape sur un siège pour le sélectionner</p>
        </div>

        <div className="seat-pick">
          <div className="seat-pick-pitch">↑ Vers la pelouse ↑</div>
          <div className="seat-grid">
            {rows.map(({ row, seats }) => (
              <div className="seat-row" key={row}>
                <span className="seat-row-label">{row}</span>
                {seats.map(seat => {
                  const isTaken = seat.status !== 'free';
                  const isOn    = picked.some(s => s.id === seat.id);
                  return (
                    <button
                      key={seat.id}
                      className={`seat ${isTaken ? 'taken' : ''} ${isOn ? 'on' : ''}`}
                      aria-label={`Rang ${row}, place ${seat.number}${isTaken ? ' — occupée' : ''}`}
                      onClick={() => toggle({ id: seat.id, row, number: seat.number, status: seat.status })}
                    >
                      {seat.number}
                    </button>
                  );
                })}
              </div>
            ))}
          </div>
          <div className="seat-legend">
            <span className="seat-legend-item"><span className="seat-legend-dot"/> Libre</span>
            <span className="seat-legend-item"><span className="seat-legend-dot on"/> Choisi</span>
            <span className="seat-legend-item"><span className="seat-legend-dot taken"/> Occupé</span>
          </div>
        </div>

        <div className="seat-selected-card">
          <b>{picked.length} place{picked.length > 1 ? 's' : ''} sélectionnée{picked.length > 1 ? 's' : ''}</b>
          <div className="seat-selected-list">
            {picked.length === 0
              ? <em>Tape sur un siège libre pour le choisir.</em>
              : pickedLabel
            }
          </div>
        </div>

        {error && <p style={{ padding: '0 20px', color: 'var(--bad)' }}>{error}</p>}

        <div className="help-banner" style={{ marginTop: 14 }}>
          <div className="help-banner-icon"><Ic name="info" size={20}/></div>
          <div className="help-banner-text">
            <b>Astuce</b>
            Choisis des places côte à côte sur la même rangée pour rester ensemble.
          </div>
        </div>
        <div style={{ height: 20 }}/>
      </div>
      <div className="action-bar">
        <div className="action-bar-summary">
          <span className="lbl">{picked.length} place{picked.length > 1 ? 's' : ''} × {pricePer} €</span>
          <b className="val">{total} €</b>
        </div>
        <button className="btn-primary" disabled={picked.length === 0 || busy} onClick={handleContinue}>
          {busy ? 'Chargement…' : 'Continuer'}
          {!busy && <Ic name="arrow" size={20}/>}
        </button>
      </div>
    </div>
  );
};

// ── SCREEN 5 — Récapitulatif + paiement Stripe ────────────────
const ScrPay = () => {
  const { appState, setAppState, goTo } = useCtx();
  const { match, zone, holdId, selectedSeats, qty } = appState;
  const effectiveQty = selectedSeats?.length || qty || 1;
  const pricePer     = zone?.price || 0;
  const total        = pricePer * effectiveQty;

  const [holderNames,   setHolderNames]   = useState(() => Array.from({ length: effectiveQty }, () => ''));
  const [step,          setStep]          = useState('names');  // 'names' | 'stripe'
  const [orderData,     setOrderData]     = useState(null);
  const [error,         setError]         = useState(null);
  const [busy,          setBusy]          = useState(false);

  const stripeRef   = useRef(null);
  const elementsRef = useRef(null);
  const payElRef    = useRef(null);

  const namesValid = holderNames.every(n => (n || '').trim().length >= 2);

  const handleNamesContinue = async () => {
    if (!namesValid || busy) return;
    setBusy(true);
    setError(null);
    try {
      const result = await API.createOrder(holdId, holderNames.map(n => n.trim()));
      setOrderData(result);
      setAppState(s => ({ ...s, orderId: result.order_id }));
      setStep('stripe');
    } catch (err) {
      if (handleAuthErr(err, setAppState, goTo)) return;
      if (err.code === 'HOLD_EXPIRED') { goTo('errSess'); return; }
      setError(err.message || 'Erreur lors de la commande.');
    } finally {
      setBusy(false);
    }
  };

  useEffect(() => {
    if (step !== 'stripe' || !orderData || !payElRef.current) return;
    if (stripeRef.current) return;
    try {
      const stripe   = window.Stripe(orderData.stripe_publishable_key);
      const elements = stripe.elements({ clientSecret: orderData.client_secret });
      const payEl    = elements.create('payment');
      payEl.mount(payElRef.current);
      stripeRef.current   = stripe;
      elementsRef.current = elements;
    } catch {}
  }, [step, orderData]);

  const handlePay = async () => {
    if (!stripeRef.current || !elementsRef.current || busy) return;
    setBusy(true);
    setError(null);
    try {
      const { error: stripeErr } = await stripeRef.current.confirmPayment({
        elements: elementsRef.current,
        redirect: 'if_required',
      });
      if (stripeErr) {
        setError(stripeErr.message);
        goTo('errPay');
        return;
      }
      const orderFull = await API.order(orderData.order_id);
      setAppState(s => ({
        ...s,
        order:      orderFull,
        orderId:    orderData.order_id,
        downloadCtx:{ type: 'order', orderId: orderData.order_id },
      }));
      goTo('done');
    } catch (err) {
      setError(err.message || 'Paiement refusé.');
      goTo('errPay');
    } finally {
      setBusy(false);
    }
  };

  if (step === 'stripe') {
    return (
      <div className="scr" data-screen-label="05 Paiement — carte">
        <BackBar/>
        <Steps step={4} total={4} label="Paiement"/>
        <div className="body">
          <div className="page-title">
            <h1>Paiement sécurisé</h1>
            <p>Total : <b>{total} €</b></p>
          </div>
          <div ref={payElRef} style={{ padding: '0 16px 24px' }}/>
          {error && <p style={{ padding: '0 20px', color: 'var(--bad)' }}>{error}</p>}
          <div className="help-banner" style={{ marginTop: 0 }}>
            <div className="help-banner-icon"><Ic name="lock" size={20}/></div>
            <div className="help-banner-text">
              <b>Paiement 100 % sécurisé</b>
              Tes coordonnées bancaires ne sont jamais conservées par le club.
            </div>
          </div>
        </div>
        <div className="action-bar">
          <div className="action-bar-summary">
            <span className="lbl">Total</span>
            <b className="val">{total} €</b>
          </div>
          <button className="btn-primary" onClick={handlePay} disabled={busy}>
            <Ic name="lock" size={18}/>
            {busy ? 'Traitement…' : `Payer ${total} €`}
          </button>
        </div>
      </div>
    );
  }

  // Étape noms + récap
  return (
    <div className="scr" data-screen-label="05 Paiement — récap">
      <BackBar/>
      <Steps step={4} total={4} label="Paiement"/>
      <div className="body">
        <div className="page-title">
          <h1>Tout est bon&nbsp;?</h1>
          <p>Vérifie ta commande et donne le nom de chaque personne.</p>
        </div>

        <div className="summary">
          <div className="summary-head">
            <b>{C.name || "Club"} — {match?.away || '…'}</b>
            <span>{match?.dateText || ''} à {match?.timeText || ''} · {C.stadiumShort || C.stadium || "Stade"}</span>
          </div>
          <div className="summary-body">
            <div className="summary-line">
              <span className="lbl">Tribune</span>
              <span className="val">{zone?.name || '…'}</span>
            </div>
            {selectedSeats?.length > 0 && (
              <div className="summary-line">
                <span className="lbl">Places</span>
                <span className="val">{selectedSeats.map(s => `Rang ${s.row} · ${s.number}`).join(', ')}</span>
              </div>
            )}
            <div className="summary-line">
              <span className="lbl">Tarif</span>
              <span className="val">{effectiveQty} × {pricePer} €</span>
            </div>
            <div className="summary-line">
              <span className="lbl">Frais de réservation</span>
              <span className="val">Offerts</span>
            </div>
            <div className="summary-total">
              <span>Total à payer</span>
              <span className="val">{total} €</span>
            </div>
          </div>
        </div>

        <div className="section-h">Nom des titulaires</div>
        <div className="transfer-card">
          <div className="transfer-form">
            {holderNames.map((name, i) => (
              <div key={i} className="field">
                <label>Place {i + 1}</label>
                <input
                  type="text"
                  placeholder="Prénom et nom"
                  value={name}
                  onChange={e => {
                    const n = [...holderNames];
                    n[i] = e.target.value;
                    setHolderNames(n);
                  }}
                />
              </div>
            ))}
          </div>
        </div>

        {error && <p style={{ padding: '0 20px', color: 'var(--bad)' }}>{error}</p>}

        <div className="help-banner" style={{ marginTop: 22 }}>
          <div className="help-banner-icon"><Ic name="lock" size={20}/></div>
          <div className="help-banner-text">
            <b>Paiement 100 % sécurisé</b>
            Tes coordonnées ne sont jamais conservées par le club.
          </div>
        </div>
      </div>
      <div className="action-bar">
        <div className="action-bar-summary">
          <span className="lbl">Total</span>
          <b className="val">{total} €</b>
        </div>
        <button className="btn-primary" disabled={!namesValid || busy} onClick={handleNamesContinue}>
          {busy ? 'Chargement…' : 'Continuer vers le paiement'}
          {!busy && <Ic name="arrow" size={20}/>}
        </button>
      </div>
    </div>
  );
};

// ── SCREEN 6 — Confirmation ───────────────────────────────────
const ScrDone = () => {
  const { appState } = useCtx();
  const { order, match, zone, selectedSeats, qty } = appState;
  const tickets      = order?.tickets?.filter(t => t && t.id) || [];
  const effectiveQty = tickets.length || selectedSeats?.length || qty || 1;

  return (
    <div className="scr" data-screen-label="06 Confirmation">
      <div className="topbar topbar--centered" style={{ background: "var(--navy)" }}>
        <div className="topbar-brand">
          <div className="topbar-name">{C.name || "Club"}<span>{C.billetterieLabel || "Billetterie officielle"}</span></div>
        </div>
        <img className="topbar-shield" src={C.logo || "assets/fcsm-logo.png"} alt={C.abbreviation || C.name || "Club"}/>
      </div>
      <div className="body" style={{ padding: 0 }}>
        <div className="confirm">
          <div className="confirm-check"><Ic name="check" size={48} stroke={3}/></div>
          <h1>C'est validé&nbsp;!</h1>
          <p>
            {effectiveQty > 1 ? `Tes ${effectiveQty} places sont prêtes.` : 'Ta place est prête.'}<br/>
            On t'envoie aussi un email de confirmation.
          </p>

          <div className="ticket">
            <div style={{ fontSize: 13, fontWeight: 700, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--yellow)", marginBottom: 4 }}>
              Billet officiel
            </div>
            <div style={{ fontSize: 22, fontWeight: 800, letterSpacing: "-0.02em", marginBottom: 12 }}>
              {C.name || "Club"} — {match?.away || '…'}
            </div>
            <div className="ticket-row">
              <span className="lbl">Date</span>
              <span className="val">{match?.dateText || '…'} · {match?.timeText || ''}</span>
            </div>
            <div className="ticket-row">
              <span className="lbl">Tribune</span>
              <span className="val">{zone?.name || '…'}</span>
            </div>
            {selectedSeats?.length > 0 && (
              <div className="ticket-row">
                <span className="lbl">Places</span>
                <span className="val">{selectedSeats.map(s => `Rang ${s.row} · ${s.number}`).join(', ')}</span>
              </div>
            )}
            <div className="ticket-row">
              <span className="lbl">Total payé</span>
              <span className="val">{order?.total != null ? order.total + ' €' : '…'}</span>
            </div>

            <div className="ticket-qr">
              <MiniQR size={100} token={tickets[0]?.qr_token}/>
            </div>
            <div style={{ textAlign: "center", fontSize: 12, color: "rgba(255,255,255,0.7)" }}>
              À présenter à l'entrée du stade
            </div>
          </div>

          <button className="btn-primary" style={{ marginTop: 8 }}>
            Voir mes billets
            <Ic name="arrow" size={20}/>
          </button>
          <button className="btn-text" style={{ marginTop: 6 }}>
            Retour à l'accueil
          </button>
        </div>
      </div>
    </div>
  );
};

// ── SCREEN 7 — Wallet abonné ──────────────────────────────────
const ScrWallet = () => {
  const { appState, setAppState, goTo } = useCtx();
  const [sub,     setSub]     = useState(appState.subscription || null);
  const [loading, setLoading] = useState(!appState.subscription);

  useEffect(() => {
    if (appState.subscription) return;
    if (!appState.token) { goTo('login'); return; }
    API.subscription()
      .then(d => {
        setSub(d.subscription);
        setAppState(s => ({ ...s, subscription: d.subscription }));
      })
      .catch(err => handleAuthErr(err, setAppState, goTo))
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <div className="scr"><TopBar/><Loading/></div>;
  if (!sub) return (
    <div className="scr"><TopBar/>
      <div className="body"><p style={{ padding: 20, color: 'var(--ink-2)' }}>Aucun abonnement actif.<br/><a href="#" onClick={e => { e.preventDefault(); goTo('aboPick'); }}>Découvrir les formules →</a></p></div>
    </div>
  );

  const nextMatch = appState.subscription?.next_match || null;

  return (
    <div className="scr" data-screen-label="07 Wallet abonné">
      <TopBar showHelp={true}/>
      <div className="body">
        <div className="wallet-intro">
          <h1>Mon abonnement</h1>
          <p>Une seule carte. Scannée à chaque match.</p>
        </div>

        <div className="abo-card">
          <div className="abo-card-head">
            <div className="abo-card-label">Carte abonné<small>Saison {sub.season}</small></div>
            <div className="abo-card-shield"><img src={C.logo || "assets/fcsm-logo.png"} alt={C.abbreviation || C.name || "Club"}/></div>
          </div>
          <div className="abo-card-name">{sub.holder_name}</div>
          <div className="abo-card-since">Abonné depuis {sub.seasons_count} saison{sub.seasons_count > 1 ? 's' : ''} · Merci ♥</div>
          <div className="abo-card-qr">
            <div className="abo-card-qr-frame">
              <MiniQR size={140} fg="#133478" token={sub.qr_token}/>
            </div>
            <div className="abo-card-qr-cap">Présente ce code à l'entrée</div>
          </div>
          <div className="abo-card-row">
            <div className="abo-card-cell"><small>Tribune</small><b>{sub.zone}</b></div>
            {sub.row        && <div className="abo-card-cell"><small>Rang</small><b>{sub.row}</b></div>}
            {sub.seat_number && <div className="abo-card-cell"><small>Place</small><b>{sub.seat_number}</b></div>}
          </div>
          <div className="abo-card-num"><span>N° abonné</span><b>{sub.number}</b></div>
        </div>

        <div className="wallet-actions">
          <button className="wallet-btn">
            <AppleWalletIcon size={24}/>
            <div className="wallet-btn-stack">
              <span className="lbl-small">Ajouter à</span>
              <span className="lbl-big">Apple Wallet</span>
            </div>
          </button>
          <button className="wallet-btn" style={{ background: "#fff", color: "#1F1F1F", border: "1.5px solid #DADCE0" }}>
            <GoogleWalletIcon size={24}/>
            <div className="wallet-btn-stack">
              <span className="lbl-small" style={{ opacity: 0.6 }}>Ajouter au</span>
              <span className="lbl-big">Google Wallet</span>
            </div>
          </button>
        </div>

        {nextMatch && (
          <div className="abo-next">
            <div className="abo-next-head">
              <b>Prochain match</b>
              <span className="status-pill">
                {(() => {
                  const diff = Math.ceil((new Date(nextMatch.date + 'T00:00:00') - new Date()) / 86400000);
                  return diff <= 0 ? "Aujourd'hui" : `Dans ${diff} jour${diff > 1 ? 's' : ''}`;
                })()}
              </span>
            </div>
            <div className="abo-next-body" style={{ paddingTop: 16, paddingBottom: 4 }}>
              <h3>{C.name || "Club"} — {nextMatch.away}</h3>
              <div className="when" style={{ marginBottom: 8 }}>
                {API.fmtDate(nextMatch.date)} · {(nextMatch.kickoff || '').slice(0,5).replace(':','h')}
              </div>
              {sub.row && (
                <div style={{ fontSize: 14, color: "var(--ink-2)", lineHeight: 1.4, maxWidth: 280, margin: "0 auto 10px" }}>
                  Ta place habituelle t'attend.<br/>
                  {sub.entrance_gate && <>Scanne ta carte à la porte <b>{sub.entrance_gate}</b>.</>}
                </div>
              )}
              <div className="abo-next-info" style={{ marginTop: 8 }}>
                {sub.row && sub.seat_number && (
                  <div className="abo-next-info-cell"><small>Ta place</small><b>Rang {sub.row} · {sub.seat_number}</b></div>
                )}
                {sub.entrance_gate && (
                  <div className="abo-next-info-cell"><small>Porte d'entrée</small><b>{sub.entrance_gate}</b></div>
                )}
                {nextMatch.doors_open && (
                  <div className="abo-next-info-cell"><small>Ouverture</small><b>{(nextMatch.doors_open || '').slice(0,5).replace(':','h')}</b></div>
                )}
                <div className="abo-next-info-cell"><small>Coup d'envoi</small><b>{(nextMatch.kickoff || '').slice(0,5).replace(':','h')}</b></div>
              </div>
            </div>
            <div className="abo-next-actions">
              <button className="btn-secondary">
                <Ic name="users" size={18}/>
                Je ne peux pas y aller — céder ma place
              </button>
            </div>
          </div>
        )}

        <div style={{ padding: "20px 16px 0" }}>
          <button className="btn-secondary" onClick={() => goTo('season')}>
            <Ic name="calendar" size={18}/>
            Voir tous mes matchs de la saison
          </button>
        </div>

        <div className="help-banner">
          <div className="help-banner-icon"><Ic name="info" size={20}/></div>
          <div className="help-banner-text">
            <b>Pas de billet à télécharger</b>
            Ta carte abonné fonctionne pour tous les matchs de la saison.
          </div>
        </div>
      </div>
    </div>
  );
};

// ── SCREEN 8 — Tous les matchs de la saison ───────────────────
const ScrSeason = () => {
  const { appState, setAppState, goTo } = useCtx();
  const [data,    setData]    = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!appState.token) { goTo('login'); return; }
    API.seasonMatches()
      .then(d => setData(d))
      .catch(err => handleAuthErr(err, setAppState, goTo))
      .finally(() => setLoading(false));
  }, []);

  const matches   = data?.matches || [];
  const upcoming  = matches.filter(m => m.status !== 'past');
  const past      = matches.filter(m => m.status === 'past');

  const formatMatchDate = (iso) => {
    const d = new Date(iso + 'T00:00:00');
    return { num: d.getDate(), month: API.FR_MONTHS_SHORT[d.getMonth()] };
  };

  const sub = appState.subscription;

  return (
    <div className="scr" data-screen-label="08 Tous mes matchs">
      <BackBar label="Mon abonnement"/>
      <div className="body">
        <div className="page-title">
          <h1>Tous mes matchs</h1>
          <p>{data ? `Saison ${data.season} · ${matches.length} matchs · ${upcoming.length} à venir` : 'Chargement…'}</p>
        </div>
        {loading ? <Loading/> : (
          <>
            <div className="section-h">À venir</div>
            <div className="season-list">
              {upcoming.map(m => {
                const { num, month } = formatMatchDate(m.match.date);
                const isNext       = m.status === 'upcoming' && upcoming[0]?.slot_id === m.slot_id;
                const isTransferred = m.status === 'transferred';
                return (
                  <div key={m.slot_id} className={`season-row ${isTransferred ? 'transferred' : ''}`}
                    onClick={() => { setAppState(s => ({...s, downloadCtx: {type:'subscription'}})); goTo('wallet'); }}>
                    <div className="season-row-date"><b>{num}</b><span>{month}</span></div>
                    <div className="season-row-body">
                      <b>{C.name || "Club"} — {m.match.away}</b>
                      <span>
                        {isTransferred
                          ? `Place cédée · QR transmis à ton invité`
                          : sub?.row
                            ? `Rang ${sub.row}, place ${sub.seat_number} · scanne ta carte`
                            : 'Scanne ta carte abonné'}
                      </span>
                    </div>
                    <div className={`season-row-pill ${isNext ? 'ok' : isTransferred ? 'transferred' : ''}`}>
                      {isTransferred ? 'Cédé' : isNext ? 'Prochain' : 'À venir'}
                    </div>
                  </div>
                );
              })}
            </div>
            {past.length > 0 && (
              <>
                <div className="section-h">Joués</div>
                <div className="season-list">
                  {past.map(m => {
                    const { num, month } = formatMatchDate(m.match.date);
                    return (
                      <div key={m.slot_id} className="season-row past">
                        <div className="season-row-date"><b>{num}</b><span>{month}</span></div>
                        <div className="season-row-body">
                          <b>{C.name || "Club"} — {m.match.away}</b>
                          <span>{C.stadiumShort || C.stadium || "Stade"}</span>
                        </div>
                        <div className="season-row-pill past">Joué</div>
                      </div>
                    );
                  })}
                </div>
              </>
            )}
          </>
        )}
      </div>
    </div>
  );
};

// ── SCREEN 9 — Céder une place ────────────────────────────────
const ScrTransfer = () => {
  const { appState, setAppState, goTo } = useCtx();
  const [recipientName,  setRecipientName]  = useState('');
  const [recipientEmail, setRecipientEmail] = useState('');
  const [message,        setMessage]        = useState('');
  const [busy,           setBusy]           = useState(false);
  const [error,          setError]          = useState(null);

  const sub       = appState.subscription;
  const nextMatch = sub?.next_match;

  if (!sub || !nextMatch) return (
    <div className="scr"><BackBar label="Mon abonnement"/>
      <div className="body"><p style={{ padding: 20, color: 'var(--ink-2)' }}>Aucun prochain match trouvé.</p></div>
    </div>
  );

  const handleSubmit = async () => {
    if (busy || !recipientName.trim() || !recipientEmail.trim()) return;
    setBusy(true);
    setError(null);
    try {
      const result = await API.transfer(nextMatch.id, recipientName.trim(), recipientEmail.trim(), message.trim() || undefined);
      setAppState(s => ({ ...s, transferResult: result }));
      goTo('transferDone');
    } catch (err) {
      if (handleAuthErr(err, setAppState, goTo)) return;
      setError(err.message || 'Erreur lors de la cession.');
    } finally {
      setBusy(false);
    }
  };

  const d = new Date(nextMatch.date + 'T00:00:00');

  return (
    <div className="scr" data-screen-label="09 Céder une place">
      <BackBar label="Mon abonnement"/>
      <div className="body">
        <div className="page-title">
          <h1>Céder ma place</h1>
          <p>Donne ta place à un proche pour ce match. Tu reprends ta place automatiquement au match suivant.</p>
        </div>

        <div className="transfer-card">
          <div className="transfer-recap">
            <div style={{ width:52,height:52,background:"var(--soft)",border:"1px solid var(--line)",borderRadius:12,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",flexShrink:0 }}>
              <b style={{ fontSize:22,fontWeight:800,color:"var(--navy)",lineHeight:1 }}>{d.getDate()}</b>
              <span style={{ fontSize:10,fontWeight:600,color:"var(--ink-2)",marginTop:2 }}>{API.FR_MONTHS_SHORT[d.getMonth()].toUpperCase().replace('.','')}</span>
            </div>
            <div>
              <b>{C.name || "Club"} — {nextMatch.away}</b>
              <span>{API.fmtDate(nextMatch.date)} à {(nextMatch.kickoff||'').slice(0,5).replace(':','h')}{sub.row ? ` · Rang ${sub.row}, place ${sub.seat_number}` : ''}</span>
            </div>
          </div>

          <div className="transfer-form">
            <div className="field">
              <label>À qui veux-tu donner ta place&nbsp;?</label>
              <input type="text" placeholder="Prénom et nom" value={recipientName} onChange={e => setRecipientName(e.target.value)}/>
            </div>
            <div className="field">
              <label>Son email</label>
              <input type="email" placeholder="exemple@email.fr" value={recipientEmail} onChange={e => setRecipientEmail(e.target.value)}/>
              <span className="field-hint">On lui envoie le billet par email. C'est gratuit.</span>
            </div>
            <div className="field">
              <label>Un petit message (facultatif)</label>
              <textarea rows="3" placeholder="Bon match !" value={message} onChange={e => setMessage(e.target.value)}/>
            </div>
          </div>
        </div>

        {error && <p style={{ padding: '0 20px', color: 'var(--bad)' }}>{error}</p>}

        <div className="help-banner" style={{ marginTop: 18 }}>
          <div className="help-banner-icon"><Ic name="info" size={20}/></div>
          <div className="help-banner-text">
            <b>Comment ça marche</b>
            On génère un QR unique à son nom pour ce match. Ta carte abonné est désactivée juste pour cette date — elle redevient active au match suivant.
          </div>
        </div>
        <div style={{ height: 20 }}/>
      </div>
      <div className="action-bar">
        <button
          className="btn-primary"
          disabled={!recipientName.trim() || !recipientEmail.trim() || busy}
          onClick={handleSubmit}
        >
          {busy ? 'Envoi…' : `Envoyer la place à ${recipientName || '…'}`}
          {!busy && <Ic name="arrow" size={20}/>}
        </button>
      </div>
    </div>
  );
};

// ── SCREEN 10 — Confirmation cession ─────────────────────────
const ScrTransferDone = () => {
  const { appState, setAppState, goTo } = useCtx();
  const result  = appState.transferResult;
  const sub     = appState.subscription;

  const cancelTransfer = async () => {
    if (!result?.transfer_id) return;
    try {
      await API.cancelTransfer(result.transfer_id);
      setAppState(s => ({ ...s, transferResult: null }));
      goTo('wallet');
    } catch {}
  };

  return (
    <div className="scr" data-screen-label="10 Cession envoyée">
      <TopBar showHelp={false}/>
      <div className="body" style={{ padding: 0 }}>
        <div className="confirm">
          <div className="confirm-check"><Ic name="check" size={48} stroke={3}/></div>
          <h1>C'est envoyé&nbsp;!</h1>
          <p>
            {result?.recipient_name || 'Ton invité'} a reçu ton billet par email.<br/>
            Il peut l'utiliser dès maintenant.
          </p>

          {result && (
            <div style={{ background:"var(--soft)",border:"1px solid var(--line)",borderRadius:14,padding:"18px 20px",margin:"0 0 24px",textAlign:"left" }}>
              <div style={{ fontSize:12,fontWeight:700,color:"var(--ink-2)",letterSpacing:"0.08em",textTransform:"uppercase",marginBottom:10 }}>Cession active</div>
              <div style={{ display:"flex",alignItems:"center",gap:14 }}>
                <div style={{ width:44,height:44,borderRadius:"50%",background:"var(--navy)",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",fontSize:17,fontWeight:700 }}>
                  {(result.recipient_name || '?')[0].toUpperCase()}
                </div>
                <div style={{ flex:1 }}>
                  <b style={{ display:"block",fontSize:16,color:"var(--navy)" }}>{result.recipient_name}</b>
                  <span style={{ fontSize:13,color:"var(--ink-2)" }}>
                    {result.recipient_email} · {C.name||"Club"} — {result.match?.away || '…'} · {API.fmtDate(result.match?.date)}
                  </span>
                </div>
              </div>
              <button
                onClick={cancelTransfer}
                style={{ marginTop:14,background:"transparent",border:0,color:"var(--bad)",fontFamily:"inherit",fontSize:14,fontWeight:600,padding:0,textDecoration:"underline",textUnderlineOffset:4,cursor:"pointer" }}
              >
                Annuler cette cession
              </button>
            </div>
          )}

          <p style={{ fontSize:14,marginBottom:24 }}>Ta place te revient automatiquement <b>au match suivant</b>.</p>
          <button className="btn-primary">
            Retour à mon abonnement
            <Ic name="arrow" size={20}/>
          </button>
        </div>
      </div>
    </div>
  );
};

// ── SCREEN 11 — Historique ────────────────────────────────────
const ScrHistory = () => {
  const { appState, setAppState, goTo } = useCtx();
  const [orders,  setOrders]  = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!appState.token) { goTo('login'); return; }
    API.orders()
      .then(os => setOrders(os))
      .catch(err => handleAuthErr(err, setAppState, goTo))
      .finally(() => setLoading(false));
  }, []);

  const upcoming = orders.filter(o => o.match && new Date(o.match.date + 'T00:00:00') >= new Date());
  const past     = orders.filter(o => !o.match || new Date(o.match.date + 'T00:00:00') < new Date());

  const openOrder = (o) => {
    setAppState(s => ({ ...s, downloadCtx: { type: 'order', orderId: o.id } }));
    goTo('download');
  };

  const OrderRow = ({ o }) => (
    <div className="order-row" onClick={() => openOrder(o)}>
      <div className="order-row-icon"><Ic name="ticket" size={20}/></div>
      <div className="order-row-body">
        <b>{o.match ? `${C.name || "Club"} — ${o.match.away}` : 'Commande'}</b>
        <span>{o.match ? `${API.fmtDate(o.match.date)} · ` : ''}{o.ticket_count} billet{o.ticket_count > 1 ? 's' : ''}</span>
      </div>
      <div className="order-row-meta">
        <b>{o.total} €</b>
        <span>Le {API.fmtDate(o.created_at)}</span>
      </div>
    </div>
  );

  return (
    <div className="scr" data-screen-label="11 Historique">
      <BackBar label="Mon compte"/>
      <div className="body">
        <div className="page-title">
          <h1>Mes achats</h1>
          <p>Retrouve tous tes billets, factures et commandes.</p>
        </div>
        {loading ? <Loading/> : (
          <>
            {upcoming.length > 0 && (
              <>
                <div className="section-h">À venir</div>
                <div className="order-list">{upcoming.map(o => <OrderRow key={o.id} o={o}/>)}</div>
              </>
            )}
            {past.length > 0 && (
              <>
                <div className="section-h">Matchs passés</div>
                <div className="order-list">{past.map(o => <OrderRow key={o.id} o={o}/>)}</div>
              </>
            )}
            {orders.length === 0 && (
              <p style={{ padding: '20px', color: 'var(--ink-2)' }}>Aucun achat pour le moment.</p>
            )}
          </>
        )}
        <div className="help-banner">
          <div className="help-banner-icon"><Ic name="info" size={20}/></div>
          <div className="help-banner-text">
            <b>Factures et reçus</b>
            Toutes tes factures sont disponibles au format PDF.
            Une question&nbsp;? Appelle-nous au <a href={`tel:${C.phone||""}`}>{C.phone || "notre service billetterie"}</a>.
          </div>
        </div>
      </div>
    </div>
  );
};

// ── SCREEN 12 — Téléchargement de places ─────────────────────
const ScrDownload = () => {
  const { appState } = useCtx();
  const [tickets, setTickets] = useState([]);
  const [active,  setActive]  = useState(0);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const ctx = appState.downloadCtx;
    if (!ctx) { setLoading(false); return; }

    if (ctx.type === 'subscription') {
      const sub = appState.subscription;
      if (sub) {
        setTickets([{
          holder_name: sub.holder_name,
          qr_token:    sub.qr_token,
          zone:        sub.zone,
          seat:        sub.row ? { row: sub.row, number: sub.seat_number } : null,
          match:       appState.subscription?.next_match || null,
          isSubscription: true,
        }]);
      }
      setLoading(false);
      return;
    }

    if (ctx.type === 'order' && ctx.orderId) {
      API.order(ctx.orderId)
        .then(async (o) => {
          const raw = (o.tickets || []).filter(t => t && t.id);
          if (raw.length === 0) { setLoading(false); return; }
          const full = await Promise.all(raw.map(t => API.ticket(t.id).catch(() => t)));
          setTickets(full);
        })
        .catch(() => {})
        .finally(() => setLoading(false));
    } else {
      setLoading(false);
    }
  }, []);

  if (loading) return <div className="scr"><BackBar label="Mes achats"/><Loading/></div>;

  const t = tickets[active] || null;
  const match = t?.match ? API.fmtMatch({ ...t.match, kickoff: t.match.kickoff || '' }) : null;

  return (
    <div className="scr" data-screen-label="12 Télécharger mes places">
      <BackBar label="Mes achats"/>
      <div className="body">
        <div className="page-title">
          <h1>Mes places</h1>
          <p>Présente le QR à l'entrée du stade, ou télécharge-le.</p>
        </div>

        {tickets.length > 1 && (
          <div className="ticket-multi-nav">
            <button onClick={() => setActive(Math.max(0, active - 1))} disabled={active === 0} aria-label="Précédent">
              <Ic name="back" size={16} stroke={2.2}/>
            </button>
            <span>Billet <b>{active + 1}</b> sur <b>{tickets.length}</b></span>
            <button onClick={() => setActive(Math.min(tickets.length - 1, active + 1))} disabled={active === tickets.length - 1} aria-label="Suivant" style={{ transform: "rotate(180deg)" }}>
              <Ic name="back" size={16} stroke={2.2}/>
            </button>
          </div>
        )}

        {t && (
          <div className="ticket-detail">
            <div className="ticket-detail-top">
              <div className="ticket-detail-label">Billet officiel · {C.abbreviation || C.name || "Club"}</div>
              <div className="ticket-detail-match">{C.name || "Club"}{match ? ` — ${match.away}` : ''}</div>
              {match && (
                <div className="ticket-detail-when">{match.dateText} · {match.timeText} · {C.stadiumShort || C.stadium || "Stade"}</div>
              )}
            </div>
            <div className="ticket-detail-qr">
              <div className="ticket-detail-qr-frame">
                <MiniQR size={170} token={t.qr_token}/>
              </div>
              <div className="ticket-detail-qr-id">
                N° {(C.abbreviation || "TK")}–{(t.id || t.qr_token || '').slice(0, 8).toUpperCase()}
              </div>
            </div>
            <div className="ticket-detail-info">
              <div><small>Au nom de</small><b>{t.holder_name}</b></div>
              <div><small>Tribune</small><b>{t.zone || '—'}</b></div>
              {t.seat && (
                <div><small>Rang &amp; place</small><b>Rang {t.seat.row} · place {t.seat.number}</b></div>
              )}
              {match?.doors_open && (
                <div><small>Ouverture portes</small><b>{(match.doors_open||'').slice(0,5).replace(':','h')}</b></div>
              )}
            </div>
          </div>
        )}

        {!t && <p style={{ padding: '20px', color: 'var(--ink-2)' }}>Aucun billet trouvé.</p>}

        <div className="section-h">Télécharger ou envoyer</div>
        <div className="download-list">
          <button className="download-btn">
            <div className="download-btn-icon dark"><AppleWalletIcon size={22}/></div>
            <div className="download-btn-body"><b>Ajouter à Apple Wallet</b><span>Le billet apparaît dans ton iPhone</span></div>
            <Ic name="arrow" size={20}/>
          </button>
          <button className="download-btn">
            <div className="download-btn-icon google"><GoogleWalletIcon size={22}/></div>
            <div className="download-btn-body"><b>Ajouter à Google Wallet</b><span>Pour les téléphones Android</span></div>
            <Ic name="arrow" size={20}/>
          </button>
          <button className="download-btn">
            <div className="download-btn-icon" style={{ background:"#FFE7E7",color:"#C44141" }}><Ic name="download-pdf" size={22}/></div>
            <div className="download-btn-body"><b>Télécharger en PDF</b><span>Pour imprimer ou enregistrer</span></div>
            <Ic name="arrow" size={20}/>
          </button>
          <button className="download-btn">
            <div className="download-btn-icon"><Ic name="mail" size={22}/></div>
            <div className="download-btn-body"><b>Renvoyer par email</b><span>À ton adresse email</span></div>
            <Ic name="arrow" size={20}/>
          </button>
        </div>

        <div style={{ height: 20 }}/>
      </div>
    </div>
  );
};

window.SimpleScreens = {
  ScrHome, ScrList, ScrZones, ScrSeats, ScrPay, ScrDone,
  ScrWallet, ScrSeason, ScrTransfer, ScrTransferDone,
  ScrHistory, ScrDownload,
};

window.SimpleHelpers = { Ic, BackBar, Steps, MiniQR };
