// ui.jsx — shared UI: icons, nav, avatar menu, toast, login modal, plan detail sheet
const { useState: useStateU, useEffect: useEffectU, useRef: useRefU } = React;

// ── Icons ─────────────────────────────────────────────────────────────────────
const Ic = {
  globe:    p => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" {...p}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.6 2.5 15.4 0 18M12 3c-2.5 2.6-2.5 15.4 0 18"/></svg>,
  bolt:     p => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinejoin="round" {...p}><path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z"/></svg>,
  shield:   p => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinejoin="round" {...p}><path d="M12 3 5 6v5c0 4.5 3 8 7 10 4-2 7-5.5 7-10V6l-7-3Z"/><path d="m9 12 2 2 4-4"/></svg>,
  signal:   p => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" {...p}><path d="M5 19a14 14 0 0 1 14 0M8 16a9 9 0 0 1 8 0M11 13a4 4 0 0 1 2 0"/><circle cx="12" cy="20" r="1" fill="currentColor"/></svg>,
  search:   p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  check:    p => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m20 6-11 11-5-5"/></svg>,
  qr:       p => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" {...p}><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><path d="M14 14h3v3M21 14v7M17 21h4M21 17.5h-.01"/></svg>,
  arrow:    p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 5l7 7-7 7"/></svg>,
  plus:     p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  user:     p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" {...p}><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 4-6 8-6s8 2 8 6"/></svg>,
  logout:   p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg>,
  x:        p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M6 6l12 12M18 6 6 18"/></svg>,
  menu:     p => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M4 7h16M4 12h16M4 17h16"/></svg>,
  spark:    p => <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M12 2l1.8 6.2L20 10l-6.2 1.8L12 18l-1.8-6.2L4 10l6.2-1.8L12 2Z"/></svg>,
  clock:    p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" {...p}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>,
  infinity: p => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" {...p}><path d="M6 16c-2.2 0-4-1.8-4-4s1.8-4 4-4c3 0 4 4 6 4s3-4 6-4c2.2 0 4 1.8 4 4s-1.8 4-4 4c-3 0-4-4-6-4s-3 4-6 4Z"/></svg>,
  card:     p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" {...p}><rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20"/></svg>,
  gift:     p => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 12v10H4V12M22 7H2v5h20V7zM12 22V7M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7zM12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>,
  copy:     p => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" {...p}><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>,
  share:    p => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.59 13.51 6.83 3.98M15.41 6.51l-6.82 3.98"/></svg>,
};

const GoogleG = p => (
  <svg width="20" height="20" viewBox="0 0 24 24" {...p}>
    <path fill="#4285F4" d="M22.5 12.2c0-.7-.06-1.4-.18-2.06H12v3.9h5.9a5.05 5.05 0 0 1-2.19 3.32v2.76h3.54c2.07-1.91 3.25-4.72 3.25-8.02Z"/>
    <path fill="#34A853" d="M12 23c2.95 0 5.43-.98 7.24-2.64l-3.54-2.76c-.98.66-2.24 1.05-3.7 1.05-2.85 0-5.26-1.92-6.12-4.5H2.22v2.84A11 11 0 0 0 12 23Z"/>
    <path fill="#FBBC05" d="M5.88 14.15a6.6 6.6 0 0 1 0-4.3V7.01H2.22a11 11 0 0 0 0 9.98l3.66-2.84Z"/>
    <path fill="#EA4335" d="M12 5.5c1.6 0 3.05.55 4.18 1.63l3.14-3.14C17.43 2.18 14.95 1 12 1A11 11 0 0 0 2.22 7.01l3.66 2.84C6.74 7.42 9.15 5.5 12 5.5Z"/>
  </svg>
);

function isGenericPlanNetwork(value) {
  return !value || /^4g\/5g$/i.test(String(value).trim());
}

function isGenericPlanCarrier(value) {
  return !value || /^\d+\s+(country|countries|destination|destinations)$/i.test(String(value).trim());
}

function planNetworkSummary(plan) {
  const parts = [];
  if (!isGenericPlanNetwork(plan?.net)) parts.push(plan.net);
  if (!isGenericPlanCarrier(plan?.carriers)) parts.push(plan.carriers);
  return parts.join(" · ");
}

function uiMoney(value) {
  const amount = Number(value);
  return Number.isFinite(amount) ? amount.toFixed(2) : "0.00";
}

// ── Nav ───────────────────────────────────────────────────────────────────────
function Nav({ route, go, user, onLogin, onLogout }) {
  const [scrolled, setScrolled] = useStateU(false);
  const [menu, setMenu]         = useStateU(false);
  const [mobileNavOpen, setMobileNavOpen] = useStateU(false);
  useEffectU(() => {
    const f = () => setScrolled(window.scrollY > 12);
    window.addEventListener("scroll", f);
    return () => window.removeEventListener("scroll", f);
  }, []);
  useEffectU(() => {
    setMobileNavOpen(false);
  }, [route]);

  const links = [["home", "Home"], ["marketplace", "Marketplace"], ["myesims", "My eSIMs"]];
  const solidNav = scrolled || route.startsWith("marketplace/");
  const navTo = key => {
    setMobileNavOpen(false);
    go(key);
  };

  return (
    <nav className={"nav" + (solidNav ? " nav-scrolled" : "")}>
      <div className="nav-inner">
        <div className="brand" onClick={() => go("home")} style={{ cursor: "pointer" }}>
          <img className="brand-mark" src="/logo-transparent.png" alt="" /> Journey
        </div>
        <div className="nav-links">
          {links.map(([k, l]) => (
            <span key={k} className={"nav-link" + (route === k || route.startsWith(k + "/") ? " active" : "")}
              onClick={() => go(k)}>{l}</span>
          ))}
        </div>
        <div className="nav-spacer"></div>
        <button
          type="button"
          className="mobile-nav-toggle"
          aria-label={mobileNavOpen ? "Close navigation menu" : "Open navigation menu"}
          aria-expanded={mobileNavOpen}
          onClick={() => setMobileNavOpen(open => !open)}
        >
          {mobileNavOpen ? <Ic.x/> : <Ic.menu/>}
        </button>
        {user ? (
          <div className="nav-account" style={{ position: "relative", display: "flex", alignItems: "center", gap: 10 }}>
            {user.creditCents > 0 && (
              <div className="credit-pill">${(user.creditCents / 100).toFixed(2)} credit</div>
            )}
            <div className="avatar" onClick={() => setMenu(m => !m)}>
              {user.photo
                ? <img src={user.photo} alt={user.name} style={{ width: "100%", height: "100%", borderRadius: "50%", objectFit: "cover" }} referrerPolicy="no-referrer" />
                : user.name[0].toUpperCase()}
            </div>
            {menu && (
              <>
                <div style={{ position: "fixed", inset: 0, zIndex: 290 }} onClick={() => setMenu(false)}></div>
                <div className="menu">
                  <div className="menu-user">
                    <div style={{ fontWeight: 700, fontSize: 14 }}>{user.name}</div>
                    <div style={{ color: "var(--muted)", fontSize: 12.5, marginTop: 2 }}>{user.email}</div>
                  </div>
                  <div className="menu-item" onClick={() => { setMenu(false); go("myesims"); }}><Ic.qr/> My eSIMs</div>
                  <div className="menu-item" onClick={() => { setMenu(false); go("referrals"); }}><Ic.gift/> My Referrals</div>
                  <div className="menu-item" onClick={() => { setMenu(false); onLogout(); }}><Ic.logout/> Sign out</div>
                </div>
              </>
            )}
          </div>
        ) : (
          <button className="btn btn-ghost btn-sm nav-account" onClick={onLogin}>Sign in</button>
        )}
      </div>
      {mobileNavOpen && (
        <>
          <div className="mobile-nav-scrim" onClick={() => setMobileNavOpen(false)}></div>
          <div className="mobile-nav-panel">
            {links.map(([k, l]) => (
              <button
                key={k}
                type="button"
                className={"mobile-nav-link" + (route === k || route.startsWith(k + "/") ? " active" : "")}
                onClick={() => navTo(k)}
              >
                {l}
              </button>
            ))}
          </div>
        </>
      )}
    </nav>
  );
}

// ── Toast ─────────────────────────────────────────────────────────────────────
function ToastHost({ toasts }) {
  return (
    <div className="toast-wrap">
      {toasts.map(t => (
        <div className="toast" key={t.id}>
          <span className="tick"><Ic.check/></span>{t.msg}
        </div>
      ))}
    </div>
  );
}

// ── Login modal ───────────────────────────────────────────────────────────────
function LoginModal({ onClose }) {
  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="modal-top">
          <div className="modal-x" onClick={onClose}><Ic.x/></div>
          <div className="modal-orb"></div>
          <h2>Welcome to Journey</h2>
          <p>Sign in to purchase and manage your travel eSIMs</p>
        </div>
        <div className="modal-body">
          <button className="gbtn" onClick={() => { window.location.href = "/auth/google"; }}>
            <GoogleG/> Continue with Google
          </button>
          <div className="fineprint" style={{ textAlign: "center", marginTop: 16 }}>
            By signing in you agree to our terms of service and privacy policy.
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Plan detail sheet ─────────────────────────────────────────────────────────
function PlanSheet({ plan, onClose, onBuy, user }) {
  if (!plan) return null;
  const [buying, setBuying] = useStateU(false);
  const [applyCredit, setApplyCredit] = useStateU(false);
  const [refCode, setRefCode] = useStateU(() => localStorage.getItem("pendingReferralCode") || "");
  const [refStatus, setRefStatus] = useStateU(null); // null | { ok, discountCents } | { error }
  const [refChecking, setRefChecking] = useStateU(false);

  useEffectU(() => {
    const saved = localStorage.getItem("pendingReferralCode");
    if (saved && user) validateRef(saved);
  }, [user?.id, plan?.id]);

  const networkSummary = planNetworkSummary(plan);
  const heroChip = [plan.region, !isGenericPlanNetwork(plan.net) ? plan.net : ""].filter(Boolean).join(" · ");
  const perks = [
    "QR delivery after provider provisioning",
    "No physical SIM needed",
    "Keep your home number",
    "Hotspot / tethering ready",
  ];

  const retailPrice = plan.price;
  const creditCents = user?.creditCents || 0;
  const creditDollars = creditCents / 100;

  const discountCents = (refStatus?.ok && refStatus.discountCents) ? refStatus.discountCents : 0;
  const creditUsedCents = applyCredit && !refStatus?.ok ? Math.min(creditCents, Math.round(retailPrice * 100)) : 0;
  const finalPrice = Math.max(0, retailPrice - creditUsedCents / 100 - discountCents / 100);
  const isFree = finalPrice === 0;

  const validateRef = async (code) => {
    if (!code.trim() || !user) return;
    setRefChecking(true);
    setRefStatus(null);
    try {
      const res = await fetch("/api/validate-referral", {
        method: "POST", credentials: "include",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ code: code.trim(), planId: plan.id }),
      });
      const data = await res.json();
      if (res.ok) {
        setRefStatus({ ok: true, discountCents: data.discountCents });
        setApplyCredit(false);
      } else {
        setRefStatus({ error: data.error });
      }
    } catch (_) {
      setRefStatus({ error: "Could not validate code" });
    }
    setRefChecking(false);
  };

  const handleRefChange = (val) => {
    setRefCode(val);
    setRefStatus(null);
  };

  const handleBuy = async () => {
    setBuying(true);
    await onBuy(plan, {
      applyCredit: applyCredit && !refStatus?.ok,
      referralCode: refStatus?.ok ? refCode.trim().toUpperCase() : null,
      discountCents,
      creditUsedCents,
      isFree,
    });
    setBuying(false);
  };

  const checkoutLabel = () => {
    if (!user) return "Sign in to checkout";
    if (isFree) return "Claim free eSIM";
    return `Checkout · $${uiMoney(finalPrice)}`;
  };

  return (
    <>
      <div className="sheet-scrim" onClick={onClose}></div>
      <div className="sheet">
        <div className="sheet-hero">
          <div className="modal-x" style={{ position: "absolute", top: 22, right: 22 }} onClick={onClose}><Ic.x/></div>
          <div className="chip accent">{heroChip}</div>
          <h2 style={{ fontFamily: "var(--font-d)", fontSize: 30, letterSpacing: "-0.03em", margin: "12px 0 4px" }}>{plan.country}</h2>
          {networkSummary && <div style={{ color: "var(--muted)", fontSize: 14 }}>{networkSummary}</div>}
        </div>
        <div className="sheet-body">
          <div className="sheet-row"><span className="k">Data</span><span className="v">{plan.data}</span></div>
          <div className="sheet-row"><span className="k">Validity</span><span className="v">{plan.days} days</span></div>
          <div className="sheet-row"><span className="k">Network</span><span className="v">{networkSummary || "Supported partner networks"}</span></div>
          <div className="sheet-row"><span className="k">Activation</span><span className="v">Scan QR · eKYC-free</span></div>
          <div className="sheet-price">
            {(creditUsedCents > 0 || discountCents > 0) && (
              <span className="price-original">${uiMoney(retailPrice)}</span>
            )}
            <span className="big">{isFree ? "Free" : `$${uiMoney(finalPrice)}`}</span>
            <span style={{ color: "var(--muted)" }}>one-time · no subscription</span>
          </div>

          {user && creditCents > 0 && !refStatus?.ok && (
            <label className="credit-toggle">
              <input type="checkbox" checked={applyCredit} onChange={e => setApplyCredit(e.target.checked)} />
              <span>Apply ${uiMoney(creditDollars)} credit
                <span className="credit-toggle-save"> — saves ${uiMoney(Math.min(creditDollars, retailPrice))}</span>
              </span>
            </label>
          )}

          {user && !applyCredit && (
            <div className="ref-input-wrap">
              <div className="ref-input-row">
                <input
                  className={"ref-input" + (refStatus?.ok ? " ref-ok" : refStatus?.error ? " ref-err" : "")}
                  placeholder="Referral code (optional)"
                  value={refCode}
                  onChange={e => handleRefChange(e.target.value.toUpperCase())}
                  onKeyDown={e => e.key === "Enter" && validateRef(refCode)}
                  maxLength={20}
                />
                <button className="ref-apply-btn" onClick={() => validateRef(refCode)} disabled={refChecking || !refCode.trim()}>
                  {refChecking ? <span className="spinner" style={{ width: 14, height: 14 }} /> : "Apply"}
                </button>
              </div>
              {refStatus?.ok && <div className="ref-msg ref-msg-ok"><Ic.check/> ${uiMoney(discountCents / 100)} off applied!</div>}
              {refStatus?.error && <div className="ref-msg ref-msg-err">{refStatus.error}</div>}
            </div>
          )}

          <div style={{ display: "grid", gap: 10, margin: "20px 0 26px" }}>
            {perks.map(p => (
              <div key={p} style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 14 }}>
                <span style={{ color: "var(--accent)", display: "grid", placeItems: "center" }}><Ic.check/></span>{p}
              </div>
            ))}
          </div>
          <button className="btn btn-accent btn-lg" style={{ width: "100%" }}
            onClick={handleBuy} disabled={buying}>
            {buying ? <span className="spinner"></span> : <><Ic.card/> {checkoutLabel()}</>}
          </button>
          <p className="fineprint">Payment is processed first. Your eSIM install details appear in My eSIMs after provider provisioning completes.</p>
        </div>
      </div>
    </>
  );
}

function FreeConfirmModal({ plan, opts, onClose, onConfirm }) {
  const [confirming, setConfirming] = useStateU(false);
  const saving = ((opts.creditUsedCents || 0) + (opts.discountCents || 0)) / 100;
  return (
    <>
      <div className="modal-scrim" onClick={onClose}></div>
      <div className="modal" style={{ maxWidth: 420, textAlign: "center" }}>
        <div className="modal-x" onClick={onClose}><Ic.x/></div>
        <div style={{ fontSize: 40, marginBottom: 8 }}>🎉</div>
        <h3 style={{ fontFamily: "var(--font-d)", fontSize: 22, margin: "0 0 8px" }}>Your plan is fully covered!</h3>
        <p style={{ color: "var(--muted)", fontSize: 14, margin: "0 0 20px" }}>
          {plan.country} {plan.data} · {plan.days} days<br/>
          <strong style={{ color: "var(--pos)" }}>${saving.toFixed(2)} saved</strong> — no charge today
        </p>
        <button className="btn btn-accent btn-lg" style={{ width: "100%" }}
          disabled={confirming}
          onClick={async () => { setConfirming(true); await onConfirm(); }}>
          {confirming ? <span className="spinner"/> : "Confirm & get my eSIM"}
        </button>
        <button className="btn btn-ghost" style={{ width: "100%", marginTop: 10 }} onClick={onClose}>Cancel</button>
      </div>
    </>
  );
}

function Referrals({ user, go, toast }) {
  const [data, setData] = useStateU(null);
  const [loading, setLoading] = useStateU(true);
  const [copiedCode, setCopiedCode] = useStateU(false);
  const [copiedLink, setCopiedLink] = useStateU(false);

  useEffectU(() => {
    fetch("/api/my-referrals", { credentials: "include" })
      .then(r => r.json())
      .then(d => { setData(d); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  if (!user) {
    return (
      <div style={{ padding: "80px 24px", textAlign: "center" }}>
        <p style={{ color: "var(--muted)" }}>Sign in to view your referral code.</p>
      </div>
    );
  }

  const copyText = (text, setCopied) => {
    navigator.clipboard.writeText(text)
      .then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); })
      .catch(() => toast("Could not copy — try manually selecting the text"));
  };

  return (
    <div className="referrals-page">
      <div className="referrals-inner">
        <h1 className="referrals-title">Refer friends, earn credit</h1>
        <p className="referrals-sub">
          Share your code with a friend. When they buy their first eSIM they get{" "}
          <strong>70% off</strong>{" "}
          <span style={{ color: "var(--muted)", fontSize: 13 }}>(up to $5.00)</span>.
          You get <strong>$3.00 credit</strong> added to your account.
        </p>

        <div className="ref-card">
          <div className="ref-card-label">Your referral code</div>
          {loading ? (
            <div className="ref-code-display" style={{ opacity: .4, fontSize: 22 }}>Generating…</div>
          ) : data?.code ? (
            <>
              <div className="ref-code-display">{data.code}</div>
              <div className="ref-card-actions">
                <button className="btn btn-accent" onClick={() => copyText(data.code, setCopiedCode)}>
                  <Ic.copy/> {copiedCode ? "Copied!" : "Copy code"}
                </button>
                <button className="btn btn-ghost" onClick={() => copyText(data.shareUrl, setCopiedLink)}>
                  <Ic.share/> {copiedLink ? "Copied!" : "Copy link"}
                </button>
              </div>
            </>
          ) : (
            <div style={{ color: "var(--muted)", fontSize: 14 }}>Could not load your code — try refreshing.</div>
          )}
        </div>

        <div className="ref-stats-row">
          <div className="ref-stat">
            <div className="ref-stat-num">{loading ? "—" : (data?.count ?? 0)}</div>
            <div className="ref-stat-label">Successful referrals</div>
          </div>
          <div className="ref-stat">
            <div className="ref-stat-num">{loading ? "—" : `$${((data?.creditEarned || 0) / 100).toFixed(2)}`}</div>
            <div className="ref-stat-label">Credits earned from referrals</div>
          </div>
          <div className="ref-stat">
            <div className="ref-stat-num">${((user.creditCents || 0) / 100).toFixed(2)}</div>
            <div className="ref-stat-label">Current balance</div>
          </div>
        </div>

        <div className="ref-how">
          <div className="ref-how-step"><span className="ref-how-n">1</span><span>Share your code or link with a friend</span></div>
          <div className="ref-how-step"><span className="ref-how-n">2</span><span>They enter it at checkout on their first eSIM purchase</span></div>
          <div className="ref-how-step"><span className="ref-how-n">3</span><span>They save 70% <span style={{color:"var(--muted)",fontSize:12}}>(up to $5.00)</span> — you earn $3.00 credit</span></div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Ic, GoogleG, Nav, ToastHost, LoginModal, PlanSheet, FreeConfirmModal, Referrals });
