// VELOUR — signed-in dashboard top bar + shared dashboard pieces.
const { Avatar, Badge } = window.VelourDesignSystem_380ed4;
const DASH_FRESH = !!window.VELOUR_FRESH;

// Who the header should say you are. A real session wins; otherwise fall back to
// the name Begin collected on this device, and only then to the demo identity.
// Showing "Jennifer" to a signed-in member reads as the wrong account entirely —
// it is cosmetic in the code and not at all cosmetic to the person looking at it.
// Avatar takes the first letter of the first two words, so a real name gives the
// initials you'd expect ("Miguel Demo 3" reads MD). An account with no name yet —
// which is every magic-link signup until onboarding fills it in — has only an
// email, and "malvez825+test@…" is one word and one letter. Split the local part
// on its punctuation so those accounts get two initials too.
function nameFromEmail(email) {
  const local = String(email || "").split("@")[0];
  const parts = local.split(/[._+\-\d]+/).filter(Boolean).slice(0, 2);
  return parts.length ? parts.join(" ") : local;
}

function dashIdentity(plan) {
  const m = plan && typeof plan.member === "function" ? plan.member() : null;
  if (m) {
    const named = (m.name || "").trim();
    if (named) return { full: named, short: named.split(/\s+/)[0] };
    const derived = nameFromEmail(m.email);
    return { full: derived, short: derived.split(/\s+/)[0] };
  }
  if (DASH_FRESH) {
    try {
      const onb = JSON.parse(localStorage.getItem("velour_fresh_onboarding_v1") || "null");
      const n = onb && (onb.name || "").trim();
      if (n) return { full: n, short: n.split(/\s+/)[0] };
    } catch (e) {}
    return { full: "You", short: "You" };
  }
  return { full: "Jennifer Sichenzia", short: "Jennifer" };
}

function DashTopBar({ onNavigate, section = "dashboard", onSection }) {
  const [menuOpen, setMenuOpen] = React.useState(false);
  // Re-renders when /api/me answers, which is when the real name arrives.
  const plan = window.useVelourPlan ? window.useVelourPlan() : null;
  const [identity, setIdentity] = React.useState(() => dashIdentity(window.velourPlan));
  React.useEffect(() => { setIdentity(dashIdentity(window.velourPlan)); }, [plan]);
  // Backup lives here rather than in a pillar: it covers everything, not one section.
  const [backupNote, setBackupNote] = React.useState(null);
  const restoreRef = React.useRef(null);
  const doSave = () => {
    setBackupNote("Preparing…");
    window.velourBackup.save()
      .then((c) => setBackupNote(`Saved — ${c.keys} record${c.keys === 1 ? "" : "s"} and ${c.photos} photo${c.photos === 1 ? "" : "s"}.`))
      .catch(() => setBackupNote("Couldn't save a backup just now."));
  };
  const doRestore = (file) => {
    if (!file) return;
    setBackupNote("Restoring…");
    window.velourBackup.restore(file)
      .then((r) => { setBackupNote(`Restored ${r.keys} record${r.keys === 1 ? "" : "s"} and ${r.photos} photo${r.photos === 1 ? "" : "s"}. Reloading…`); setTimeout(() => window.location.reload(), 1200); })
      .catch((e) => setBackupNote(e.message || "That file could not be restored."));
  };
  const menuRef = React.useRef(null);
  React.useEffect(() => {
    if (!menuOpen) return;
    const onDoc = (e) => { if (menuRef.current && !menuRef.current.contains(e.target)) setMenuOpen(false); };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [menuOpen]);

  const go = (v) => (e) => { e.preventDefault(); onNavigate && onNavigate(v); };
  const goSection = (v) => (e) => { e.preventDefault(); onSection && onSection(v); };
  const pick = (v) => (e) => { e.preventDefault(); setMenuOpen(false); onSection && onSection(v); };

  // Pillars live on the left.
  const items = [
    { label: "Dashboard", view: "dashboard" },
    { label: "Rituals", view: "rituals" }, { label: "Wellness", view: "wellness" }, { label: "Wardrobe", view: "wardrobe" }, { label: "Efficiency", view: "efficiency" },
  ];
  // Education & Blog live in the menu by the user.
  const menuItems = [
    { label: "Education", view: "education", icon: "graduation-cap" },
    { label: "Blog", view: "blog", icon: "envelope-open", locked: DASH_FRESH },
  ];
  const menuActive = menuItems.some((m) => m.view === section);

  // MANAGE MEMBERSHIP LIVES HERE BECAUSE THE DASHBOARD HAS NO PRICING LINK. The
  // portal button was added to the pricing page first, which is where a member
  // decides to *start* paying — but a member who has already paid is signed in, and
  // a signed-in member never sees that page. So the only route to cancelling was
  // one that only non-members could find, which is the same asymmetry the portal
  // was built to remove, one layer up.
  //
  // Paid members only: someone on the free plan has no Stripe customer, and
  // /api/portal answers them with a sentence rather than a page. Better not to
  // offer the door than to offer one that explains itself away.
  const isPaid = !!(plan && plan.tier === "paid");

  // WHAT A MEMBER WHO HAS CANCELLED SEES. Until this, nothing: they cancelled, and
  // the product carried on exactly as before — every feature open, no acknowledgement,
  // no date, for as long as a year on an annual membership. The silence was the worst
  // part of the cancellation flow, and it was the only part that was entirely ours.
  //
  // status stays `active` because they paid for the period and keep it, so `endsOn`
  // from /api/me is the only signal. When it is absent this falls back to the renewal
  // date, which is worth saying out loud too — a member should be able to find out
  // when they will next be charged without opening Stripe.
  const billingNote = (() => {
    const b = (window.velourPlan && window.velourPlan.billing && window.velourPlan.billing()) || null;
    const when = (iso) => {
      if (!iso) return null;
      const d = new Date(iso);
      return isNaN(d) ? null : d.toLocaleDateString(undefined, { day: "numeric", month: "long", year: "numeric" });
    };
    const ends = b && when(b.endsOn);
    if (ends) return { ending: true, text: `Cancelled. Everything stays open until ${ends}.` };
    const renews = b && when(b.renewsOn);
    if (renews) return { ending: false, text: `Renews ${renews}. Your card, your invoices, and cancelling — all here.` };
    return { ending: false, text: "Your card, your invoices, and cancelling — all in one place." };
  })();
  const [portalBusy, setPortalBusy] = React.useState(false);
  const openPortal = async () => {
    if (portalBusy) return;
    let token = null;
    try {
      const sess = window.velourAuth ? await window.velourAuth.ensureFresh() : null;
      token = sess && sess.access_token ? sess.access_token : null;
    } catch (e) { token = null; }
    if (!token) return;
    setPortalBusy(true);
    try {
      const r = await fetch("/api/portal", {
        method: "POST",
        headers: { "Content-Type": "application/json", Authorization: "Bearer " + token },
      });
      const body = await r.json().catch(() => ({}));
      if (r.ok && body.url) { window.location.href = body.url; return; }
      setPortalBusy(false);
    } catch (e) { setPortalBusy(false); }
  };

  return (
    <header style={{ position: "sticky", top: 0, zIndex: 30, background: "rgba(247,244,239,0.86)", backdropFilter: "saturate(140%) blur(12px)", WebkitBackdropFilter: "saturate(140%) blur(12px)", borderBottom: "var(--border-width) solid var(--border)" }}>
      {/* This bar is built from inline styles, which cannot carry a media query —
          so at phone width it simply overflowed: 553px of it, with Wardrobe and
          Efficiency off the right edge and no way to reach them. These rules need
          !important because an inline style beats a stylesheet. The nav scrolls
          sideways rather than collapsing into another menu: four destinations is
          few enough to swipe, and hiding pillars behind a control is what made
          them unreachable in the first place. */}
      <style>{`
        @media (max-width: 900px) {
          .vlr-topbar-inner { padding: 0 16px !important; gap: 12px !important; }
          .vlr-topbar-left { gap: 18px !important; min-width: 0; }
          /* No fade mask here. A mask cannot know whether the nav is actually
             overflowing, so an unconditional one clipped the last item's final
             letter at widths where everything already fit — "Efficienc" with a
             ghosted y. A decoration that lies about the content is worse than no
             decoration. */
          .vlr-topbar-nav {
            gap: 20px !important; overflow-x: auto; scrollbar-width: none;
            -webkit-overflow-scrolling: touch;
          }
          .vlr-topbar-nav::-webkit-scrollbar { display: none; }
          .vlr-topbar-nav a { white-space: nowrap; flex: 0 0 auto; }
          .vlr-topbar-right { gap: 12px !important; }
          .vlr-topbar-search, .vlr-topbar-username, .vlr-topbar-divider { display: none !important; }
        }
      `}</style>
      <div className="vlr-topbar-inner" style={{ maxWidth: 1240, margin: "0 auto", padding: "0 32px", height: 68, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 24 }}>
        <div className="vlr-topbar-left" style={{ display: "flex", alignItems: "center", gap: 36 }}>
          <span onClick={go("home")} style={{ fontFamily: "var(--font-serif)", fontWeight: 500, fontSize: 20, letterSpacing: "var(--wordmark-ls)", paddingLeft: "var(--wordmark-ls)", color: "var(--ink)", cursor: "pointer" }}>VELOUR</span>
          <nav className="vlr-topbar-nav" style={{ display: "flex", alignItems: "center", gap: 26 }}>
            {items.map((it) => {
              const active = section === it.view;
              return (
                <a key={it.label} href="#" onClick={goSection(it.view)} style={{ fontSize: 14, color: active ? "var(--text-primary)" : "var(--text-tertiary)", fontWeight: active ? 500 : 400, cursor: "pointer", textDecoration: "none", paddingBottom: 3, borderBottom: active ? "1.5px solid var(--ink)" : "1.5px solid transparent", transition: "color var(--dur-base) var(--ease-out)" }}>{it.label}</a>
              );
            })}
          </nav>
        </div>
        <div className="vlr-topbar-right" style={{ display: "flex", alignItems: "center", gap: 18 }}>
          <div className="vlr-topbar-search" style={{ display: "flex", alignItems: "center", gap: 9, background: "var(--surface-card)", border: "var(--border-width) solid var(--border)", borderRadius: 999, padding: "8px 14px", color: "var(--text-tertiary)" }}>
            <i className="ph ph-magnifying-glass" style={{ fontSize: 16 }}></i>
            <span style={{ fontSize: 13.5 }}>Search</span>
          </div>
          <i className="ph ph-bell" style={{ fontSize: 20, color: "var(--text-secondary)", cursor: "pointer" }}></i>
          <span className="vlr-topbar-divider" style={{ width: 1, height: 26, background: "var(--border)" }}></span>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <Avatar name={identity.full} ring="rituals" size="sm" />
            <span className="vlr-topbar-username" style={{ fontSize: 14, color: "var(--text-primary)", fontWeight: 500 }}>{identity.short}</span>
          </div>

          {/* More menu — Education & Blog */}
          <div ref={menuRef} style={{ position: "relative" }}>
            <button onClick={() => setMenuOpen((o) => !o)} aria-label="More" aria-expanded={menuOpen} style={{ width: 36, height: 36, borderRadius: 10, display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", background: (menuOpen || menuActive) ? "var(--surface-sunken)" : "transparent", border: "var(--border-width) solid " + ((menuOpen || menuActive) ? "var(--border-strong)" : "var(--border)"), color: menuActive ? "var(--text-primary)" : "var(--text-secondary)", transition: "all var(--dur-base) var(--ease-out)" }}>
              <i className="ph ph-list" style={{ fontSize: 18 }}></i>
            </button>
            {menuOpen && (
              <div style={{ position: "absolute", top: "calc(100% + 10px)", right: 0, minWidth: 216, background: "var(--surface-card)", border: "var(--border-width) solid var(--border)", borderRadius: 14, boxShadow: "var(--shadow-lg)", padding: 6, zIndex: 40 }}>
                <div style={{ fontSize: 10.5, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--text-tertiary)", fontWeight: 500, padding: "8px 12px 6px" }}>More from VELOUR</div>
                {menuItems.map((mi) => {
                  const active = section === mi.view;
                  return (
                    <a key={mi.label} href="#" onClick={pick(mi.view)}
                      onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = "var(--surface-sunken)"; }}
                      onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = "transparent"; }}
                      style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", borderRadius: 10, textDecoration: "none", color: active ? "var(--text-primary)" : "var(--text-secondary)", background: active ? "var(--surface-sunken)" : "transparent", fontSize: 14, fontWeight: active ? 500 : 400, transition: "background var(--dur-base) var(--ease-out)" }}>
                      <i className={`ph ph-${mi.icon}`} style={{ fontSize: 17, color: "var(--text-tertiary)" }}></i>
                      <span style={{ flex: 1 }}>{mi.label}</span>
                      {mi.locked && <i className="ph ph-lock-simple" title="Paid plan" style={{ fontSize: 13, opacity: 0.7 }}></i>}
                    </a>
                  );
                })}

                {isPaid && (
                  <React.Fragment>
                    <div style={{ height: 1, background: "var(--divider)", margin: "6px 8px" }}></div>
                    <div style={{ fontSize: 10.5, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--text-tertiary)", fontWeight: 500, padding: "6px 12px" }}>Membership</div>
                    <button onClick={openPortal} disabled={portalBusy}
                      onMouseEnter={(e) => { e.currentTarget.style.background = "var(--surface-sunken)"; }}
                      onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; }}
                      style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", borderRadius: 10, width: "100%", border: "none", background: "transparent", color: "var(--text-secondary)", fontFamily: "var(--font-sans)", fontSize: 14, cursor: portalBusy ? "default" : "pointer", textAlign: "left", opacity: portalBusy ? 0.6 : 1 }}>
                      <i className="ph ph-credit-card" style={{ fontSize: 17, color: "var(--text-tertiary)" }}></i>
                      <span style={{ flex: 1 }}>{portalBusy ? "One moment" : "Manage membership"}</span>
                    </button>
                    <div style={{ fontSize: 11.5, color: billingNote.ending ? "var(--terracotta-text, #8A4B28)" : "var(--text-tertiary)", padding: "4px 12px 8px", lineHeight: 1.45 }}>
                      {billingNote.text}
                    </div>
                  </React.Fragment>
                )}

                {/* WRITING TO US. A plain anchor to a mailto, not a button that
                    calls window.open — an anchor is a user gesture, so nothing
                    stands between a member and their mail client, and it is the
                    same reasoning that made the legal links anchors (see
                    velourLegalUrl). The address and the subject live in
                    _ds_bundle.js so this surface and the app cannot drift apart. */}
                <div style={{ height: 1, background: "var(--divider)", margin: "6px 8px" }}></div>
                <a href={window.velourFeedbackUrl ? window.velourFeedbackUrl("web") : "mailto:admin@tryvelour.com"}
                  onMouseEnter={(e) => { e.currentTarget.style.background = "var(--surface-sunken)"; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; }}
                  style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", borderRadius: 10, textDecoration: "none", color: "var(--text-secondary)", fontSize: 14, transition: "background var(--dur-base) var(--ease-out)" }}>
                  <i className="ph ph-paper-plane-tilt" style={{ fontSize: 17, color: "var(--text-tertiary)" }}></i>
                  <span style={{ flex: 1 }}>Write to us</span>
                </a>
                <div style={{ fontSize: 11.5, color: "var(--text-tertiary)", padding: "4px 12px 8px", lineHeight: 1.45 }}>
                  Tell us what is working and what is not. It opens your mail.
                </div>

                <div style={{ height: 1, background: "var(--divider)", margin: "6px 8px" }}></div>
                <div style={{ fontSize: 10.5, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--text-tertiary)", fontWeight: 500, padding: "6px 12px" }}>Your data</div>
                <button onClick={doSave}
                  onMouseEnter={(e) => { e.currentTarget.style.background = "var(--surface-sunken)"; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; }}
                  style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", borderRadius: 10, width: "100%", border: "none", background: "transparent", color: "var(--text-secondary)", fontFamily: "var(--font-sans)", fontSize: 14, cursor: "pointer", textAlign: "left" }}>
                  <i className="ph ph-download-simple" style={{ fontSize: 17, color: "var(--text-tertiary)" }}></i>
                  <span style={{ flex: 1 }}>Save a backup</span>
                </button>
                <button onClick={() => restoreRef.current && restoreRef.current.click()}
                  onMouseEnter={(e) => { e.currentTarget.style.background = "var(--surface-sunken)"; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; }}
                  style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", borderRadius: 10, width: "100%", border: "none", background: "transparent", color: "var(--text-secondary)", fontFamily: "var(--font-sans)", fontSize: 14, cursor: "pointer", textAlign: "left" }}>
                  <i className="ph ph-upload-simple" style={{ fontSize: 17, color: "var(--text-tertiary)" }}></i>
                  <span style={{ flex: 1 }}>Restore from a backup</span>
                </button>
                <input ref={restoreRef} type="file" accept="application/json,.json" style={{ display: "none" }}
                  onChange={(e) => { doRestore(e.target.files && e.target.files[0]); e.target.value = ""; }} />
                <div style={{ fontSize: 11.5, color: "var(--text-tertiary)", padding: "4px 12px 8px", lineHeight: 1.45 }}>
                  {backupNote || "Everything you add is kept in this browser. A backup is how it travels."}
                </div>
              </div>
            )}
          </div>

          {/* This said "Sign out" and only navigated home — the session survived,
              so the header still read "Your space", no "Sign in" door appeared,
              and there was no way to switch accounts in one browser at all. It
              signs out for real now. velourAuth.signOut() clears the session
              locally first and revokes server-side as best effort, because a
              sign-out that can fail is not a sign-out; velourSync then purges
              this device's copy of the account. */}
          <a href="#" title="Sign out"
            onClick={(e) => {
              e.preventDefault();
              const done = () => onNavigate && onNavigate("home");
              if (window.velourAuth) window.velourAuth.signOut().then(done).catch(done);
              else done();
            }}
            style={{ color: "var(--text-tertiary)", display: "flex" }}><i className="ph ph-sign-out" style={{ fontSize: 19 }}></i></a>
        </div>
      </div>
    </header>
  );
}

// Thin bar for dark surfaces.
function DarkBar({ pct, color }) {
  return (
    <div style={{ height: 6, borderRadius: 999, background: "rgba(247,244,239,0.14)", overflow: "hidden" }}>
      <div style={{ width: `${pct}%`, height: "100%", borderRadius: 999, background: color }}></div>
    </div>
  );
}

// Trend chip: direction up/steady, colored.
function Trend({ dir, label }) {
  const map = { up: { icon: "trend-up", color: "var(--teal-text)", bg: "var(--teal-fill)" }, good: { icon: "trend-up", color: "var(--sage-text)", bg: "var(--sage-fill)" }, steady: { icon: "minus", color: "var(--text-tertiary)", bg: "var(--surface-sunken)" }, watch: { icon: "trend-down", color: "var(--terracotta-text)", bg: "var(--terracotta-fill)" } };
  const m = map[dir] || map.steady;
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 12, fontWeight: 500, color: m.color, background: m.bg, borderRadius: 999, padding: "4px 10px", whiteSpace: "nowrap" }}>
      <i className={`ph ph-${m.icon}`} style={{ fontSize: 13 }}></i>{label}
    </span>
  );
}

Object.assign(window, { DashTopBar, DarkBar, Trend });
