// pages.jsx — Diagnostic, Shop, Tracking, Account pages

// ============================================
// DIAGNOSTIC
// ============================================
const DEVICE_TYPES = [
  { id: "iphone", name: "iPhone", sub: "Tous modèles depuis 6", icon: <IconPhone size={24} /> },
  { id: "samsung", name: "Samsung", sub: "Galaxy S, A, Note", icon: <IconPhone size={24} /> },
  { id: "xiaomi", name: "Xiaomi", sub: "Mi, Redmi, Poco", icon: <IconPhone size={24} /> },
  { id: "mac", name: "MacBook / iMac", sub: "Tous Apple Silicon & Intel", icon: <IconLaptop size={24} /> },
  { id: "pc", name: "PC / Portable", sub: "Toutes marques", icon: <IconLaptop size={24} /> },
  { id: "ipad", name: "iPad", sub: "Air, Pro, mini", icon: <IconTablet size={24} /> },
];

const ISSUES = [
  { id: "screen", name: "Écran cassé", sub: "Vitre fissurée ou LCD KO" },
  { id: "battery", name: "Batterie", sub: "Décharge rapide, gonflée" },
  { id: "charger", name: "Connecteur charge", sub: "Charge mal ou pas du tout" },
  { id: "water", name: "Désoxydation", sub: "Tombé dans l'eau" },
  { id: "speaker", name: "Haut-parleur / micro", sub: "Son crachoté ou muet" },
  { id: "camera", name: "Caméra", sub: "Flou, tâche, ne s'ouvre pas" },
  { id: "board", name: "Carte mère", sub: "Ne s'allume plus" },
  { id: "other", name: "Autre", sub: "Diagnostic complet en boutique" },
];

const IPHONE_MODELS = Object.keys(window.RN_DATA.repairPrices);

const REQUEST_SLOTS = [
  { value: "asap",        label: "Dès que possible" },
  { value: "matin",       label: "Matin (10h – 13h)" },
  { value: "après-midi",  label: "Après-midi (14h – 18h)" },
  { value: "soirée",      label: "Soirée (18h – 21h)" },
];

const Diagnostic = ({ compact = false, navigate }) => {
  const [step, setStep] = React.useState(0);
  const [device, setDevice] = React.useState(null);
  const [model, setModel] = React.useState(null);
  const [issue, setIssue] = React.useState(null);

  // Booking state
  const [booking, setBooking]     = React.useState(null); // null | 'form' | 'sending' | 'done'
  const [bookForm, setBookForm]   = React.useState({ name: "", phone: "", email: "", date: "", slot: "asap", notes: "" });
  const [bookError, setBookError] = React.useState("");

  const openBooking = async () => {
    const db = window.SUPABASE;
    if (db) {
      const { data: { session } } = await db.auth.getSession();
      if (session) {
        const { data: cust } = await db.from("customers").select("name, phone").eq("email", session.user.email).maybeSingle();
        setBookForm(f => ({
          ...f,
          name:  cust?.name  || session.user.user_metadata?.name || "",
          email: session.user.email || "",
          phone: cust?.phone || "",
        }));
      }
    }
    setBooking("form");
  };

  const submitBooking = async (e) => {
    e.preventDefault();
    setBookError("");
    setBooking("sending");
    try {
      const db = window.SUPABASE;
      const { data: { session } } = await db.auth.getSession();
      const { error } = await db.from("client_requests").insert({
        type:            "diagnostic",
        auth_uid:        session?.user?.id || null,
        name:            bookForm.name,
        email:           bookForm.email || session?.user?.email || null,
        phone:           bookForm.phone || null,
        device_type:     device,
        device_model:    model,
        issue_type:      issue,
        estimated_price: getPrice() || null,
        preferred_date:  bookForm.date || null,
        preferred_slot:  bookForm.slot,
        notes:           bookForm.notes || null,
      });
      if (error) throw error;
      setBooking("done");
    } catch (err) {
      setBookError("Erreur lors de l'envoi. Réessayez ou appelez-nous.");
      setBooking("form");
    }
  };

  const steps = ["Appareil", "Modèle", "Panne", "Devis"];
  const isApple = device === "iphone";

  const getPrice = () => {
    if (issue === "screen" && isApple && model && window.RN_DATA.repairPrices[model]) {
      return window.RN_DATA.repairPrices[model];
    }
    // synthetic estimates for other cases
    const base = {
      battery: 49,
      charger: 59,
      water: 89,
      speaker: 59,
      camera: 79,
      board: 149,
      other: null,
    };
    if (issue === "screen") return 120; // generic
    return base[issue];
  };

  const price = getPrice();
  const points = price ? Math.round(price) : 0;

  const reset = () => { setStep(0); setDevice(null); setModel(null); setIssue(null); setBooking(null); setBookError(""); };

  return (
    <div className="diag-card" style={compact ? { padding: 32 } : {}}>
      <div className="diag-progress">
        {steps.map((s, i) => (
          <div key={s} className={"step " + (i < step ? "done" : i === step ? "active" : "")} />
        ))}
      </div>
      <div className="diag-step-label">
        Étape {step + 1} / {steps.length} — {steps[step]}
      </div>

      {step === 0 && (
        <div key="s0" className="ink-rise">
          <h3 className="diag-question">Quel appareil ?</h3>
          <div className="diag-options">
            {DEVICE_TYPES.map((d) => (
              <button key={d.id} className={"diag-option" + (device === d.id ? " selected" : "")}
                onClick={() => { setDevice(d.id); setTimeout(() => setStep(1), 200); }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                  <span>{d.name}</span>
                  <span style={{ color: "var(--crimson)" }}>{d.icon}</span>
                </div>
                <span className="sub">{d.sub}</span>
              </button>
            ))}
          </div>
        </div>
      )}

      {step === 1 && (
        <div key="s1" className="ink-rise">
          <h3 className="diag-question">{isApple ? "Quel modèle d'iPhone ?" : "Modèle ?"}</h3>
          {isApple ? (
            <div className="diag-options" style={{ maxHeight: 320, overflowY: "auto", gridTemplateColumns: "1fr 1fr" }}>
              {IPHONE_MODELS.map((m) => (
                <button key={m} className={"diag-option" + (model === m ? " selected" : "")}
                  onClick={() => { setModel(m); setTimeout(() => setStep(2), 200); }}>
                  <span>{m}</span>
                </button>
              ))}
            </div>
          ) : (
            <div className="field" style={{ marginTop: 0 }}>
              <input
                type="text"
                placeholder="ex: Galaxy S23, MacBook Pro 14 M2..."
                style={{
                  background: "var(--ink-3)", border: "1px solid var(--ink-line)",
                  padding: "16px", borderRadius: 4, color: "var(--cream)", fontSize: 15,
                }}
                value={model || ""}
                onChange={(e) => setModel(e.target.value)}
              />
            </div>
          )}
          <div className="diag-nav">
            <button className="btn btn--ghost btn--small" onClick={() => setStep(0)} style={{ color: "var(--cream)" }}>
              <IconArrowLeft /> <span>Retour</span>
            </button>
            <button className="btn btn--primary btn--small" disabled={!model} onClick={() => setStep(2)} style={{ opacity: model ? 1 : 0.4 }}>
              <span>Continuer</span> <IconArrowRight />
            </button>
          </div>
        </div>
      )}

      {step === 2 && (
        <div key="s2" className="ink-rise">
          <h3 className="diag-question">Quelle panne ?</h3>
          <div className="diag-options">
            {ISSUES.map((i) => (
              <button key={i.id} className={"diag-option" + (issue === i.id ? " selected" : "")}
                onClick={() => { setIssue(i.id); setTimeout(() => setStep(3), 200); }}>
                <span>{i.name}</span>
                <span className="sub">{i.sub}</span>
              </button>
            ))}
          </div>
          <div className="diag-nav">
            <button className="btn btn--ghost btn--small" onClick={() => setStep(1)} style={{ color: "var(--cream)" }}>
              <IconArrowLeft /> <span>Retour</span>
            </button>
          </div>
        </div>
      )}

      {step === 3 && (
        <div key="s3" className="diag-result ink-rise">
          <span className="diag-step-label" style={{ marginBottom: 8 }}>Devis instantané</span>
          {price !== null ? (
            <div className="price">
              <span className="currency">€</span>{price}
              <span style={{ fontSize: 14, fontFamily: "var(--font-mono)", color: "var(--muted-2)", marginLeft: 12, letterSpacing: 0.1 }}>TTC</span>
            </div>
          ) : (
            <div className="price" style={{ fontSize: 56 }}>Sur devis</div>
          )}
          <div className="diag-summary">
            <div className="row"><span>Appareil</span><strong>{DEVICE_TYPES.find(d => d.id === device)?.name}</strong></div>
            <div className="row"><span>Modèle</span><strong>{model}</strong></div>
            <div className="row"><span>Panne</span><strong>{ISSUES.find(i => i.id === issue)?.name}</strong></div>
            <div className="row"><span>Délai estimé</span><strong>{issue === "screen" || issue === "battery" ? "30 min" : "24-48h"}</strong></div>
            {price && <div className="row"><span>Shuriken Points</span><strong style={{ color: "var(--crimson)" }}>+{points} pts</strong></div>}
            <div className="row"><span>Garantie</span><strong>6 mois pièces & main-d'œuvre</strong></div>
          </div>
          {booking === "done" ? (
            <div style={{ padding: 20, background: "rgba(22,163,74,0.1)", border: "1px solid rgba(22,163,74,0.3)", borderRadius: 8, color: "#16a34a", textAlign: "center" }}>
              <div style={{ fontSize: 22, marginBottom: 6 }}>✓ Demande envoyée !</div>
              <div style={{ fontSize: 13, color: "var(--muted-2)" }}>Nous vous contacterons dans les 30 minutes pour confirmer le créneau.</div>
              <button className="btn btn--ghost btn--small" onClick={() => { reset(); setBooking(null); }} style={{ color: "var(--cream)", marginTop: 12 }}>Nouvelle demande</button>
            </div>
          ) : booking === "form" || booking === "sending" ? (
            <form onSubmit={submitBooking} style={{ display: "flex", flexDirection: "column", gap: 12, marginTop: 8 }}>
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--crimson)", letterSpacing: 0.15, textTransform: "uppercase", marginBottom: 4 }}>Réserver un créneau</div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }} className="form-2col">
                <div className="field" style={{ margin: 0 }}>
                  <label style={{ fontSize: 11 }}>Nom</label>
                  <input required value={bookForm.name} onChange={e => setBookForm(f => ({ ...f, name: e.target.value }))} style={{ background: "var(--ink-3)", border: "1px solid var(--ink-line)", padding: 10, borderRadius: 4, color: "var(--cream)", fontSize: 14 }} />
                </div>
                <div className="field" style={{ margin: 0 }}>
                  <label style={{ fontSize: 11 }}>Téléphone</label>
                  <input required value={bookForm.phone} onChange={e => setBookForm(f => ({ ...f, phone: e.target.value }))} type="tel" style={{ background: "var(--ink-3)", border: "1px solid var(--ink-line)", padding: 10, borderRadius: 4, color: "var(--cream)", fontSize: 14 }} />
                </div>
              </div>
              <div className="field" style={{ margin: 0 }}>
                <label style={{ fontSize: 11 }}>Email</label>
                <input value={bookForm.email} onChange={e => setBookForm(f => ({ ...f, email: e.target.value }))} type="email" style={{ background: "var(--ink-3)", border: "1px solid var(--ink-line)", padding: 10, borderRadius: 4, color: "var(--cream)", fontSize: 14 }} />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }} className="form-2col">
                <div className="field" style={{ margin: 0 }}>
                  <label style={{ fontSize: 11 }}>Date souhaitée</label>
                  <input value={bookForm.date} onChange={e => setBookForm(f => ({ ...f, date: e.target.value }))} type="date" min={new Date().toISOString().split("T")[0]} style={{ background: "var(--ink-3)", border: "1px solid var(--ink-line)", padding: 10, borderRadius: 4, color: "var(--cream)", fontSize: 14, colorScheme: "dark" }} />
                </div>
                <div className="field" style={{ margin: 0 }}>
                  <label style={{ fontSize: 11 }}>Créneau</label>
                  <select value={bookForm.slot} onChange={e => setBookForm(f => ({ ...f, slot: e.target.value }))} style={{ background: "var(--ink-3)", border: "1px solid var(--ink-line)", padding: 10, borderRadius: 4, color: "var(--cream)", fontSize: 14 }}>
                    {REQUEST_SLOTS.map(s => <option key={s.value} value={s.value}>{s.label}</option>)}
                  </select>
                </div>
              </div>
              <div className="field" style={{ margin: 0 }}>
                <label style={{ fontSize: 11 }}>Notes (optionnel)</label>
                <textarea value={bookForm.notes} onChange={e => setBookForm(f => ({ ...f, notes: e.target.value }))} rows={2} style={{ background: "var(--ink-3)", border: "1px solid var(--ink-line)", padding: 10, borderRadius: 4, color: "var(--cream)", fontSize: 14, resize: "vertical" }} />
              </div>
              {bookError && <div style={{ color: "var(--crimson)", fontSize: 12 }}>{bookError}</div>}
              <div style={{ display: "flex", gap: 8 }}>
                <button className="btn btn--primary" type="submit" disabled={booking === "sending"} style={{ flex: 1, justifyContent: "center", opacity: booking === "sending" ? 0.6 : 1 }}>
                  <span>{booking === "sending" ? "Envoi…" : "Confirmer la demande"}</span>
                  {booking !== "sending" && <IconArrowRight />}
                </button>
                <button type="button" className="btn btn--ghost btn--small" onClick={() => setBooking(null)} style={{ color: "var(--cream)" }}>Annuler</button>
              </div>
            </form>
          ) : (
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
              <button className="btn btn--primary" style={{ flex: 1 }} onClick={openBooking}>
                <span>Réserver un créneau</span> <IconArrowRight />
              </button>
              <button className="btn btn--ghost btn--small" onClick={reset} style={{ color: "var(--cream)" }}>Recommencer</button>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

const DiagnosticPage = ({ navigate }) => {
  return (
    <div className="paper">
      <div className="page-hero">
        <span className="kanji">診断</span>
        <div className="container">
          <span className="kicker" style={{ color: "var(--crimson)" }}>DIAGNOSTIC EN LIGNE</span>
          <h1>Trois questions.<br/><em style={{ fontStyle: "italic", color: "var(--crimson)" }}>Un devis exact.</em></h1>
          <p>Basé sur nos tarifs réels en boutique. Aucune surprise au moment du règlement — le prix affiché est le prix final, garantie 6 mois incluse.</p>
        </div>
      </div>
      <section className="section section--dark" style={{ paddingTop: 0 }}>
        <div className="container">
          <div style={{ maxWidth: 720, margin: "0 auto" }}>
            <Diagnostic navigate={navigate} />
          </div>
          <div style={{ marginTop: 64, display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))", gap: 32, maxWidth: 920, margin: "64px auto 0", color: "var(--muted-2)", fontSize: 14 }}>
            <div>
              <div style={{ color: "var(--crimson)", fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: 0.15, marginBottom: 8 }}>01 / FIABILITÉ</div>
              <div>Pièces certifiées OEM premium uniquement. Pas d'écrans aftermarket bas de gamme.</div>
            </div>
            <div>
              <div style={{ color: "var(--crimson)", fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: 0.15, marginBottom: 8 }}>02 / RAPIDITÉ</div>
              <div>30 min pour la majorité des écrans et batteries en stock immédiat.</div>
            </div>
            <div>
              <div style={{ color: "var(--crimson)", fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: 0.15, marginBottom: 8 }}>03 / TRANSPARENCE</div>
              <div>Tarif fixe affiché. Si la réparation s'avère impossible, c'est gratuit.</div>
            </div>
          </div>
        </div>
      </section>
    </div>
  );
};

// ============================================
// SHOP
// ============================================
const ProductImage = ({ color, name }) => {
  const palette = {
    "hydrogel": ["#e0f2fe", "#7dd3fc"],
    "glass": ["#f1f5f9", "#cbd5e1"],
    "case-clear": ["#f1f5f9", "#e2e8f0"],
    "case-red": ["#fee2e2", "#c8102e"],
    "case-black": ["#27272a", "#09090b"],
    "case-cream": ["#fef3c7", "#fde68a"],
    "charger": ["#fafafa", "#a1a1aa"],
    "cable": ["#f5f5f4", "#a8a29e"],
    "lens": ["#e0e7ff", "#818cf8"],
    "audio": ["#fce7f3", "#f9a8d4"],
  };
  const [bg, fg] = palette[color] || ["#f5f1e8", "#ddd5c0"];

  return (
    <svg width="100%" viewBox="0 0 200 200" preserveAspectRatio="xMidYMid slice" style={{ display: "block", background: bg }}>
      <defs>
        <pattern id={"hatch-" + color} x="0" y="0" width="12" height="12" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
          <line x1="0" y1="0" x2="0" y2="12" stroke="rgba(10, 9, 8, 0.05)" strokeWidth="1" />
        </pattern>
      </defs>
      <rect width="200" height="200" fill={"url(#hatch-" + color + ")"} />
      {color.startsWith("case") ? (
        <rect x="60" y="30" width="80" height="140" rx="20" fill={fg} stroke="rgba(0,0,0,0.1)" strokeWidth="1" />
      ) : color === "hydrogel" || color === "glass" ? (
        <g>
          <rect x="60" y="30" width="80" height="140" rx="14" fill="rgba(255,255,255,0.7)" stroke={fg} strokeWidth="2" />
          <path d="M70 40 L130 40 L130 160 L70 160 Z" fill="rgba(255,255,255,0.4)" />
          <line x1="60" y1="55" x2="140" y2="55" stroke={fg} strokeWidth="1" strokeDasharray="2 4" opacity="0.5" />
        </g>
      ) : color === "charger" || color === "cable" ? (
        <g>
          <rect x="70" y="40" width="60" height="60" rx="8" fill={fg} />
          <path d="M100 100 Q90 130 110 140 Q130 150 100 170" stroke={fg} strokeWidth="6" fill="none" strokeLinecap="round" />
        </g>
      ) : color === "audio" ? (
        <g>
          <circle cx="80" cy="80" r="20" fill={fg} />
          <circle cx="120" cy="80" r="20" fill={fg} />
          <path d="M75 90 Q100 140 125 90" stroke={fg} strokeWidth="3" fill="none" />
        </g>
      ) : (
        <circle cx="100" cy="100" r="40" fill={fg} />
      )}
      <text x="100" y="195" textAnchor="middle" fontSize="8" fontFamily="monospace" fill="rgba(10, 9, 8, 0.4)" letterSpacing="1">
        {name.toUpperCase()}
      </text>
    </svg>
  );
};

const ShopPage = ({ navigate, addToCart }) => {
  const products = window.RN_DATA.products;
  const cats = ["Tous", ...new Set(products.map(p => p.cat))];
  const [cat, setCat] = React.useState("Tous");
  const [sort, setSort] = React.useState("popular");

  let filtered = cat === "Tous" ? products : products.filter(p => p.cat === cat);
  if (sort === "asc") filtered = [...filtered].sort((a, b) => a.price - b.price);
  if (sort === "desc") filtered = [...filtered].sort((a, b) => b.price - a.price);

  return (
    <div className="paper">
      <div className="page-hero">
        <span className="kanji">物</span>
        <div className="container">
          <span className="kicker" style={{ color: "var(--crimson)" }}>BOUTIQUE · ACCESSOIRES</span>
          <h1>L'arsenal du<br/><em style={{ fontStyle: "italic", color: "var(--crimson)" }}>quotidien.</em></h1>
          <p>Protections, coques, chargeurs, audio. Sélection serrée, posée sur place gratuitement à l'achat en boutique.</p>
        </div>
      </div>
      <section className="section section--cream">
        <div className="container">
          <div className="shop-toolbar">
            <div className="shop-filters">
              {cats.map((c) => (
                <button key={c} className={"shop-filter" + (cat === c ? " active" : "")} onClick={() => setCat(c)}>
                  {c}
                </button>
              ))}
            </div>
            <label className="shop-sort">
              <span>Trier</span>
              <select value={sort} onChange={(e) => setSort(e.target.value)}>
                <option value="popular">Populaires</option>
                <option value="asc">Prix croissant</option>
                <option value="desc">Prix décroissant</option>
              </select>
            </label>
          </div>

          <div className="product-grid">
            {filtered.map((p, i) => (
              <div className="product" key={p.id} style={{ animationDelay: `${i * 0.04}s` }}>
                <div className="product-img">
                  <ProductImage color={p.color} name={p.name} />
                  {p.badge && (
                    <span className={"product-badge " + (p.badge === "BEST" ? "product-badge--hot" : p.badge === "NEW" ? "product-badge--new" : "")}>
                      {p.badge}
                    </span>
                  )}
                  <button className="product-fav" title="Favoris"><IconHeart size={16} /></button>
                </div>
                <div className="product-info">
                  <span className="product-cat">{p.cat}</span>
                  <div className="product-name">{p.name}</div>
                  <div className="product-bottom">
                    <div>
                      <div className="product-price">
                        <span className="currency">€</span>{p.price.toFixed(2)}
                      </div>
                      <div className="product-points">
                        <Shuriken size={10} /> +{Math.round(p.price)} pts
                      </div>
                    </div>
                    <button className="product-add" onClick={() => addToCart(p)}>
                      <IconCart size={14} />
                    </button>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </section>
    </div>
  );
};

// ============================================
// SUPABASE HELPERS
// ============================================
const STATUS_LABELS = {
  pending:     "En attente",
  diagnostic:  "Diagnostic",
  in_progress: "En cours de réparation",
  ready:       "Prête à récupérer",
  completed:   "Terminée",
  delivered:   "Livrée",
  refunded:    "Remboursée",
};

const STATUS_COLOR = {
  pending:     "var(--muted-2)",
  diagnostic:  "var(--gold)",
  in_progress: "var(--crimson)",
  ready:       "#22c55e",
  completed:   "var(--muted-2)",
  delivered:   "var(--muted-2)",
  refunded:    "var(--muted-2)",
};

const TYPE_LABEL = {
  repair:          "Réparation",
  sale:            "Achat",
  repair_and_sale: "Réparation + Achat",
};

const fmtDate = (d) => {
  if (!d) return "—";
  return new Date(d).toLocaleDateString("fr-FR", { day: "numeric", month: "short", year: "numeric" });
};
const fmtPrice = (p) => (typeof p === "number" ? p.toFixed(2) + "\u202f€" : "—");
const parseItems = (json) => { try { return JSON.parse(json || "[]"); } catch { return []; } };

const sbErrMsg = (err) => {
  const m = err?.message || "";
  if (m.includes("Invalid login credentials")) return "Email ou mot de passe incorrect.";
  if (m.includes("Email not confirmed"))       return "Confirmez votre email avant de vous connecter.";
  if (m.includes("User already registered"))   return "Un compte existe déjà avec cet email.";
  if (m.includes("Password should be"))        return "Mot de passe trop court (minimum 6 caractères).";
  return m || "Erreur inattendue.";
};

// ============================================
// TRACKING
// ============================================
const TrackingPage = ({ navigate }) => {
  const [ref, setRef] = React.useState("");
  const [order, setOrder] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const [notFound, setNotFound] = React.useState(false);

  const findRepair = async () => {
    if (!ref.trim()) return;
    setLoading(true); setNotFound(false); setOrder(null);
    try {
      const data = await apiFetch("/repair/" + encodeURIComponent(ref.trim()));
      setOrder(data);
    } catch {
      setNotFound(true);
    } finally {
      setLoading(false);
    }
  };

  const stages = [
    { name: "Reçu" },
    { name: "Diagnostiqué" },
    { name: "En réparation" },
    { name: "Test qualité" },
    { name: "Prêt à récupérer" },
  ];

  return (
    <div className="paper">
      <div className="page-hero">
        <span className="kanji">追跡</span>
        <div className="container">
          <span className="kicker" style={{ color: "var(--crimson)" }}>SUIVI DE RÉPARATION</span>
          <h1>Étape par étape.<br/><em style={{ fontStyle: "italic", color: "var(--crimson)" }}>En temps réel.</em></h1>
          <p>Saisissez votre numéro de référence (reçu lors du dépôt) pour suivre l'avancement minute par minute.</p>
        </div>
      </div>

      <section className="section section--dark" style={{ paddingTop: 60 }}>
        <div className="container">
          <div style={{ maxWidth: 720, margin: "0 auto", background: "var(--ink-2)", border: "1px solid var(--ink-line)", borderRadius: "var(--r-md)", padding: 32, display: "flex", gap: 12 }}>
            <input
              type="text"
              placeholder="N° de référence (ex: RN-2026-04829)"
              value={ref}
              onChange={(e) => setRef(e.target.value)}
              style={{
                flex: 1, background: "var(--ink-3)", border: "1px solid var(--ink-line)",
                padding: "16px 20px", borderRadius: 4, color: "var(--cream)", fontSize: 15,
              }}
              onKeyDown={(e) => e.key === "Enter" && findRepair()}
            />
            <button className="btn btn--primary" onClick={findRepair} disabled={loading}>
              <span>{loading ? "Recherche..." : "Suivre"}</span>
              {!loading && <IconArrowRight />}
            </button>
          </div>

          {notFound && (
            <div style={{ maxWidth: 720, margin: "24px auto 0", textAlign: "center", color: "var(--crimson)", fontSize: 14, fontFamily: "var(--font-mono)" }}>
              Référence introuvable. Vérifiez le numéro sur votre reçu.
            </div>
          )}

          {order && (
            <div className="tracking-card ink-rise">
              <div className="tracking-meta">
                <div className="item">
                  <div className="l">Référence</div>
                  <div className="v mono" style={{ fontFamily: "var(--font-mono)", fontSize: 18 }}>{order.ref}</div>
                </div>
                <div className="item">
                  <div className="l">Appareil</div>
                  <div className="v">{order.device}</div>
                </div>
                <div className="item">
                  <div className="l">Intervention</div>
                  <div className="v">{order.issue}</div>
                </div>
                <div className="item">
                  <div className="l">Montant</div>
                  <div className="v"><em>€</em>{order.price}</div>
                </div>
              </div>

              <div className="tracking-stages">
                <div className="tracking-line">
                  <div className="tracking-line-fill" style={{ transform: `scaleX(${order.stage / (stages.length - 1)})` }} />
                </div>
                {stages.map((s, i) => (
                  <div key={i} className={"tracking-stage " + (i < order.stage ? "done" : i === order.stage ? "active" : "pending")}>
                    <div className="dot">
                      {i < order.stage ? <IconCheck size={20} /> : i === order.stage ? <Shuriken size={20} className="shuriken-rotate" /> : i + 1}
                    </div>
                    <div className="name">{s.name}</div>
                    <div className="time">{i <= order.stage ? order.createdAt : "—"}</div>
                  </div>
                ))}
              </div>

              <div className="tracking-log">
                {(order.log && order.log.length > 0) ? order.log.map((entry, i) => (
                  <div key={i} className="entry"><span className="ts">{entry.time}</span><span className="msg">▸ {entry.msg}</span></div>
                )) : (
                  <div className="entry"><span className="ts">—</span><span className="msg">▸ Appareil reçu en boutique · technicien {order.tech}</span></div>
                )}
              </div>

              {order.stage === 4 && (
                <div style={{ marginTop: 24, padding: 16, background: "rgba(200, 16, 46, 0.08)", border: "1px solid rgba(200, 16, 46, 0.2)", borderRadius: 8, color: "var(--cream)", fontSize: 13, display: "flex", alignItems: "center", gap: 12 }}>
                  <Shuriken size={20} style={{ color: "var(--crimson)", flexShrink: 0 }} />
                  <div><strong>Votre appareil est prêt !</strong> <span style={{ color: "var(--muted-2)" }}>Venez le récupérer en boutique.</span></div>
                </div>
              )}
            </div>
          )}

          {!order && !notFound && (
            <div style={{ maxWidth: 720, margin: "32px auto 0", textAlign: "center", color: "var(--muted-2)", fontSize: 14, fontFamily: "var(--font-mono)", letterSpacing: 0.05 }}>
              Entrez votre numéro de référence pour suivre votre réparation.
            </div>
          )}
        </div>
      </section>
    </div>
  );
};

// ============================================
// INVOICE VIEWER
// ============================================
const InvoicePrintView = ({ inv, order, customer }) => {
  const info  = window.RN_INFO;
  const items = parseItems(order?.items_json);

  return (
    <div id="rn-invoice-print" style={{ fontFamily: "var(--font-body)", color: "#111", background: "#fff", padding: "48px 56px", maxWidth: 760, margin: "0 auto", lineHeight: 1.5 }}>
      {/* ── Header ── */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 40, paddingBottom: 24, borderBottom: "2px solid #111" }}>
        <div>
          <div style={{ fontFamily: "serif", fontSize: 28, fontWeight: 700, letterSpacing: -0.5 }}>Repair Ninja</div>
          <div style={{ fontFamily: "serif", fontSize: 13, color: "#666", marginTop: 2 }}>修理忍者</div>
          <div style={{ marginTop: 10, fontSize: 13, color: "#444", lineHeight: 1.7 }}>
            {info.address}<br/>{info.city}<br/>{info.phone}<br/>{info.email}
          </div>
        </div>
        <div style={{ textAlign: "right" }}>
          <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: 2, color: "#888", marginBottom: 6 }}>Facture</div>
          <div style={{ fontSize: 28, fontWeight: 700, fontFamily: "monospace" }}>{inv.number}</div>
          <div style={{ marginTop: 8, fontSize: 13, color: "#666" }}>
            Émise le {fmtDate(inv.issued_at)}<br/>
            {order?.delivery_date && <>Livraison : {fmtDate(order.delivery_date)}</>}
          </div>
        </div>
      </div>

      {/* ── Client ── */}
      <div style={{ marginBottom: 36 }}>
        <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: 2, color: "#888", marginBottom: 8 }}>Facturer à</div>
        <div style={{ fontSize: 15, fontWeight: 600 }}>{customer?.name || "—"}</div>
        <div style={{ fontSize: 13, color: "#555" }}>{customer?.email || "—"}</div>
        {customer?.phone && <div style={{ fontSize: 13, color: "#555" }}>{customer.phone}</div>}
        {customer?.address && <div style={{ fontSize: 13, color: "#555" }}>{customer.address}</div>}
      </div>

      {/* ── Commande ── */}
      {order && (
        <div style={{ marginBottom: 8, fontSize: 12, color: "#888", fontFamily: "monospace" }}>
          Réf. commande : {order.order_number} · {TYPE_LABEL[order.type] || order.type}
        </div>
      )}

      {/* ── Lignes ── */}
      <table style={{ width: "100%", borderCollapse: "collapse", marginTop: 8, marginBottom: 24 }}>
        <thead>
          <tr style={{ background: "#111", color: "#fff" }}>
            <th style={{ padding: "10px 14px", textAlign: "left",  fontSize: 11, textTransform: "uppercase", letterSpacing: 1, fontWeight: 600 }}>Désignation</th>
            <th style={{ padding: "10px 14px", textAlign: "center", fontSize: 11, textTransform: "uppercase", letterSpacing: 1, fontWeight: 600, width: 60 }}>Qté</th>
            <th style={{ padding: "10px 14px", textAlign: "right",  fontSize: 11, textTransform: "uppercase", letterSpacing: 1, fontWeight: 600, width: 110 }}>P.U.</th>
            <th style={{ padding: "10px 14px", textAlign: "right",  fontSize: 11, textTransform: "uppercase", letterSpacing: 1, fontWeight: 600, width: 110 }}>Total</th>
          </tr>
        </thead>
        <tbody>
          {items.length > 0 ? items.map((it, i) => (
            <tr key={i} style={{ borderBottom: "1px solid #e5e5e5", background: i % 2 === 0 ? "#fafafa" : "#fff" }}>
              <td style={{ padding: "12px 14px", fontSize: 14 }}>
                <div style={{ fontWeight: 500 }}>{it.product_name || it.description || "Article"}</div>
                {it.description && it.product_name && <div style={{ fontSize: 12, color: "#777", marginTop: 2 }}>{it.description}</div>}
                {it.discount > 0 && <div style={{ fontSize: 11, color: "#c8102e" }}>Remise : -{fmtPrice(it.discount)}</div>}
              </td>
              <td style={{ padding: "12px 14px", textAlign: "center", fontSize: 14 }}>{it.quantity ?? 1}</td>
              <td style={{ padding: "12px 14px", textAlign: "right", fontSize: 14, fontFamily: "monospace" }}>{fmtPrice(it.unit_price)}</td>
              <td style={{ padding: "12px 14px", textAlign: "right", fontSize: 14, fontFamily: "monospace", fontWeight: 600 }}>{fmtPrice(it.total ?? it.unit_price * (it.quantity ?? 1))}</td>
            </tr>
          )) : (
            <tr>
              <td colSpan={4} style={{ padding: "16px 14px", color: "#999", fontSize: 13, textAlign: "center" }}>Aucun détail disponible</td>
            </tr>
          )}
        </tbody>
      </table>

      {/* ── Total ── */}
      <div style={{ display: "flex", justifyContent: "flex-end", marginBottom: 40 }}>
        <div style={{ width: 260 }}>
          <div style={{ display: "flex", justifyContent: "space-between", padding: "8px 0", borderTop: "1px solid #e5e5e5", fontSize: 13, color: "#555" }}>
            <span>Sous-total HT</span>
            <span style={{ fontFamily: "monospace" }}>{fmtPrice(order?.total)}</span>
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", padding: "8px 0", fontSize: 13, color: "#555" }}>
            <span>TVA (20 %)</span>
            <span style={{ fontFamily: "monospace" }}>{fmtPrice(order ? order.total * 0.2 / 1.2 : 0)}</span>
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", padding: "12px 14px", background: "#111", color: "#fff", borderRadius: 4, marginTop: 4, fontSize: 16, fontWeight: 700 }}>
            <span>Total TTC</span>
            <span style={{ fontFamily: "monospace" }}>{fmtPrice(order?.total)}</span>
          </div>
          {order?.paid ? (
            <div style={{ marginTop: 8, textAlign: "right", fontSize: 12, color: "#16a34a", fontWeight: 600 }}>✓ Payé · {order.payment_method || ""}</div>
          ) : (
            <div style={{ marginTop: 8, textAlign: "right", fontSize: 12, color: "#c8102e" }}>En attente de paiement</div>
          )}
        </div>
      </div>

      {/* ── Pied ── */}
      <div style={{ borderTop: "1px solid #e5e5e5", paddingTop: 20, fontSize: 11, color: "#999", lineHeight: 1.7 }}>
        <strong style={{ color: "#111" }}>Repair Ninja</strong> · SIRET {info.siret} · TVA {info.tva}<br/>
        Garantie 6 mois pièces & main-d'œuvre · Tout litige : {info.email}
      </div>
    </div>
  );
};

const InvoiceModal = ({ inv, order, customer, onClose }) => {
  const printInvoice = () => {
    const el = document.getElementById("rn-invoice-print");
    if (!el) return;
    const w = window.open("", "_blank");
    w.document.write(`<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Facture ${inv.number}</title>
      <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: #111; background: #fff; }
        @media print { @page { margin: 1.5cm; } }
      </style>
    </head><body>${el.innerHTML}</body></html>`);
    w.document.close();
    w.focus();
    setTimeout(() => { w.print(); }, 400);
  };

  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 1000, display: "flex", alignItems: "flex-start", justifyContent: "center", overflowY: "auto", padding: "40px 16px" }}>
      <div onClick={onClose} style={{ position: "fixed", inset: 0, background: "rgba(10,9,8,0.7)", backdropFilter: "blur(2px)" }} />
      <div style={{ position: "relative", width: "100%", maxWidth: 820, background: "#fff", borderRadius: 12, overflow: "hidden", boxShadow: "0 24px 80px rgba(0,0,0,0.35)" }}>
        {/* toolbar */}
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "16px 24px", background: "var(--ink)", borderBottom: "1px solid var(--ink-line)" }}>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 14, color: "var(--cream)" }}>{inv.number}</span>
          <div style={{ display: "flex", gap: 8 }}>
            <button onClick={printInvoice} className="btn btn--primary btn--small">
              <span>Imprimer / PDF</span><IconArrowRight />
            </button>
            <button onClick={onClose} className="btn btn--ghost btn--small" style={{ color: "var(--cream)" }}>✕</button>
          </div>
        </div>
        {/* invoice content */}
        <div style={{ overflowY: "auto", maxHeight: "80vh" }}>
          <InvoicePrintView inv={inv} order={order} customer={customer} />
        </div>
      </div>
    </div>
  );
};

const InvoicesTab = ({ invoices, allOrders, customer, dataLoading, Spinner }) => {
  const [openInv, setOpenInv] = React.useState(null);
  const openOrder = openInv ? allOrders.find(o => o.id === openInv.order_id) : null;

  return (
    <div>
      <h3 style={{ marginBottom: 24, fontSize: 28 }}>Factures</h3>
      {dataLoading ? <Spinner /> : invoices.length === 0 ? (
        <div className="empty-state">
          <IconReceipt size={48} style={{ margin: "0 auto 16px", color: "var(--cream-3)" }} />
          <h4>Aucune facture</h4>
          <p>Vos factures générées en boutique apparaîtront ici.</p>
        </div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {invoices.map(inv => {
            const order = allOrders.find(o => o.id === inv.order_id);
            return (
              <div key={inv.id} style={{ padding: "16px 20px", background: "var(--cream)", border: "1px solid rgba(10,9,8,0.1)", borderRadius: 10, display: "flex", justifyContent: "space-between", alignItems: "center", gap: 16, flexWrap: "wrap" }}>
                <div>
                  <div style={{ fontFamily: "var(--font-mono)", fontSize: 15 }}>{inv.number}</div>
                  <div style={{ fontSize: 12, color: "var(--muted)", marginTop: 3 }}>{fmtDate(inv.issued_at)}</div>
                </div>
                <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
                  {order && <span style={{ fontFamily: "var(--font-display)", fontSize: 20 }}>{fmtPrice(order.total)}</span>}
                  <button onClick={() => setOpenInv(inv)} className="btn btn--primary btn--small">
                    <span>Voir la facture</span><IconArrowRight />
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      )}
      {openInv && <InvoiceModal inv={openInv} order={openOrder} customer={customer} onClose={() => setOpenInv(null)} />}
    </div>
  );
};

// ============================================
// CHAT PANEL
// ============================================
const ChatPanel = ({ requestId, authUid }) => {
  const db = window.SUPABASE;
  const [messages, setMessages] = React.useState([]);
  const [input, setInput]       = React.useState("");
  const [sending, setSending]   = React.useState(false);
  const [sendError, setSendError] = React.useState("");
  const bottomRef               = React.useRef(null);

  React.useEffect(() => {
    if (!requestId || !db) return;

    // Load existing messages
    db.from("request_messages")
      .select("*")
      .eq("request_id", requestId)
      .order("created_at", { ascending: true })
      .then(({ data }) => {
        const msgs = data || [];
        setMessages(msgs);
        // Mark unread POS messages as read
        const unread = msgs.filter(m => m.sender === "pos" && !m.read_at);
        if (unread.length > 0) {
          db.from("request_messages")
            .update({ read_at: new Date().toISOString() })
            .in("id", unread.map(m => m.id))
            .then(() => {});
        }
      });

    // Subscribe to real-time new messages
    const channel = db
      .channel("chat-req-" + requestId)
      .on("postgres_changes", {
        event: "INSERT",
        schema: "public",
        table: "request_messages",
        filter: "request_id=eq." + requestId,
      }, (payload) => {
        setMessages(prev => [...prev, payload.new]);
        if (payload.new.sender === "pos") {
          db.from("request_messages")
            .update({ read_at: new Date().toISOString() })
            .eq("id", payload.new.id)
            .then(() => {});
        }
      })
      .subscribe();

    return () => { db.removeChannel(channel); };
  }, [requestId]);

  // Auto-scroll to bottom
  React.useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  const sendMessage = async (e) => {
    e.preventDefault();
    const text = input.trim();
    if (!text || sending) return;
    setSending(true);
    setSendError("");
    try {
      const { error } = await db.from("request_messages").insert({
        request_id: requestId,
        sender:     "client",
        auth_uid:   authUid,
        message:    text,
      });
      if (error) {
        console.error("[RN] send message:", error);
        setSendError("Erreur d'envoi. Vérifiez votre connexion ou réessayez.");
      } else {
        setInput("");
      }
    } catch (err) {
      console.error("[RN] send message:", err);
      setSendError("Erreur d'envoi. Réessayez.");
    } finally {
      setSending(false);
    }
  };

  return (
    <div style={{ marginTop: 12, border: "1px solid rgba(59,130,246,0.2)", borderRadius: 8, overflow: "hidden" }}>
      {/* header */}
      <div style={{ padding: "8px 12px", background: "rgba(59,130,246,0.06)", borderBottom: "1px solid rgba(59,130,246,0.1)", display: "flex", alignItems: "center", gap: 6 }}>
        <span style={{ width: 7, height: 7, borderRadius: "50%", background: "#22c55e", display: "inline-block" }} />
        <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "#3b82f6", textTransform: "uppercase", letterSpacing: 0.1 }}>Chat · Repair Ninja</span>
      </div>
      {/* messages */}
      <div style={{ maxHeight: 240, overflowY: "auto", padding: 12, display: "flex", flexDirection: "column", gap: 8, background: "var(--cream)" }}>
        {messages.length === 0 && (
          <div style={{ textAlign: "center", color: "var(--muted)", fontSize: 12, padding: 16 }}>
            Envoyez un message à l'équipe Repair Ninja.
          </div>
        )}
        {messages.map(msg => (
          <div key={msg.id} style={{ display: "flex", flexDirection: "column", alignItems: msg.sender === "client" ? "flex-end" : "flex-start" }}>
            <div style={{
              maxWidth: "80%", padding: "8px 12px",
              borderRadius: msg.sender === "client" ? "12px 12px 2px 12px" : "12px 12px 12px 2px",
              background: msg.sender === "client" ? "var(--crimson)" : "var(--ink-3)",
              color: "#fff", fontSize: 13, lineHeight: 1.5,
            }}>
              {msg.message}
            </div>
            <span style={{ fontSize: 10, color: "var(--muted)", marginTop: 3 }}>
              {msg.sender === "pos" ? "Repair Ninja · " : ""}{new Date(msg.created_at).toLocaleTimeString("fr-FR", { hour: "2-digit", minute: "2-digit" })}
            </span>
          </div>
        ))}
        <div ref={bottomRef} />
      </div>
      {/* input */}
      <div style={{ borderTop: "1px solid rgba(59,130,246,0.1)", background: "var(--cream-2)" }}>
        {sendError && (
          <div style={{ padding: "6px 10px", fontSize: 11, color: "var(--crimson)", background: "rgba(200,16,46,0.06)" }}>
            {sendError}
          </div>
        )}
        <form onSubmit={sendMessage} style={{ display: "flex", gap: 8, padding: 10 }}>
          <input
            type="text" value={input} onChange={e => { setInput(e.target.value); if (sendError) setSendError(""); }}
            placeholder="Votre message…"
            style={{ flex: 1, background: "var(--cream)", border: "1px solid rgba(10,9,8,0.15)", padding: "8px 12px", borderRadius: 6, color: "var(--ink)", fontSize: 13 }}
          />
          <button type="submit" className="btn btn--primary btn--small"
            disabled={!input.trim() || sending}
            style={{ opacity: (!input.trim() || sending) ? 0.5 : 1 }}>
            <span>{sending ? "…" : "Envoyer"}</span>
          </button>
        </form>
      </div>
    </div>
  );
};

// ============================================
// ACCOUNT
// ============================================
const AccountPage = ({ navigate, account, setAccount }) => {
  const db = window.SUPABASE;

  const [tab, setTab]                   = React.useState("overview");
  const [loggedIn, setLoggedIn]         = React.useState(false);
  const [showSignup, setShowSignup]     = React.useState(false);
  const [form, setForm]                 = React.useState({ email: "", password: "", name: "" });
  const [error, setError]               = React.useState("");
  const [loading, setLoading]           = React.useState(false);
  const [initDone, setInitDone]         = React.useState(false);

  // Customer record from Supabase
  const [customer, setCustomer]         = React.useState(null);
  // Data
  const [activeRepairs, setActiveRepairs]   = React.useState([]);
  const [allOrders, setAllOrders]           = React.useState([]);
  const [invoices, setInvoices]             = React.useState([]);
  const [loyaltyLog, setLoyaltyLog]         = React.useState([]);
  const [clientRequests, setClientRequests] = React.useState([]);
  const [dataLoading, setDataLoading]       = React.useState(false);
  const [authUid, setAuthUid]               = React.useState(null);
  const [openChatReqId, setOpenChatReqId]   = React.useState(null);
  const [otpPending, setOtpPending]         = React.useState(null);
  const [otpCode, setOtpCode]               = React.useState("");
  const [resetStep, setResetStep]           = React.useState(null); // null | 'email' | 'otp' | 'newpassword'
  const [resetEmail, setResetEmail]         = React.useState("");
  const [resetOtp, setResetOtp]             = React.useState("");
  const [resetPwd, setResetPwd]             = React.useState("");
  const [resendCooldown, setResendCooldown] = React.useState(0);

  // ── helpers ──────────────────────────────
  const resolveCustomer = async (session) => {
    const email = session.user.email;

    // 1. Cherche dans portal_users si déjà lié
    const { data: pu } = await db
      .from("portal_users")
      .select("customer_id, name")
      .eq("auth_uid", session.user.id)
      .maybeSingle();

    // customer_id résolu : soit via portal_users, soit via email direct
    let customerId = pu?.customer_id ?? null;

    if (!customerId) {
      // 2. Recherche dans customers par email (pour la liaison auto)
      const { data: cust, error: custErr } = await db
        .from("customers")
        .select("id, name, email, phone, shuriken_points")
        .eq("email", email)
        .maybeSingle();

      if (!custErr && cust) {
        customerId = cust.id;
        // Met à jour portal_users avec le lien trouvé (silencieux si table pas encore créée)
        db.from("portal_users")
          .upsert({ auth_uid: session.user.id, email, customer_id: cust.id, name: cust.name || session.user.user_metadata?.name }, { onConflict: "auth_uid" })
          .then(({ error }) => { if (error && error.code !== "42P01") console.warn("[RN] portal_users upsert:", error.message); });
        setCustomer(cust);
        await loadData(cust.id);
        return;
      }
    }

    if (customerId) {
      // 3. Charge la fiche customer complète
      const { data: cust } = await db
        .from("customers")
        .select("id, name, email, phone, shuriken_points")
        .eq("id", customerId)
        .maybeSingle();
      if (cust) { setCustomer(cust); await loadData(cust.id); return; }
    }

    // 4. Pas de correspondance POS — profil portail vide
    const fallbackName = pu?.name || session.user.user_metadata?.name || email.split("@")[0];
    setCustomer({ name: fallbackName, email, shuriken_points: 0, id: null });
  };

  const loadData = async (customerId) => {
    if (!customerId) return;
    setDataLoading(true);

    // Active repairs = réparations pas encore terminées
    const ACTIVE_STATUSES = ["pending", "diagnostic", "in_progress", "ready"];

    const { data: { session: sess } } = await db.auth.getSession();
    const authUid = sess?.user?.id;

    const [repRes, ordRes, invRes, loyRes, reqRes] = await Promise.all([
      db.from("orders")
        .select("*")
        .eq("customer_id", customerId)
        .in("type", ["repair", "repair_and_sale"])
        .in("status", ACTIVE_STATUSES)
        .order("created_at", { ascending: false }),
      db.from("orders")
        .select("*")
        .eq("customer_id", customerId)
        .order("created_at", { ascending: false }),
      db.from("invoices")
        .select("*")
        .eq("customer_id", customerId)
        .order("issued_at", { ascending: false }),
      db.from("loyalty_points")
        .select("*")
        .eq("customer_id", customerId)
        .order("created_at", { ascending: false }),
      authUid
        ? db.from("client_requests").select("*").eq("auth_uid", authUid).order("created_at", { ascending: false })
        : Promise.resolve({ data: [], error: null }),
    ]);

    if (repRes.error) console.error("[RN] repairs query:", repRes.error);
    if (ordRes.error) console.error("[RN] orders query:", ordRes.error);
    if (invRes.error) console.error("[RN] invoices query:", invRes.error);
    if (loyRes.error) console.error("[RN] loyalty query:", loyRes.error);
    if (reqRes.error) console.error("[RN] requests query:", reqRes.error);

    setActiveRepairs(repRes.data || []);
    setAllOrders(ordRes.data || []);
    setInvoices(invRes.data || []);
    setLoyaltyLog(loyRes.data || []);
    setClientRequests(reqRes.data || []);

    setDataLoading(false);
  };

  // ── auth init ────────────────────────────
  React.useEffect(() => {
    if (!db) { setInitDone(true); return; }

    db.auth.getSession().then(async ({ data: { session } }) => {
      if (session) {
        setLoggedIn(true);
        setAuthUid(session.user.id);
        const name = session.user.user_metadata?.name || session.user.email.split("@")[0];
        setAccount({ name, email: session.user.email });
        await resolveCustomer(session);
      }
      setInitDone(true);
    });

    const { data: { subscription } } = db.auth.onAuthStateChange(async (event, session) => {
      if (event === "SIGNED_OUT") {
        setLoggedIn(false);
        setCustomer(null);
        setActiveRepairs([]); setAllOrders([]); setInvoices([]); setLoyaltyLog([]);
        setAccount(null);
      }
    });
    return () => subscription.unsubscribe();
  }, []);

  React.useEffect(() => {
    if (resendCooldown <= 0) return;
    const t = setTimeout(() => setResendCooldown(c => c - 1), 1000);
    return () => clearTimeout(t);
  }, [resendCooldown]);

  // ── auth actions ─────────────────────────
  const submit = async (e) => {
    e?.preventDefault?.();
    setError(""); setLoading(true);
    try {
      if (showSignup) {
        const { data, error } = await db.auth.signUp({
          email: form.email,
          password: form.password,
          options: { data: { name: form.name } },
        });
        if (error) throw error;
        if (data.session) {
          setLoggedIn(true);
          setAuthUid(data.session.user.id);
          const name = form.name || form.email.split("@")[0];
          setAccount({ name, email: form.email });
          await resolveCustomer(data.session);
        } else {
          setOtpPending(form.email);
          setOtpCode("");
        }
      } else {
        const { data, error } = await db.auth.signInWithPassword({
          email: form.email,
          password: form.password,
        });
        if (error) throw error;
        setLoggedIn(true);
        setAuthUid(data.session.user.id);
        const name = data.session.user.user_metadata?.name || form.email.split("@")[0];
        setAccount({ name, email: form.email });
        await resolveCustomer(data.session);
      }
    } catch (err) {
      setError(sbErrMsg(err));
    } finally {
      setLoading(false);
    }
  };

  const submitOtp = async (e) => {
    e?.preventDefault?.();
    if (otpCode.length < 6) return;
    setError(""); setLoading(true);
    try {
      const { data, error } = await db.auth.verifyOtp({
        email: otpPending,
        token: otpCode,
        type:  "signup",
      });
      if (error) throw error;
      if (data.session) {
        setLoggedIn(true);
        setAuthUid(data.session.user.id);
        setOtpPending(null);
        const name = data.session.user.user_metadata?.name || otpPending.split("@")[0];
        setAccount({ name, email: otpPending });
        await resolveCustomer(data.session);
      }
    } catch (err) {
      setError(sbErrMsg(err));
    } finally {
      setLoading(false);
    }
  };

  const resendOtp = async () => {
    setError(""); setLoading(true);
    try {
      const { error } = await db.auth.resend({ type: "signup", email: otpPending });
      if (error) throw error;
      setResendCooldown(60);
      setError("✓ Code renvoyé. Vérifiez votre boîte mail.");
    } catch (err) {
      setError(sbErrMsg(err));
    } finally {
      setLoading(false);
    }
  };

  const sendReset = async (e) => {
    e?.preventDefault?.();
    if (!resetEmail.trim()) return;
    setError(""); setLoading(true);
    try {
      const { error } = await db.auth.resetPasswordForEmail(resetEmail);
      if (error) throw error;
      setResetStep("otp"); setResetOtp(""); setResendCooldown(60);
    } catch (err) { setError(sbErrMsg(err)); }
    finally { setLoading(false); }
  };

  const verifyReset = async (e) => {
    e?.preventDefault?.();
    if (resetOtp.length < 6) return;
    setError(""); setLoading(true);
    try {
      const { data, error } = await db.auth.verifyOtp({ email: resetEmail, token: resetOtp, type: "recovery" });
      if (error) throw error;
      if (data.session) setResetStep("newpassword");
    } catch (err) { setError(sbErrMsg(err)); }
    finally { setLoading(false); }
  };

  const updatePwd = async (e) => {
    e?.preventDefault?.();
    if (resetPwd.length < 6) return;
    setError(""); setLoading(true);
    try {
      const { error } = await db.auth.updateUser({ password: resetPwd });
      if (error) throw error;
      const { data: { session } } = await db.auth.getSession();
      if (session) {
        setLoggedIn(true); setAuthUid(session.user.id);
        setAccount({ name: session.user.user_metadata?.name || session.user.email.split("@")[0], email: session.user.email });
        await resolveCustomer(session);
      }
      setResetStep(null); setResetEmail(""); setResetOtp(""); setResetPwd("");
    } catch (err) { setError(sbErrMsg(err)); }
    finally { setLoading(false); }
  };

  const logout = async () => {
    await db.auth.signOut();
  };

  // ── loading state ────────────────────────
  if (!initDone) {
    return (
      <div className="paper" style={{ minHeight: "60vh", display: "flex", alignItems: "center", justifyContent: "center" }}>
        <Shuriken size={40} className="shuriken-rotate" style={{ color: "var(--crimson)" }} />
      </div>
    );
  }

  // ── LOGIN SCREEN ─────────────────────────
  if (!loggedIn) {

    if (resetStep) {
      const heroTitles = { email: "Mot de passe\noublié.", otp: "Vérification.", newpassword: "Nouveau\nmot de passe." };
      const heroSubs   = { email: "Entrez votre email pour recevoir un code de réinitialisation.", otp: `Code envoyé à ${resetEmail}`, newpassword: "Choisissez un nouveau mot de passe." };
      const resetBack  = () => { setResetStep(null); setResetEmail(""); setResetOtp(""); setResetPwd(""); setError(""); };
      const ErrBox = () => error ? <div style={{ color: error.startsWith("✓") ? "#16a34a" : "var(--crimson)", fontSize: 13, margin: "8px 0", padding: "8px 12px", background: error.startsWith("✓") ? "rgba(22,163,74,0.08)" : "rgba(200,16,46,0.08)", borderRadius: 4 }}>{error}</div> : null;
      return (
        <div className="paper">
          <div className="page-hero">
            <span className="kanji">道場</span>
            <div className="container">
              <span className="kicker" style={{ color: "var(--crimson)" }}>ESPACE CLIENT · DOJO</span>
              <h1 style={{ whiteSpace: "pre-line" }}>{heroTitles[resetStep]}</h1>
              <p>{heroSubs[resetStep]}</p>
            </div>
          </div>
          <section className="section section--cream">
            <div className="container" style={{ maxWidth: 480 }}>
              <div style={{ background: "var(--cream)", border: "1px solid rgba(10,9,8,0.1)", borderRadius: "var(--r-md)", padding: 40 }}>

                {resetStep === "email" && (
                  <form onSubmit={sendReset}>
                    <div className="field" style={{ color: "var(--ink)" }}>
                      <label style={{ color: "var(--muted)" }}>Email</label>
                      <input autoFocus type="email" required value={resetEmail} onChange={e => { setResetEmail(e.target.value); setError(""); }} style={{ borderColor: "rgba(10,9,8,0.2)", color: "var(--ink)" }} />
                    </div>
                    <ErrBox />
                    <button className="btn btn--primary" type="submit" disabled={loading} style={{ width: "100%", justifyContent: "center", marginTop: 16, opacity: loading ? 0.6 : 1 }}>
                      <span>{loading ? "Envoi…" : "Envoyer le code"}</span>{!loading && <IconArrowRight />}
                    </button>
                  </form>
                )}

                {resetStep === "otp" && (
                  <form onSubmit={verifyReset}>
                    <div className="field" style={{ color: "var(--ink)" }}>
                      <label style={{ color: "var(--muted)" }}>Code de confirmation</label>
                      <input autoFocus type="text" inputMode="text" maxLength={8} placeholder="••••••••" value={resetOtp}
                        onChange={e => { setResetOtp(e.target.value.trim().slice(0, 8)); setError(""); }}
                        style={{ borderColor: "rgba(10,9,8,0.2)", color: "var(--ink)", fontSize: 28, letterSpacing: 10, textAlign: "center", fontFamily: "var(--font-mono)", padding: "16px" }} />
                    </div>
                    <ErrBox />
                    <button className="btn btn--primary" type="submit" disabled={resetOtp.length < 6 || loading} style={{ width: "100%", justifyContent: "center", marginTop: 16, opacity: (resetOtp.length < 6 || loading) ? 0.5 : 1 }}>
                      <span>{loading ? "Vérification…" : "Vérifier"}</span>{!loading && <IconArrowRight />}
                    </button>
                    <div style={{ marginTop: 12, textAlign: "right" }}>
                      <button type="button" onClick={sendReset} disabled={loading || resendCooldown > 0}
                      style={{ background: "none", border: "none", color: resendCooldown > 0 ? "var(--muted)" : "var(--crimson)", fontSize: 13, cursor: resendCooldown > 0 ? "default" : "pointer" }}>
                      {resendCooldown > 0 ? `Renvoyer dans ${resendCooldown}s` : "Renvoyer le code"}
                    </button>
                    </div>
                  </form>
                )}

                {resetStep === "newpassword" && (
                  <form onSubmit={updatePwd}>
                    <div className="field" style={{ color: "var(--ink)" }}>
                      <label style={{ color: "var(--muted)" }}>Nouveau mot de passe</label>
                      <input autoFocus type="password" required minLength={6} value={resetPwd} onChange={e => { setResetPwd(e.target.value); setError(""); }} style={{ borderColor: "rgba(10,9,8,0.2)", color: "var(--ink)" }} />
                    </div>
                    <ErrBox />
                    <button className="btn btn--primary" type="submit" disabled={resetPwd.length < 6 || loading} style={{ width: "100%", justifyContent: "center", marginTop: 16, opacity: (resetPwd.length < 6 || loading) ? 0.5 : 1 }}>
                      <span>{loading ? "Mise à jour…" : "Mettre à jour le mot de passe"}</span>{!loading && <IconArrowRight />}
                    </button>
                  </form>
                )}

                <div style={{ marginTop: 20, textAlign: "center" }}>
                  <button onClick={resetBack} style={{ background: "none", border: "none", color: "var(--muted)", fontSize: 13, cursor: "pointer" }}>← Retour à la connexion</button>
                </div>
              </div>
            </div>
          </section>
        </div>
      );
    }

    if (otpPending) {
      return (
        <div className="paper">
          <div className="page-hero">
            <span className="kanji">道場</span>
            <div className="container">
              <span className="kicker" style={{ color: "var(--crimson)" }}>ESPACE CLIENT · DOJO</span>
              <h1>Vérification.</h1>
              <p>Entrez le code de confirmation reçu par email.</p>
            </div>
          </div>
          <section className="section section--cream">
            <div className="container" style={{ maxWidth: 480 }}>
              <div style={{ background: "var(--cream)", border: "1px solid rgba(10,9,8,0.1)", borderRadius: "var(--r-md)", padding: 40 }}>
                <div style={{ marginBottom: 20, fontSize: 13, color: "var(--muted)", lineHeight: 1.6 }}>
                  Code envoyé à <strong style={{ color: "var(--ink)" }}>{otpPending}</strong>
                </div>
                <form onSubmit={submitOtp}>
                  <div className="field" style={{ color: "var(--ink)" }}>
                    <label style={{ color: "var(--muted)" }}>Code de confirmation</label>
                    <input
                      type="text" inputMode="text" maxLength={8} autoFocus
                      placeholder="••••••••"
                      value={otpCode}
                      onChange={e => {
                        const v = e.target.value.trim().slice(0, 8);
                        setOtpCode(v);
                        setError("");
                      }}
                      style={{
                        borderColor: "rgba(10,9,8,0.2)", color: "var(--ink)",
                        fontSize: 28, letterSpacing: 10, textAlign: "center",
                        fontFamily: "var(--font-mono)", padding: "16px",
                        textTransform: "lowercase",
                      }}
                    />
                  </div>
                  {error && (
                    <div style={{ color: error.startsWith("✓") ? "#16a34a" : "var(--crimson)", fontSize: 13, marginTop: 8, padding: "8px 12px", background: error.startsWith("✓") ? "rgba(22,163,74,0.08)" : "rgba(200,16,46,0.08)", borderRadius: 4 }}>
                      {error}
                    </div>
                  )}
                  <button className="btn btn--primary" type="submit"
                    disabled={otpCode.length < 6 || loading}
                    style={{ width: "100%", justifyContent: "center", marginTop: 16, opacity: (otpCode.length < 6 || loading) ? 0.5 : 1 }}>
                    <span>{loading ? "Vérification…" : "Confirmer"}</span>
                    {!loading && <IconArrowRight />}
                  </button>
                </form>
                <div style={{ marginTop: 20, display: "flex", justifyContent: "space-between" }}>
                  <button onClick={() => { setOtpPending(null); setOtpCode(""); setError(""); }}
                    style={{ background: "none", border: "none", color: "var(--muted)", fontSize: 13, cursor: "pointer" }}>
                    ← Retour
                  </button>
                  <button onClick={resendOtp} disabled={loading || resendCooldown > 0}
                    style={{ background: "none", border: "none", color: resendCooldown > 0 ? "var(--muted)" : "var(--crimson)", fontSize: 13, cursor: resendCooldown > 0 ? "default" : "pointer" }}>
                    {resendCooldown > 0 ? `Renvoyer dans ${resendCooldown}s` : "Renvoyer le code"}
                  </button>
                </div>
              </div>
            </div>
          </section>
        </div>
      );
    }

    return (
      <div className="paper">
        <div className="page-hero">
          <span className="kanji">道場</span>
          <div className="container">
            <span className="kicker" style={{ color: "var(--crimson)" }}>ESPACE CLIENT · DOJO</span>
            <h1>Connexion.</h1>
            <p>Accédez à votre historique, vos Shuriken Points et vos réparations en cours.</p>
          </div>
        </div>
        <section className="section section--cream">
          <div className="container" style={{ maxWidth: 480 }}>
            <div style={{ background: "var(--cream)", border: "1px solid rgba(10,9,8,0.1)", borderRadius: "var(--r-md)", padding: 40 }}>
              <div style={{ display: "flex", gap: 4, marginBottom: 32, background: "var(--cream-2)", padding: 4, borderRadius: 100 }}>
                <button className={"shop-filter" + (!showSignup ? " active" : "")} onClick={() => { setShowSignup(false); setError(""); }} style={{ flex: 1, textAlign: "center" }}>Connexion</button>
                <button className={"shop-filter" + (showSignup ? " active" : "")} onClick={() => { setShowSignup(true); setError(""); }} style={{ flex: 1, textAlign: "center" }}>Créer un compte</button>
              </div>

              <form onSubmit={submit}>
                {showSignup && (
                  <div className="field" style={{ color: "var(--ink)" }}>
                    <label style={{ color: "var(--muted)" }}>Nom complet</label>
                    <input style={{ borderColor: "rgba(10,9,8,0.2)", color: "var(--ink)" }} type="text" required value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} />
                  </div>
                )}
                <div className="field" style={{ color: "var(--ink)" }}>
                  <label style={{ color: "var(--muted)" }}>Email</label>
                  <input style={{ borderColor: "rgba(10,9,8,0.2)", color: "var(--ink)" }} type="email" required value={form.email} onChange={(e) => setForm({ ...form, email: e.target.value })} />
                </div>
                <div className="field" style={{ color: "var(--ink)" }}>
                  <label style={{ color: "var(--muted)" }}>Mot de passe</label>
                  <input style={{ borderColor: "rgba(10,9,8,0.2)", color: "var(--ink)" }} type="password" required minLength={6} value={form.password} onChange={(e) => setForm({ ...form, password: e.target.value })} />
                </div>
                {error && (
                  <div style={{ color: error.startsWith("✓") ? "#16a34a" : "var(--crimson)", fontSize: 13, marginTop: 8, padding: "8px 12px", background: error.startsWith("✓") ? "rgba(22,163,74,0.08)" : "rgba(200,16,46,0.08)", borderRadius: 4 }}>
                    {error}
                  </div>
                )}
                <button className="btn btn--primary" type="submit" disabled={loading} style={{ width: "100%", justifyContent: "center", marginTop: 16, opacity: loading ? 0.6 : 1 }}>
                  <span>{loading ? "…" : showSignup ? "Créer mon compte" : "Se connecter"}</span>
                  {!loading && <IconArrowRight />}
                </button>
                {!showSignup && (
                  <div style={{ marginTop: 12, textAlign: "center" }}>
                    <button type="button" onClick={() => { setResetStep("email"); setResetEmail(form.email); setError(""); }}
                      style={{ background: "none", border: "none", color: "var(--muted)", fontSize: 13, cursor: "pointer" }}>
                      Mot de passe oublié ?
                    </button>
                  </div>
                )}
              </form>

              <div style={{ marginTop: 24, padding: 16, background: "var(--cream-2)", borderRadius: 8, fontSize: 12, color: "var(--muted)", display: "flex", alignItems: "start", gap: 10, lineHeight: 1.5 }}>
                <IconLock />
                <div>
                  Si votre email correspond à une fiche dans notre boutique, votre historique et vos Shuriken Points s'affichent <strong style={{ color: "var(--ink)" }}>automatiquement</strong>.
                </div>
              </div>
            </div>
          </div>
        </section>
      </div>
    );
  }

  // ── DASHBOARD ────────────────────────────
  const pts   = customer?.shuriken_points ?? 0;
  const uName = customer?.name || account?.name || "Client";
  const uMail = customer?.email || account?.email || "—";
  const uPhone = customer?.phone || "—";

  const niveau = pts >= 2000 ? "Jonin" : pts >= 500 ? "Chunin" : "Genin";
  const nextPalier = pts >= 2000 ? "Niveau max" : pts >= 500 ? `Jonin · ${2000 - pts} pts` : `Chunin · ${500 - pts} pts`;

  const Spinner = () => (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "center", padding: 48 }}>
      <Shuriken size={32} className="shuriken-rotate" style={{ color: "var(--crimson)" }} />
    </div>
  );

  // — order card —
  const OrderCard = ({ o }) => {
    const items = parseItems(o.items_json);
    const statusColor = STATUS_COLOR[o.status] || "var(--muted-2)";
    return (
      <div style={{ padding: 20, background: "var(--cream)", border: "1px solid rgba(10,9,8,0.1)", borderRadius: 10, display: "flex", flexDirection: "column", gap: 10 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 8, flexWrap: "wrap" }}>
          <div>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 16, letterSpacing: 0.05 }}>{o.order_number}</span>
            <span style={{ marginLeft: 10, fontSize: 11, fontFamily: "var(--font-mono)", color: "var(--muted)", textTransform: "uppercase" }}>{TYPE_LABEL[o.type] || o.type}</span>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
            <span style={{ width: 8, height: 8, borderRadius: "50%", background: statusColor, flexShrink: 0, display: "inline-block" }} />
            <span style={{ fontSize: 12, color: statusColor, fontFamily: "var(--font-mono)" }}>{STATUS_LABELS[o.status] || o.status}</span>
          </div>
        </div>
        {items.length > 0 && (
          <div style={{ fontSize: 13, color: "var(--muted)", display: "flex", flexDirection: "column", gap: 3 }}>
            {items.map((it, i) => (
              <div key={i} style={{ display: "flex", justifyContent: "space-between" }}>
                <span>{it.product_name || it.description || "Article"}{it.quantity > 1 ? ` ×${it.quantity}` : ""}</span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 12 }}>{fmtPrice(it.total ?? it.unit_price)}</span>
              </div>
            ))}
          </div>
        )}
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", borderTop: "1px solid rgba(10,9,8,0.06)", paddingTop: 10 }}>
          <span style={{ fontSize: 12, color: "var(--muted)" }}>{fmtDate(o.created_at)}</span>
          <span style={{ fontFamily: "var(--font-display)", fontSize: 20 }}>{fmtPrice(o.total)}</span>
        </div>
      </div>
    );
  };

  return (
    <div className="paper">
      <div className="page-hero">
        <span className="kanji">道場</span>
        <div className="container">
          <span className="kicker" style={{ color: "var(--crimson)" }}>ESPACE CLIENT · DOJO</span>
          <h1>Bienvenue,<br/><em style={{ fontStyle: "italic", color: "var(--crimson)" }}>{uName}.</em></h1>
          <p>Votre historique, vos Shuriken Points et vos réparations en cours — synchronisés en temps réel.</p>
        </div>
      </div>

      <section className="section section--cream">
        <div className="container">
          <div className="account-shell">

            {/* ── SIDEBAR ── */}
            <aside className="account-side">
              <div className="account-user">
                <div className="account-avatar">{(uName)[0].toUpperCase()}</div>
                <div className="account-name">{uName}</div>
                <div className="account-mail">{uMail}</div>
              </div>
              <nav className="account-nav">
                <a className={tab === "overview"  ? "active" : ""} onClick={() => setTab("overview")}><Shuriken size={14} /> Aperçu</a>
                <a className={tab === "repairs"   ? "active" : ""} onClick={() => setTab("repairs")}><IconTools size={14} /> Réparations en cours</a>
                <a className={tab === "requests"  ? "active" : ""} onClick={() => setTab("requests")}><IconSparkle size={14} /> Mes demandes{clientRequests.filter(r => r.status === "pending").length > 0 && <span style={{ marginLeft: 6, background: "var(--crimson)", color: "#fff", borderRadius: 100, fontSize: 10, padding: "1px 6px" }}>{clientRequests.filter(r => r.status === "pending").length}</span>}</a>
                <a className={tab === "history"   ? "active" : ""} onClick={() => setTab("history")}><IconReceipt size={14} /> Historique</a>
                <a className={tab === "invoices"  ? "active" : ""} onClick={() => setTab("invoices")}><IconReceipt size={14} /> Factures</a>
                <a className={tab === "points"    ? "active" : ""} onClick={() => setTab("points")}><IconSparkle size={14} /> Shuriken Points</a>
                <a className={tab === "settings"  ? "active" : ""} onClick={() => setTab("settings")}><IconSettings size={14} /> Mon compte</a>
                <a onClick={logout} style={{ marginTop: 16, color: "var(--muted)", cursor: "pointer" }}>Déconnexion →</a>
              </nav>
            </aside>

            {/* ── MAIN ── */}
            <main className="account-main">

              {/* ══ APERÇU ══ */}
              {tab === "overview" && (
                <div>
                  <div className="points-card">
                    <Shuriken className="shuriken-bg shuriken-rotate" />
                    <span className="kicker">SHURIKEN POINTS</span>
                    <div className="value">{pts}<em>pts</em></div>
                    <div className="meta">
                      <div className="item"><div className="l">Valeur</div><div className="v">{(pts * 0.05).toFixed(2)} €</div></div>
                      <div className="item"><div className="l">Niveau</div><div className="v">{niveau}</div></div>
                      <div className="item"><div className="l">Prochain palier</div><div className="v">{nextPalier}</div></div>
                    </div>
                  </div>

                  <h3 style={{ marginBottom: 16, fontSize: 22 }}>Réparations en cours</h3>
                  {dataLoading ? <Spinner /> : activeRepairs.length === 0 ? (
                    <div className="empty-state">
                      <Shuriken className="shuriken-mini" size={48} />
                      <h4>Aucune réparation active</h4>
                      <p>Vos réparations en cours apparaîtront ici automatiquement.</p>
                    </div>
                  ) : (
                    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                      {activeRepairs.slice(0, 3).map(o => (
                        <div key={o.id} style={{ padding: "12px 16px", background: "var(--cream-2)", borderRadius: 8, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                          <div>
                            <span style={{ fontFamily: "var(--font-mono)", fontWeight: 600 }}>{o.order_number}</span>
                            <span style={{ fontSize: 13, color: "var(--muted)", marginLeft: 10 }}>{parseItems(o.items_json).map(i => i.product_name || i.description).filter(Boolean).join(", ") || "—"}</span>
                          </div>
                          <span style={{ fontSize: 12, color: STATUS_COLOR[o.status], fontFamily: "var(--font-mono)" }}>{STATUS_LABELS[o.status] || o.status}</span>
                        </div>
                      ))}
                      {activeRepairs.length > 3 && (
                        <button className="btn btn--ghost btn--small" onClick={() => setTab("repairs")} style={{ alignSelf: "flex-start", color: "var(--ink)" }}>
                          Voir toutes les réparations <IconArrowRight />
                        </button>
                      )}
                    </div>
                  )}

                  {!customer?.id && (
                    <div style={{ marginTop: 24, padding: 20, background: "rgba(200,16,46,0.06)", border: "1px solid rgba(200,16,46,0.15)", borderRadius: 8, fontSize: 13, lineHeight: 1.6, color: "var(--ink)" }}>
                      <strong style={{ color: "var(--crimson)" }}>Compte non lié</strong> — votre email n'est pas encore associé à une fiche client dans notre boutique. Vos données apparaîtront automatiquement dès que la boutique vous enregistrera avec cet email.
                    </div>
                  )}
                </div>
              )}

              {/* ══ RÉPARATIONS EN COURS ══ */}
              {tab === "repairs" && (
                <div>
                  <h3 style={{ marginBottom: 24, fontSize: 28 }}>Réparations en cours</h3>
                  {dataLoading ? <Spinner /> : activeRepairs.length === 0 ? (
                    <div className="empty-state">
                      <IconTools size={48} style={{ margin: "0 auto 16px", color: "var(--cream-3)" }} />
                      <h4>Aucune réparation en cours</h4>
                      <p>Vos réparations actives (en attente, diagnostic, en réparation, prêtes) s'affichent ici.</p>
                      <button className="btn btn--primary" onClick={() => navigate("diagnostic")} style={{ marginTop: 16 }}>
                        <span>Lancer un diagnostic</span><IconArrowRight />
                      </button>
                    </div>
                  ) : (
                    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
                      {activeRepairs.map(o => <OrderCard key={o.id} o={o} />)}
                    </div>
                  )}
                </div>
              )}

              {/* ══ MES DEMANDES ══ */}
              {tab === "requests" && (() => {
                const REQ_TYPE   = { diagnostic: "Diagnostic", appointment: "Rendez-vous", coursier: "Coursier", contact: "Contact", devis: "Devis" };
                const REQ_STATUS = { pending: "En attente", confirmed: "Confirmé", in_progress: "En cours", completed: "Terminé", cancelled: "Annulé" };
                const REQ_STATUS_COLOR = { pending: "var(--gold)", confirmed: "#3b82f6", in_progress: "var(--crimson)", completed: "#16a34a", cancelled: "var(--muted-2)" };
                return (
                  <div>
                    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 24 }}>
                      <h3 style={{ fontSize: 28 }}>Mes demandes</h3>
                      <button className="btn btn--primary btn--small" onClick={() => navigate("diagnostic")}>
                        <span>Nouveau diagnostic</span><IconArrowRight />
                      </button>
                    </div>
                    {dataLoading ? <Spinner /> : clientRequests.length === 0 ? (
                      <div className="empty-state">
                        <IconSparkle size={48} style={{ margin: "0 auto 16px", color: "var(--cream-3)" }} />
                        <h4>Aucune demande</h4>
                        <p>Vos demandes de diagnostic, devis et rendez-vous apparaîtront ici.</p>
                        <button className="btn btn--primary" onClick={() => navigate("diagnostic")} style={{ marginTop: 16 }}>
                          <span>Lancer un diagnostic</span><IconArrowRight />
                        </button>
                      </div>
                    ) : (
                      <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
                        {clientRequests.map(req => (
                          <div key={req.id} style={{ padding: 20, background: "var(--cream)", border: "1px solid rgba(10,9,8,0.1)", borderRadius: 10 }}>
                            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 8, marginBottom: 10 }}>
                              <div>
                                <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--crimson)", textTransform: "uppercase", letterSpacing: 0.1 }}>{REQ_TYPE[req.type] || req.type}</span>
                                <div style={{ fontSize: 15, fontWeight: 500, marginTop: 2 }}>
                                  {[req.device_type, req.device_model].filter(Boolean).join(" · ") || "Demande générale"}
                                </div>
                                {req.issue_type && <div style={{ fontSize: 13, color: "var(--muted)", marginTop: 2 }}>{STATUS_LABELS[req.issue_type] || req.issue_type}{req.estimated_price ? ` · Estimation ${fmtPrice(req.estimated_price)}` : ""}</div>}
                              </div>
                              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                                <span style={{ width: 8, height: 8, borderRadius: "50%", background: REQ_STATUS_COLOR[req.status] || "var(--muted-2)", display: "inline-block" }} />
                                <span style={{ fontSize: 12, color: REQ_STATUS_COLOR[req.status], fontFamily: "var(--font-mono)" }}>{REQ_STATUS[req.status] || req.status}</span>
                              </div>
                            </div>
                            <div style={{ display: "flex", gap: 24, flexWrap: "wrap", fontSize: 12, color: "var(--muted)", borderTop: "1px solid rgba(10,9,8,0.06)", paddingTop: 10 }}>
                              <span>Envoyée le {fmtDate(req.created_at)}</span>
                              {req.preferred_date && <span>Souhaitée : {fmtDate(req.preferred_date)} · {req.preferred_slot || ""}</span>}
                              {req.confirmed_date && <span style={{ color: "#16a34a" }}>Confirmée : {fmtDate(req.confirmed_date)} · {req.confirmed_slot || ""}</span>}
                              {req.pickup_address && <span>📍 {req.pickup_address}</span>}
                            </div>
                            {req.pos_notes && (
                              <div style={{ marginTop: 10, padding: "10px 14px", background: "rgba(59,130,246,0.06)", border: "1px solid rgba(59,130,246,0.15)", borderRadius: 6, fontSize: 13 }}>
                                <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "#3b82f6", textTransform: "uppercase", letterSpacing: 0.1 }}>Message de la boutique</span>
                                <div style={{ marginTop: 4 }}>{req.pos_notes}</div>
                              </div>
                            )}
                            {["confirmed", "in_progress", "completed"].includes(req.status) && (
                              <div style={{ marginTop: 12 }}>
                                <button
                                  className="btn btn--ghost btn--small"
                                  onClick={() => setOpenChatReqId(openChatReqId === req.id ? null : req.id)}
                                  style={{ fontSize: 12, color: "#3b82f6", borderColor: "rgba(59,130,246,0.3)" }}
                                >
                                  <span>{openChatReqId === req.id ? "Fermer le chat" : "💬 Chat avec Repair Ninja"}</span>
                                </button>
                                {openChatReqId === req.id && (
                                  <ChatPanel requestId={req.id} authUid={authUid} />
                                )}
                              </div>
                            )}
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                );
              })()}

              {/* ══ HISTORIQUE COMPLET ══ */}
              {tab === "history" && (
                <div>
                  <h3 style={{ marginBottom: 24, fontSize: 28 }}>Historique complet</h3>
                  {dataLoading ? <Spinner /> : allOrders.length === 0 ? (
                    <div className="empty-state">
                      <IconReceipt size={48} style={{ margin: "0 auto 16px", color: "var(--cream-3)" }} />
                      <h4>Aucun historique</h4>
                      <p>Toutes vos réparations et achats en boutique apparaîtront ici.</p>
                    </div>
                  ) : (
                    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
                      {allOrders.map(o => <OrderCard key={o.id} o={o} />)}
                    </div>
                  )}
                </div>
              )}

              {/* ══ FACTURES ══ */}
              {tab === "invoices" && (
                <InvoicesTab
                  invoices={invoices}
                  allOrders={allOrders}
                  customer={customer}
                  dataLoading={dataLoading}
                  Spinner={Spinner}
                />
              )}

              {/* ══ SHURIKEN POINTS ══ */}
              {tab === "points" && (
                <div>
                  <h3 style={{ marginBottom: 24, fontSize: 28 }}>Shuriken Points</h3>
                  <div className="points-card">
                    <Shuriken className="shuriken-bg shuriken-rotate" />
                    <span className="kicker">SOLDE ACTUEL</span>
                    <div className="value">{pts}<em>pts</em></div>
                    <div style={{ marginTop: 16, color: "var(--muted-2)", fontSize: 14, maxWidth: 480 }}>
                      Soit <strong style={{ color: "var(--cream)" }}>{(pts * 0.05).toFixed(2)} €</strong> utilisables sur votre prochaine réparation ou commande.
                    </div>
                  </div>

                  <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 16, marginTop: 32 }}>
                    {[
                      { lvl: "Genin",  min: 0,    color: "var(--crimson)" },
                      { lvl: "Chunin", min: 500,  color: "var(--gold)" },
                      { lvl: "Jonin",  min: 2000, color: "var(--ink)" },
                    ].map((r) => (
                      <div key={r.lvl} style={{ background: r.lvl === niveau ? "var(--cream-2)" : "var(--cream)", padding: 24, borderRadius: 8, borderLeft: `3px solid ${r.color}`, border: r.lvl === niveau ? `2px solid ${r.color}` : `1px solid rgba(10,9,8,0.08)`, boxShadow: r.lvl === niveau ? `0 0 0 1px ${r.color}22` : "none" }}>
                        <div style={{ fontFamily: "var(--font-jp)", color: r.color, fontSize: 14, letterSpacing: 0.2, textTransform: "uppercase", marginBottom: 4 }}>{r.lvl}</div>
                        <div style={{ fontFamily: "var(--font-display)", fontSize: 28 }}>{r.min}+</div>
                        <div style={{ fontSize: 12, color: "var(--muted)", marginTop: 4 }}>points requis{r.lvl === niveau ? " · Niveau actuel" : ""}</div>
                      </div>
                    ))}
                  </div>

                  {loyaltyLog.length > 0 && (
                    <>
                      <h4 style={{ marginTop: 36, marginBottom: 16, fontSize: 18 }}>Historique des points</h4>
                      <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                        {loyaltyLog.map(l => (
                          <div key={l.id} style={{ padding: "12px 16px", background: "var(--cream)", border: "1px solid rgba(10,9,8,0.08)", borderRadius: 8, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                            <div>
                              <span style={{ fontSize: 14 }}>{l.reason || "Mouvement de points"}</span>
                              <span style={{ fontSize: 11, color: "var(--muted)", fontFamily: "var(--font-mono)", display: "block", marginTop: 2 }}>{fmtDate(l.created_at)}</span>
                            </div>
                            <span style={{ fontFamily: "var(--font-display)", fontSize: 20, color: l.points >= 0 ? "#16a34a" : "var(--crimson)" }}>
                              {l.points >= 0 ? "+" : ""}{l.points}
                            </span>
                          </div>
                        ))}
                      </div>
                    </>
                  )}

                  <div style={{ marginTop: 32, padding: 24, background: "var(--cream-2)", borderRadius: 8, fontSize: 13, lineHeight: 1.6 }}>
                    <strong>Comment ça marche ?</strong><br/>
                    1 € dépensé en boutique = 1 Shuriken Point.<br/>
                    Chaque point vaut 0,05 € utilisables sur votre prochain achat.<br/>
                    Aucune date d'expiration.
                  </div>
                </div>
              )}

              {/* ══ MON COMPTE ══ */}
              {tab === "settings" && (
                <div>
                  <h3 style={{ marginBottom: 24, fontSize: 28 }}>Mon compte</h3>
                  <div style={{ padding: 24, background: "var(--cream-2)", borderRadius: 8, marginBottom: 24, fontSize: 13, color: "var(--muted)", display: "flex", gap: 10, lineHeight: 1.5 }}>
                    <IconLock />
                    <span>Le portail est en lecture seule. Pour modifier vos informations, contactez la boutique.</span>
                  </div>
                  <div className="field">
                    <label style={{ color: "var(--muted)" }}>Nom complet</label>
                    <input style={{ borderBottomColor: "rgba(10,9,8,0.15)", color: "var(--ink)" }} type="text" readOnly value={uName} />
                  </div>
                  <div className="field">
                    <label style={{ color: "var(--muted)" }}>Email</label>
                    <input style={{ borderBottomColor: "rgba(10,9,8,0.15)", color: "var(--ink)" }} type="email" readOnly value={uMail} />
                  </div>
                  <div className="field">
                    <label style={{ color: "var(--muted)" }}>Téléphone</label>
                    <input style={{ borderBottomColor: "rgba(10,9,8,0.15)", color: "var(--ink)" }} type="tel" readOnly value={uPhone} />
                  </div>
                  <div style={{ marginTop: 32, paddingTop: 24, borderTop: "1px solid rgba(10,9,8,0.08)" }}>
                    <button className="btn btn--ghost btn--small" onClick={logout} style={{ color: "var(--crimson)" }}>
                      Déconnexion →
                    </button>
                  </div>
                </div>
              )}

            </main>
          </div>
        </div>
      </section>
    </div>
  );
};

Object.assign(window, { Diagnostic, DiagnosticPage, ShopPage, TrackingPage, AccountPage });
