// screens-admin-more.jsx — More menu + all secondary CRUD screens
//   Packages · Class types · Studios · Accounts · Payments · Reports

const { fmtIDR, findClass, findCoach } = window.NADI_HELPERS;

function AdminMoreScreen({ admin, openSection, onExitAdmin, showToast }) {
  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <div style={{ padding: "12px 22px 18px", display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12 }}>
        <div>
          <Eyebrow>more</Eyebrow>
          <h1 className="display stretch-in" style={{ fontSize: 38, marginTop: 12 }}>
            The <em style={{ fontStyle: "italic", color: "var(--primary)" }}>library</em>.
          </h1>
        </div>
        <Logo size={48} style={{ marginTop: 4 }} />
      </div>

      {/* Signed-in admin card */}
      <section style={{ padding: "0 22px 18px" }}>
        <div style={{ padding: 18, background: "var(--surface)", border: "1px solid var(--rule)", display: "flex", alignItems: "center", gap: 14 }}>
          <Avatar name={admin.name} initials={admin.initials} tone={admin.tone} size={48} />
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: "Newsreader, serif", fontSize: 18, color: "var(--ink)" }}>{admin.name}</div>
            <Mono color="var(--primary)">{admin.role.toLowerCase()} · {admin.email}</Mono>
          </div>
        </div>
      </section>

      {/* Main library sections */}
      <Section title="catalogue">
        <MoreRow icon="packages" label="Packages"     sub={`${window.NADI.PACKAGES.length} active`}     onClick={() => openSection("packages")} />
        <MoreRow icon="classes"  label="Class types"  sub={`${window.NADI.CLASS_TYPES.length} types`}    onClick={() => openSection("classes")} />
        <MoreRow icon="studios"  label="Studios"      sub={`${window.NADI.STUDIOS.length} rooms`}        onClick={() => openSection("studios")} />
      </Section>

      <Section title="money">
        <MoreRow icon="purchases" label="Pack purchases" sub={`${window.NADI_ADMIN.PACK_PURCHASES.filter((p) => p.status === "pending").length} awaiting confirmation`} onClick={() => openSection("purchases")} />
        <MoreRow icon="banks"     label="Bank accounts"  sub={`${window.NADI_ADMIN.BANK_ACCOUNTS.filter((b) => b.active).length} active · ${window.NADI_ADMIN.BANK_ACCOUNTS.length} total`} onClick={() => openSection("banks")} />
        <MoreRow icon="payments"  label="Payments"       sub={`${window.NADI_ADMIN.PAYMENTS.length} this week`} onClick={() => openSection("payments")} />
        <MoreRow icon="reports"   label="Reports"        sub="payouts, churn, fill rate"                          onClick={() => openSection("reports")} />
      </Section>

      <Section title="access">
        <MoreRow icon="accounts" label="Staff accounts" sub={`${window.NADI_ADMIN.ACCOUNTS.length} accounts · ${window.NADI_ADMIN.ROLES.length} roles`} onClick={() => openSection("accounts")} />
      </Section>

      <section style={{ padding: "10px 22px 40px" }}>
        <Button variant="dangerGhost" size="md" fullWidth onClick={onExitAdmin}>Exit staff mode</Button>
      </section>
    </div>
  );
}

function Section({ title, children }) {
  return (
    <section style={{ padding: "0 22px 22px" }}>
      <Eyebrow>{title}</Eyebrow>
      <div style={{ marginTop: 10, border: "1px solid var(--rule)" }}>{children}</div>
    </section>
  );
}

function MoreRow({ icon, label, sub, onClick }) {
  return (
    <button onClick={onClick} className="press" style={{
      width: "100%", textAlign: "left",
      background: "var(--bg)",
      padding: "16px 16px",
      display: "grid", gridTemplateColumns: "28px 1fr auto", gap: 14, alignItems: "center",
      borderBottom: "1px solid var(--rule)",
    }}>
      <MoreIcon id={icon} />
      <div>
        <div style={{ fontFamily: "Newsreader, serif", fontSize: 18, color: "var(--ink)" }}>{label}</div>
        <Mono>{sub}</Mono>
      </div>
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="var(--ink-soft)" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 2l5 5-5 5"/></svg>
    </button>
  );
}

function MoreIcon({ id }) {
  const p = { width: 20, height: 20, viewBox: "0 0 22 22", fill: "none", stroke: "var(--primary)", strokeWidth: 1.4, strokeLinecap: "round", strokeLinejoin: "round" };
  if (id === "packages") return <svg {...p}><path d="M11 2L3 6v10l8 4 8-4V6z"/><path d="M3 6l8 4 8-4M11 10v10"/></svg>;
  if (id === "classes") return <svg {...p}><rect x="3" y="3" width="7" height="7"/><rect x="12" y="3" width="7" height="7"/><rect x="3" y="12" width="7" height="7"/><rect x="12" y="12" width="7" height="7"/></svg>;
  if (id === "studios") return <svg {...p}><path d="M3 8l8-5 8 5v11H3z"/><path d="M9 19v-6h4v6"/></svg>;
  if (id === "payments") return <svg {...p}><rect x="2" y="6" width="18" height="11"/><path d="M2 10h18M5 14h3"/></svg>;
  if (id === "reports") return <svg {...p}><path d="M3 19V5M3 19h16"/><path d="M7 15v-4M11 15v-7M15 15v-2"/></svg>;
  if (id === "accounts") return <svg {...p}><circle cx="11" cy="8" r="3.5"/><path d="M4 19c1.4-3.6 4-5 7-5s5.6 1.4 7 5"/></svg>;
  if (id === "purchases") return <svg {...p}><path d="M3 7h16l-1.5 11H4.5z"/><path d="M8 7V5a3 3 0 016 0v2"/><path d="M9 12l2 2 3-3"/></svg>;
  if (id === "banks") return <svg {...p}><path d="M3 9l8-5 8 5"/><path d="M4 9v9M18 9v9M9 9v9M13 9v9"/><path d="M3 19h16"/></svg>;
  return null;
}

// ── PACKAGES CRUD ─────────────────────────────────────────────────
function AdminPackagesScreen({ onBack, showToast }) {
  const [editing, setEditing] = useState(null); // package or "new"
  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader title="Packages" back={onBack} onAdd={() => setEditing("new")} addLabel="+ new pack" />
      <div style={{ padding: "8px 22px 24px", display: "flex", flexDirection: "column", gap: 10 }}>
        {window.NADI.PACKAGES.map((p) => (
          <button key={p.id} onClick={() => setEditing(p)} className="press" style={{
            width: "100%", textAlign: "left",
            background: "var(--bg)", border: "1px solid var(--rule)",
            padding: 16,
            display: "grid", gridTemplateColumns: "1fr auto", gap: 12, alignItems: "center",
          }}>
            <div>
              {p.badge && <Mono color="var(--primary)">{p.badge.toLowerCase()}</Mono>}
              <div style={{ fontFamily: "Newsreader, serif", fontSize: 22, fontWeight: 400, marginTop: p.badge ? 4 : 0 }}>{p.name}</div>
              <Mono style={{ marginTop: 4 }}>{p.classes} class · valid {p.validityDays}d</Mono>
            </div>
            <div style={{ textAlign: "right" }}>
              <div style={{ fontFamily: "Newsreader, serif", fontSize: 18, color: "var(--ink)" }}>{fmtIDR(p.price)}</div>
              <Mono>edit →</Mono>
            </div>
          </button>
        ))}
      </div>
      <Sheet open={!!editing} onClose={() => setEditing(null)} maxHeight="90%">
        <PackageEditor pkg={editing === "new" ? null : editing} onClose={() => setEditing(null)} showToast={showToast} />
      </Sheet>
    </div>
  );
}

function PackageEditor({ pkg, onClose, showToast }) {
  const isNew = !pkg;
  const [name, setName] = useState(pkg?.name || "");
  const [classes, setClasses] = useState(pkg?.classes || 5);
  const [price, setPrice] = useState(pkg?.price || 750000);
  const [validity, setValidity] = useState(pkg?.validityDays || 30);
  const [badge, setBadge] = useState(pkg?.badge || "");

  return (
    <div style={{ padding: "10px 22px 26px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <Mono>{isNew ? "new pack" : `pack · #${pkg.id}`}</Mono>
        <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
      </div>
      <h2 className="display" style={{ fontSize: 32, marginTop: 12 }}>{isNew ? "New package." : pkg.name}</h2>

      <div style={{ marginTop: 22, display: "flex", flexDirection: "column", gap: 18 }}>
        <Field label="Name" value={name} onChange={setName} placeholder="e.g. Standard 5" />
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
          <Field label="Classes" value={classes} onChange={(v) => setClasses(parseInt(v, 10) || 0)} type="number" />
          <Field label="Validity (days)" value={validity} onChange={(v) => setValidity(parseInt(v, 10) || 0)} type="number" />
        </div>
        <Field label="Price (IDR)" value={price} onChange={(v) => setPrice(parseInt(v, 10) || 0)} type="number" />
        <div>
          <Mono>badge (optional)</Mono>
          <div style={{ display: "flex", gap: 6, marginTop: 8, flexWrap: "wrap" }}>
            {["","Most popular","Best value","First-timers"].map((b) => (
              <Chip key={b} active={badge === b} onClick={() => setBadge(b)}>{b ? b.toLowerCase() : "no badge"}</Chip>
            ))}
          </div>
        </div>
        <div style={{ padding: 14, background: "var(--surface)", border: "1px solid var(--rule)" }}>
          <Mono>preview</Mono>
          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8, alignItems: "baseline" }}>
            <span style={{ fontFamily: "Newsreader, serif", fontSize: 24 }}>{name || "Untitled"}</span>
            <span style={{ fontFamily: "Newsreader, serif", fontSize: 22, color: "var(--ink)" }}>{fmtIDR(price)}</span>
          </div>
          <Mono style={{ marginTop: 6, display: "block" }}>
            {classes} class{classes === 1 ? "" : "es"} · {fmtIDR(Math.round(price / Math.max(1, classes)))}/class · {validity}d valid
          </Mono>
        </div>
      </div>

      <div style={{ marginTop: 24, display: "flex", gap: 8 }}>
        <Button variant="ghost" size="md" fullWidth onClick={onClose}>Cancel</Button>
        <Button variant="primary" size="md" fullWidth onClick={async () => {
          const token = localStorage.getItem("nadi_token");
          if (!token) return;
          const payload = {
            name: name,
            classes: classes,
            price: price,
            validity_days: validity,
            badge: badge || null,
            desc: pkg?.desc || ""
          };
          try {
            const url = isNew ? "/api/admin/packages" : `/api/admin/packages/${pkg.id}`;
            const method = isNew ? "POST" : "PUT";
            const res = await fetch(url, {
              method: method,
              headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${token}`
              },
              body: JSON.stringify(payload)
            });
            if (res.ok) {
              showToast && showToast(isNew ? "Package created." : "Package saved.");
              if (window.NADI_RELOAD_PUBLIC) {
                await window.NADI_RELOAD_PUBLIC();
              }
              onClose();
            } else {
              const err = await res.json();
              showToast && showToast(err.detail || "Error saving package.");
            }
          } catch (e) {
            console.error(e);
            showToast && showToast("Error connecting to server.");
          }
        }}>{isNew ? "Create" : "Save"}</Button>
      </div>
      {!isNew && (
        <div style={{ marginTop: 14 }}>
          <Button variant="dangerGhost" size="sm" fullWidth onClick={async () => {
            const token = localStorage.getItem("nadi_token");
            if (!token) return;
            if (!confirm(`Are you sure you want to archive this package?`)) return;
            try {
              const res = await fetch(`/api/admin/packages/${pkg.id}`, {
                method: "DELETE",
                headers: {
                  "Authorization": `Bearer ${token}`
                }
              });
              if (res.ok) {
                showToast && showToast("Package archived.");
                if (window.NADI_RELOAD_PUBLIC) {
                  await window.NADI_RELOAD_PUBLIC();
                }
                onClose();
              } else {
                const err = await res.json();
                showToast && showToast(err.detail || "Error deleting package.");
              }
            } catch (e) {
              console.error(e);
              showToast && showToast("Error connecting to server.");
            }
          }}>Archive package</Button>
        </div>
      )}
    </div>
  );
}

// ── CLASS TYPES CRUD ─────────────────────────────────────────────
function AdminClassTypesScreen({ onBack, showToast }) {
  const [editing, setEditing] = useState(null);
  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader title="Class types" back={onBack} onAdd={() => setEditing("new")} addLabel="+ new class" />
      <div style={{ padding: "8px 22px 24px", display: "flex", flexDirection: "column", gap: 8 }}>
        {window.NADI.CLASS_TYPES.map((c) => {
          const accent = c.color === "primary" ? "var(--primary)" : c.color === "accent" ? "var(--accent)" : "var(--muted)";
          return (
            <button key={c.id} onClick={() => setEditing(c)} className="press" style={{
              width: "100%", textAlign: "left",
              padding: 16, background: "var(--bg)",
              border: "1px solid var(--rule)",
              borderLeft: `3px solid ${accent}`,
              display: "grid", gridTemplateColumns: "1fr auto", gap: 12, alignItems: "center",
            }}>
              <div>
                <div style={{ fontFamily: "Newsreader, serif", fontSize: 20, fontWeight: 400 }}>{c.name}</div>
                <Mono style={{ marginTop: 4 }}>{c.tagline.toLowerCase()}</Mono>
                <Mono style={{ marginTop: 4, display: "block" }}>{c.duration} min · {c.level.toLowerCase()}</Mono>
              </div>
              <Mono>edit →</Mono>
            </button>
          );
        })}
      </div>
      <Sheet open={!!editing} onClose={() => setEditing(null)} maxHeight="90%">
        <ClassEditor cls={editing === "new" ? null : editing} onClose={() => setEditing(null)} showToast={showToast} />
      </Sheet>
    </div>
  );
}

function ClassEditor({ cls, onClose, showToast }) {
  const isNew = !cls;
  const [name, setName] = useState(cls?.name || "");
  const [tagline, setTagline] = useState(cls?.tagline || "");
  const [duration, setDuration] = useState(cls?.duration || 60);
  const [level, setLevel] = useState(cls?.level || "All levels");
  const [color, setColor] = useState(cls?.color || "primary");
  return (
    <div style={{ padding: "10px 22px 26px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <Mono>{isNew ? "new class type" : `class type · #${cls.id}`}</Mono>
        <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
      </div>
      <h2 className="display" style={{ fontSize: 32, marginTop: 12 }}>{isNew ? "New class." : cls.name}</h2>

      <div style={{ marginTop: 22, display: "flex", flexDirection: "column", gap: 18 }}>
        <Field label="Name" value={name} onChange={setName} placeholder="e.g. Slow Flow" />
        <Field label="Tagline" value={tagline} onChange={setTagline} placeholder="One short phrase" />
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
          <Field label="Duration (min)" value={duration} onChange={(v) => setDuration(parseInt(v, 10) || 0)} type="number" />
          <div>
            <Mono>level</Mono>
            <div style={{ display: "flex", flexWrap: "wrap", gap: 4, marginTop: 8 }}>
              {["Beginner","All levels","Intermediate","Advanced"].map((l) => (
                <Chip key={l} active={level === l} onClick={() => setLevel(l)}>{l.toLowerCase()}</Chip>
              ))}
            </div>
          </div>
        </div>
        <div>
          <Mono>accent</Mono>
          <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
            {[["primary","Terracotta","var(--primary)"],["accent","Sage","var(--accent)"],["muted","Muted","var(--muted)"]].map(([id, lbl, c]) => (
              <button key={id} onClick={() => setColor(id)} className="press" style={{
                flex: 1, padding: "10px 12px",
                border: `1px solid ${color === id ? "var(--ink)" : "var(--rule)"}`,
                background: color === id ? "var(--surface)" : "transparent",
                display: "flex", alignItems: "center", gap: 8,
              }}>
                <span style={{ width: 14, height: 14, background: c }} />
                <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, textTransform: "lowercase" }}>{lbl.toLowerCase()}</span>
              </button>
            ))}
          </div>
        </div>
      </div>

      <div style={{ marginTop: 24, display: "flex", gap: 8 }}>
        <Button variant="ghost" size="md" fullWidth onClick={onClose}>Cancel</Button>
        <Button variant="primary" size="md" fullWidth onClick={async () => {
          const token = localStorage.getItem("nadi_token");
          if (!token) return;
          const payload = {
            name: name,
            tagline: tagline,
            duration: duration,
            level: level,
            color: color
          };
          try {
            const url = isNew ? "/api/admin/class-types" : `/api/admin/class-types/${cls.id}`;
            const method = isNew ? "POST" : "PUT";
            const res = await fetch(url, {
              method: method,
              headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${token}`
              },
              body: JSON.stringify(payload)
            });
            if (res.ok) {
              showToast && showToast(isNew ? "Class type added." : "Class type saved.");
              if (window.NADI_RELOAD_PUBLIC) {
                await window.NADI_RELOAD_PUBLIC();
              }
              onClose();
            } else {
              const err = await res.json();
              showToast && showToast(err.detail || "Error saving class type.");
            }
          } catch (e) {
            console.error(e);
            showToast && showToast("Error connecting to server.");
          }
        }}>{isNew ? "Create" : "Save"}</Button>
      </div>
      {!isNew && (
        <div style={{ marginTop: 14 }}>
          <Button variant="dangerGhost" size="sm" fullWidth onClick={async () => {
            const token = localStorage.getItem("nadi_token");
            if (!token) return;
            if (!confirm(`Are you sure you want to delete this class type?`)) return;
            try {
              const res = await fetch(`/api/admin/class-types/${cls.id}`, {
                method: "DELETE",
                headers: {
                  "Authorization": `Bearer ${token}`
                }
              });
              if (res.ok) {
                showToast && showToast("Class type archived.");
                if (window.NADI_RELOAD_PUBLIC) {
                  await window.NADI_RELOAD_PUBLIC();
                }
                onClose();
              } else {
                const err = await res.json();
                showToast && showToast(err.detail || "Error deleting class type.");
              }
            } catch (e) {
              console.error(e);
              showToast && showToast("Error connecting to server.");
            }
          }}>Archive</Button>
        </div>
      )}
    </div>
  );
}

// ── STUDIOS CRUD ─────────────────────────────────────────────────
function AdminStudiosScreen({ onBack, showToast }) {
  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader title="Studios" back={onBack} onAdd={() => showToast && showToast("Add studio dialog.")} addLabel="+ new room" />
      <div style={{ padding: "8px 22px 24px", display: "flex", flexDirection: "column", gap: 12 }}>
        {window.NADI.STUDIOS.map((s) => (
          <div key={s.id} style={{ padding: 18, background: "var(--bg)", border: "1px solid var(--rule)" }}>
            <Mono color="var(--primary)">studio {s.id}</Mono>
            <h3 style={{ fontFamily: "Newsreader, serif", fontSize: 26, fontWeight: 400, marginTop: 4 }}>{s.full}</h3>
            <p style={{ fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink-soft)", fontWeight: 300, marginTop: 6, lineHeight: 1.5 }}>{s.desc}.</p>
            <div style={{ marginTop: 14, display: "flex", gap: 8 }}>
              <Button variant="ghost" size="sm" onClick={() => showToast && showToast("Studio editor.")}>Edit</Button>
              <Button variant="ghost" size="sm" onClick={() => showToast && showToast("Studio closed for the day.")}>Close for the day</Button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── ACCOUNTS / ROLES ─────────────────────────────────────────────
function AdminAccountsScreen({ onBack, showToast }) {
  const { useState, useEffect } = React;
  const [tab, setTab] = useState("accounts");
  const [accounts, setAccounts] = useState(window.NADI_ADMIN.ACCOUNTS || []);
  const [loading, setLoading] = useState(true);
  const [editMode, setEditMode] = useState(false);
  const [editingAccount, setEditingAccount] = useState(null);
  const [promoteOpen, setPromoteOpen] = useState(false);

  const fetchAccounts = async () => {
    const token = localStorage.getItem("nadi_token");
    const headers = token ? { "Authorization": `Bearer ${token}` } : {};
    try {
      const res = await fetch("/api/admin/accounts", { headers });
      if (res.ok) {
        const data = await res.json();
        setAccounts(data);
        // Sync with global namespace
        window.NADI_ADMIN.ACCOUNTS = data.map(a => {
          const names = (a.name || "Staff").split(" ");
          const initials = names.map(n => n[0]).slice(0, 2).join("").toUpperCase();
          const staffRoles = a.roles ? a.roles.filter(r => r !== "Member") : [a.role || "Member"];
          return {
            id: a.id,
            name: a.name,
            email: a.email,
            role: staffRoles.length > 0 ? staffRoles.join(", ") : "Member",
            roles: a.roles || [a.role || "Member"],
            status: a.status || "active",
            lastActive: "Just now",
            initials: initials,
            tone: "#C28464"
          };
        });
      }
    } catch (e) {
      console.error("Failed to fetch accounts", e);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchAccounts();
  }, []);

  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader
        title="Staff"
        back={onBack}
        onAdd={() => setEditMode(!editMode)}
        addLabel={editMode ? "Done" : "Edit"}
      />
      <div style={{ padding: "0 22px 12px" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", border: "1px solid var(--rule)" }}>
          {[["accounts","Accounts"],["roles","Roles"]].map(([id, label]) => (
            <button key={id} onClick={() => setTab(id)} className="press" style={{
              padding: "10px 8px",
              background: tab === id ? "var(--ink)" : "transparent",
              color: tab === id ? "var(--bg)" : "var(--ink-soft)",
              fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase",
            }}>{label}</button>
          ))}
        </div>
      </div>
      <div style={{ padding: "12px 22px 24px" }}>
        {tab === "accounts" ? (
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            <Button
              variant="ghost"
              size="md"
              fullWidth
              onClick={() => setPromoteOpen(true)}
              style={{
                marginBottom: 6,
                borderColor: "var(--primary)",
                color: "var(--primary)",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                gap: 8,
              }}
            >
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
              Promote Member to Staff
            </Button>

            {accounts.filter(a => a.roles ? a.roles.some(r => r !== "Member") : a.role !== "Member").map((a) => {
              const names = (a.name || "Staff").split(" ");
              const initials = names.map(n => n[0]).slice(0, 2).join("").toUpperCase();
              return (
                <button key={a.id} onClick={() => {
                  if (editMode) {
                    setEditingAccount(a);
                  } else {
                    showToast && showToast(`${a.name} is ${a.role || (a.roles && a.roles.join(', ')) || "Member"}. Click Edit to assign/change roles.`);
                  }
                }} className="press" style={{
                  width: "100%", textAlign: "left",
                  background: "var(--bg)", border: "1px solid var(--rule)",
                  padding: 16,
                  display: "grid", gridTemplateColumns: "40px 1fr auto", gap: 12, alignItems: "center",
                }}>
                  <Avatar name={a.name} initials={initials} tone="#C28464" size={40} />
                  <div>
                    <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>{a.name}</div>
                    <Mono style={{ display: "block" }}>{a.email} · {a.status || "active"}</Mono>
                    {a.roles && a.roles.filter(r => r !== "Member").length > 0 && (
                      <Mono style={{ display: "block", color: "var(--primary)", marginTop: 2 }}>
                        roles: {a.roles.filter(r => r !== "Member").join(", ").toLowerCase()}
                      </Mono>
                    )}
                  </div>
                  {editMode ? (
                    <span style={{
                      padding: "3px 8px",
                      border: "1px solid var(--primary)",
                      background: "var(--primary)",
                      color: "var(--primary-ink)",
                      fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5,
                      letterSpacing: "0.08em", textTransform: "uppercase",
                    }}>edit →</span>
                  ) : (
                    <span style={{
                      padding: "3px 8px",
                      border: "1px solid var(--rule-strong)",
                      fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5,
                      letterSpacing: "0.08em", textTransform: "uppercase",
                      color: "var(--ink-soft)",
                    }}>{(() => {
                      const staffRoles = a.roles ? a.roles.filter(r => r !== "Member") : [];
                      if (staffRoles.includes("Owner")) return "Owner";
                      if (staffRoles.includes("Manager")) return "Manager";
                      if (staffRoles.includes("Front Desk")) return "Front Desk";
                      if (staffRoles.includes("Coach")) return "Coach";
                      return a.role || "Member";
                    })()}</span>
                  )}
                </button>
              );
            })}
          </div>
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {window.NADI_ADMIN.ROLES.map((r) => (
              <div key={r.name} style={{ padding: 16, background: "var(--bg)", border: "1px solid var(--rule)" }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                  <h3 style={{ fontFamily: "Newsreader, serif", fontSize: 20, fontWeight: 400 }}>{r.name}</h3>
                  <Mono>{r.scope.toLowerCase()}</Mono>
                </div>
                <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", gap: 4 }}>
                  {r.perms.map((p) => (
                    <span key={p} style={{
                      padding: "3px 8px", border: "1px solid var(--rule)",
                      fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5,
                      letterSpacing: "0.04em", textTransform: "lowercase", color: "var(--ink-soft)",
                    }}>{p.toLowerCase()}</span>
                  ))}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      <Sheet open={!!editingAccount} onClose={() => setEditingAccount(null)} maxHeight="90%">
        {editingAccount && (
          <StaffEditor
            account={editingAccount}
            onClose={() => setEditingAccount(null)}
            onSave={fetchAccounts}
            showToast={showToast}
          />
        )}
      </Sheet>

      <Sheet open={promoteOpen} onClose={() => setPromoteOpen(false)} maxHeight="90%">
        <PromoteMemberSheet
          accounts={accounts}
          onClose={() => setPromoteOpen(false)}
          onPromote={(member) => {
            setPromoteOpen(false);
            setEditingAccount(member);
          }}
        />
      </Sheet>
    </div>
  );
}

function PromoteMemberSheet({ accounts, onClose, onPromote }) {
  const { useState } = React;
  const [query, setQuery] = useState("");

  const membersOnly = accounts.filter(a => 
    a.roles ? !a.roles.some(r => r !== "Member") : a.role === "Member"
  );

  const filtered = query
    ? membersOnly.filter(m =>
        (m.name || "").toLowerCase().includes(query.toLowerCase()) ||
        (m.email || "").toLowerCase().includes(query.toLowerCase())
      )
    : membersOnly;

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", padding: "8px 22px 22px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 18 }}>
        <h2 style={{ fontFamily: "Newsreader, serif", fontSize: 24, fontWeight: 400 }}>Promote Member</h2>
        <button onClick={onClose} className="press" style={{ background: "transparent", border: 0, padding: 6 }}>
          <Mono>close ×</Mono>
        </button>
      </div>

      <div style={{ position: "relative", marginBottom: 16 }}>
        <input
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Search registered members..."
          style={{
            width: "100%", padding: "12px 14px 12px 36px",
            border: "1px solid var(--rule)", background: "var(--bg)",
            fontFamily: "Geist, sans-serif", fontSize: 14, color: "var(--ink)",
          }}
        />
        <span style={{ position: "absolute", left: 12, top: "50%", transform: "translateY(-50%)", display: "flex" }}>
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="var(--ink-soft)" strokeWidth="1.4"><circle cx="6" cy="6" r="4.5"/><path d="M10 10l3 3"/></svg>
        </span>
      </div>

      <div style={{ flex: 1, overflowY: "auto", display: "flex", flexDirection: "column", gap: 10, maxHeight: "60vh" }} className="scroll">
        {filtered.map((user) => {
          const names = (user.name || "Member").split(" ");
          const initials = names.map(n => n[0]).slice(0, 2).join("").toUpperCase();
          return (
            <button
              key={user.id}
              onClick={() => onPromote(user)}
              className="press"
              style={{
                width: "100%", textAlign: "left",
                background: "var(--bg)", border: "1px solid var(--rule)",
                padding: 16,
                display: "grid", gridTemplateColumns: "40px 1fr auto", gap: 12, alignItems: "center",
              }}
            >
              <Avatar name={user.name} initials={initials} tone="#C28464" size={40} />
              <div>
                <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>{user.name}</div>
                <Mono>{user.email}</Mono>
              </div>
              <span style={{
                padding: "3px 8px",
                border: "1px solid var(--primary)",
                background: "var(--primary)",
                color: "var(--primary-ink)",
                fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5,
                letterSpacing: "0.08em", textTransform: "uppercase",
              }}>Promote →</span>
            </button>
          );
        })}
        {filtered.length === 0 && (
          <Mono style={{ padding: "16px 0", display: "block", textAlign: "center" }}>
            No registered members found{query ? ` matching "${query}"` : ""}.
          </Mono>
        )}
      </div>
    </div>
  );
}

function StaffEditor({ account, onClose, onSave, showToast }) {
  const { useState } = React;
  const [roles, setRoles] = useState(account.roles || [account.role || "Member"]);
  const [status, setStatus] = useState(account.status || "active");
  const [saving, setSaving] = useState(false);

  const handleSave = async () => {
    setSaving(true);
    const token = localStorage.getItem("nadi_token");
    if (token) {
      try {
        const res = await fetch(`/api/admin/accounts/${account.id}`, {
          method: "PUT",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${token}`
          },
          body: JSON.stringify({
            roles,
            status
          })
        });
        if (res.ok) {
          showToast && showToast("Staff account updated.");
          onSave && onSave();
          onClose();
        } else {
          const err = await res.json();
          showToast && showToast(err.detail || "Failed to update account.");
        }
      } catch (e) {
        console.error(e);
        showToast && showToast("Error updating account.");
      } finally {
        setSaving(false);
      }
    } else {
      // Fallback for mock mode (e.g. Nadi revamp)
      account.roles = roles;
      account.role = roles[0];
      account.status = status;
      showToast && showToast("Staff account updated (mock).");
      onSave && onSave();
      onClose();
    }
  };

  const toggleRole = (r) => {
    if (roles.includes(r)) {
      if (roles.length > 1) {
        setRoles(roles.filter(x => x !== r));
      } else {
        showToast && showToast("At least one role is required.");
      }
    } else {
      setRoles([...roles, r]);
    }
  };

  return (
    <div style={{ padding: "10px 22px 26px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <Mono>edit staff</Mono>
        <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
      </div>
      <h2 className="display" style={{ fontSize: 32, marginTop: 12 }}>{account.name}</h2>
      <Mono style={{ display: "block", marginTop: 4 }}>{account.email}</Mono>

      <div style={{ marginTop: 22, display: "flex", flexDirection: "column", gap: 18 }}>
        <div>
          <Mono style={{ marginBottom: 8, display: "block" }}>Assign Roles</Mono>
          <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {["Owner", "Manager", "Front Desk", "Coach"].map((r) => {
              const active = roles.includes(r);
              return (
                <button
                  key={r}
                  onClick={() => toggleRole(r)}
                  className="press"
                  style={{
                    padding: 12,
                    background: active ? "var(--ink)" : "var(--bg)",
                    color: active ? "var(--bg)" : "var(--ink)",
                    border: "1px solid var(--rule)",
                    textAlign: "left",
                    fontFamily: "Geist, sans-serif",
                    fontSize: 14,
                    display: "flex",
                    justifyContent: "space-between",
                    alignItems: "center"
                  }}
                >
                  <span>{r}</span>
                  {active && <span style={{ fontFamily: "monospace" }}>[x]</span>}
                </button>
              );
            })}
          </div>
        </div>

        <div>
          <Mono style={{ marginBottom: 8, display: "block" }}>Status</Mono>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
            {["active", "inactive"].map((st) => {
              const active = status === st;
              return (
                <button
                  key={st}
                  onClick={() => setStatus(st)}
                  className="press"
                  style={{
                    padding: 10,
                    background: active ? "var(--ink)" : "var(--bg)",
                    color: active ? "var(--bg)" : "var(--ink)",
                    border: "1px solid var(--rule)",
                    textAlign: "center",
                    fontFamily: "JetBrains Mono, monospace",
                    fontSize: 11,
                    textTransform: "uppercase"
                  }}
                >
                  {st}
                </button>
              );
            })}
          </div>
        </div>
      </div>

      <div style={{ marginTop: 28, display: "flex", gap: 8 }}>
        <Button variant="ghost" size="md" fullWidth onClick={onClose}>Cancel</Button>
        <Button variant="primary" size="md" fullWidth onClick={handleSave} disabled={saving}>
          {saving ? "Saving..." : "Save"}
        </Button>
      </div>
    </div>
  );
}

// ── PAYMENTS ─────────────────────────────────────────────────────
function AdminPaymentsScreen({ onBack, openMember }) {
  const total = window.NADI_ADMIN.PAYMENTS.reduce((s, p) => s + p.amount, 0);
  // group by date
  const byDate = {};
  window.NADI_ADMIN.PAYMENTS.forEach((p) => { (byDate[p.date] = byDate[p.date] || []).push(p); });
  const dates = Object.keys(byDate).sort().reverse();
  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader title="Payments" back={onBack} />
      <div style={{ padding: "0 22px 16px" }}>
        <div style={{ padding: 18, background: "var(--ink)", color: "var(--bg)" }}>
          <Mono color="rgba(248,241,225,0.6)">past 7 days</Mono>
          <div className="display" style={{ fontSize: 42, color: "#E8A07F", marginTop: 6, letterSpacing: "-0.025em" }}>{fmtIDR(total)}</div>
          <Mono color="rgba(248,241,225,0.6)" style={{ marginTop: 6, display: "block" }}>{window.NADI_ADMIN.PAYMENTS.length} payments</Mono>
        </div>
      </div>
      <div style={{ padding: "0 22px 24px" }}>
        {dates.map((d) => {
          const dayTotal = byDate[d].reduce((s, p) => s + p.amount, 0);
          return (
            <div key={d} style={{ marginBottom: 18 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 8 }}>
                <Mono>{new Date(d).toLocaleDateString("en-GB", { weekday: "short", day: "2-digit", month: "short" }).toLowerCase()}</Mono>
                <Mono>{fmtIDR(dayTotal)}</Mono>
              </div>
              <div style={{ borderTop: "1px solid var(--rule)" }}>
                {byDate[d].map((p) => {
                  const m = window.NADI_ADMIN.findMember(p.memberId);
                  return (
                    <button key={p.id} onClick={() => m && openMember(m)} className="press" style={{
                      width: "100%", textAlign: "left",
                      padding: "12px 0",
                      borderBottom: "1px solid var(--rule)",
                      display: "grid", gridTemplateColumns: "44px 1fr auto", gap: 12, alignItems: "center",
                      background: "transparent",
                    }}>
                      {m ? <Avatar name={m.name} initials={m.initials} tone={m.tone} size={32} /> : <span />}
                      <div>
                        <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>{p.member}</div>
                        <Mono>{p.item} · {p.time} · {p.method.toLowerCase()}</Mono>
                      </div>
                      <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>{fmtIDR(p.amount)}</div>
                    </button>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ── REPORTS (payouts, churn, fill rate) ──────────────────────────
function AdminReportsScreen({ onBack, openCoach, openMember }) {
  const payments = window.NADI_ADMIN.PAYMENTS || [];
  const weekRevenue = payments.reduce((s, p) => s + p.amount, 0);

  const sessions = window.NADI.SCHEDULE || [];
  const totalBooked = sessions.reduce((s, x) => s + (x.booked || 0), 0);
  const totalCapacity = sessions.reduce((s, x) => s + (x.capacity || 14), 0);
  const fillRate = totalCapacity > 0 ? Math.round((totalBooked / totalCapacity) * 100) : 78;

  const members = window.NADI_ADMIN.MEMBERS || [];
  const newMembersCount = members.filter((m) => m.status === "new" || m.status === "New").length || 2;

  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader title="Reports" back={onBack} />
      <div style={{ padding: "0 22px 24px", display: "flex", flexDirection: "column", gap: 26 }}>

        {/* Weekly */}
        <section>
          <Eyebrow>this week</Eyebrow>
          <div style={{ marginTop: 10, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1, background: "var(--rule)", border: "1px solid var(--rule)" }}>
            <SmallStat label="revenue" value={(weekRevenue / 1000000).toFixed(1) + "M"} suffix={`rp · ${fmtIDR(weekRevenue)} total`} accent />
            <SmallStat label="fill rate" value={`${fillRate}%`} suffix="of capacity" />
            <SmallStat label="new members" value={newMembersCount} suffix="this week" />
            <SmallStat label="cancellations" value={3} suffix="3% of bookings" />
          </div>
        </section>

        {/* Coach payouts */}
        <section>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 12 }}>
            <Eyebrow>coach payouts · {new Date().toLocaleDateString("en-GB", { month: "short" }).toLowerCase()}</Eyebrow>
            <Mono color="var(--primary)">{fmtIDR(window.NADI_ADMIN.PAYOUTS.filter((p) => !p.paid).reduce((s, p) => {
              const co = findCoach(p.coachId);
              const currentRate = (co && co.rate) || p.rate || 200000;
              return s + (p.classes * currentRate);
            }, 0))} owed</Mono>
          </div>
          <div style={{ border: "1px solid var(--rule)" }}>
            {window.NADI_ADMIN.PAYOUTS.map((p, i) => {
              const co = findCoach(p.coachId) || { name: "Unknown", rate: 200000 };
              const currentRate = co.rate || p.rate || 200000;
              const currentTotal = p.classes * currentRate;
              return (
                <button key={p.coachId} onClick={() => openCoach(co)} className="press" style={{
                  width: "100%", textAlign: "left",
                  padding: "12px 16px",
                  borderBottom: i < window.NADI_ADMIN.PAYOUTS.length - 1 ? "1px solid var(--rule)" : "none",
                  display: "grid", gridTemplateColumns: "36px 1fr auto", gap: 12, alignItems: "center",
                  background: "var(--bg)",
                }}>
                  <Avatar name={co.name} initials={co.initials} tone={co.tone} size={36} />
                  <div>
                    <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>{co.name}</div>
                    <Mono>{p.classes} classes · {p.hours}h</Mono>
                  </div>
                  <div style={{ textAlign: "right" }}>
                    <div style={{ fontFamily: "Newsreader, serif", fontSize: 16 }}>{fmtIDR(currentTotal)}</div>
                    <Mono color={p.paid ? "var(--accent)" : "var(--primary)"}>{p.paid ? "paid" : "owed"}</Mono>
                  </div>
                </button>
              );
            })}
          </div>
        </section>

        {/* Churn */}
        <section>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 12 }}>
            <Eyebrow color="var(--primary)">churn watch</Eyebrow>
            <Mono>{window.NADI_ADMIN.CHURN_LIST.length} members lapsed</Mono>
          </div>
          <div style={{ border: "1px solid var(--rule)" }}>
            {window.NADI_ADMIN.CHURN_LIST.map((m, i) => (
              <button key={m.id} onClick={() => openMember(m)} className="press" style={{
                width: "100%", textAlign: "left",
                padding: "12px 16px",
                borderBottom: i < window.NADI_ADMIN.CHURN_LIST.length - 1 ? "1px solid var(--rule)" : "none",
                display: "grid", gridTemplateColumns: "36px 1fr auto", gap: 12, alignItems: "center",
                background: "var(--bg)",
              }}>
                <Avatar name={m.name} initials={m.initials} tone={m.tone} size={36} />
                <div>
                  <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>{m.name}</div>
                  <Mono>last seen {m.lastVisit.toLowerCase()} · {m.visits} lifetime</Mono>
                </div>
                <Mono color="var(--primary)">{m.daysSinceVisit}d ago</Mono>
              </button>
            ))}
          </div>
        </section>

        {/* Class fill rate */}
        <section>
          <Eyebrow>fill rate · by class</Eyebrow>
          <div style={{ marginTop: 12, padding: 16, background: "var(--bg)", border: "1px solid var(--rule)" }}>
            {window.NADI.CLASS_TYPES.slice(0, 6).map((c, i) => {
              const sessions = window.NADI.SCHEDULE.filter((s) => s.classId === c.id);
              if (sessions.length === 0) return null;
              const booked = sessions.reduce((s, x) => s + x.booked, 0);
              const cap = sessions.reduce((s, x) => s + x.capacity, 0);
              const pct = Math.round((booked / cap) * 100);
              return (
                <div key={c.id} style={{ padding: "10px 0", borderBottom: i < 5 ? "1px solid var(--rule)" : "none" }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                    <span style={{ fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink)" }}>{c.name}</span>
                    <Mono color={pct > 85 ? "var(--primary)" : "var(--ink-soft)"}>{pct}%</Mono>
                  </div>
                  <div style={{ marginTop: 6, height: 3, background: "var(--surface-2)", position: "relative" }}>
                    <div style={{ position: "absolute", left: 0, top: 0, bottom: 0, width: `${pct}%`, background: pct > 85 ? "var(--primary)" : "var(--accent)" }} />
                  </div>
                </div>
              );
            })}
          </div>
        </section>
      </div>
    </div>
  );
}

// ── BANK ACCOUNTS CRUD ──────────────────────────────────────────
function AdminBankAccountsScreen({ onBack, showToast }) {
  const [, force] = useState(0);
  const [editing, setEditing] = useState(null); // bank or "new"
  const banks = window.NADI_ADMIN.BANK_ACCOUNTS;

  const toggleActive = (b) => {
    b.active = !b.active;
    force((n) => n + 1);
    showToast && showToast(b.active ? `${b.bank} enabled.` : `${b.bank} hidden from members.`);
  };

  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader title="Bank accounts" back={onBack} onAdd={() => setEditing("new")} addLabel="+ new account" />
      <div style={{ padding: "8px 22px 14px" }}>
        <p style={{ fontFamily: "Newsreader, serif", fontSize: 14, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5 }}>
          Accounts marked active appear in the members' bank-transfer checkout. Inactive accounts are kept on file but hidden.
        </p>
      </div>
      <div style={{ padding: "0 22px 24px", display: "flex", flexDirection: "column", gap: 10 }}>
        {banks.map((b) => (
          <div key={b.id} style={{
            background: "var(--bg)", border: "1px solid var(--rule)",
            opacity: b.active ? 1 : 0.7,
          }}>
            <button onClick={() => setEditing(b)} className="press" style={{
              width: "100%", textAlign: "left", background: "transparent",
              padding: 16,
              display: "grid", gridTemplateColumns: "1fr auto", gap: 12, alignItems: "center",
              borderBottom: "1px solid var(--rule)",
            }}>
              <div>
                <div style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
                  <div style={{ fontFamily: "Newsreader, serif", fontSize: 20, fontWeight: 400, color: "var(--ink)" }}>{b.bank}</div>
                  {!b.active && (
                    <span style={{
                      padding: "2px 6px", border: "1px solid var(--rule-strong)",
                      fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5,
                      letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink-soft)",
                    }}>inactive</span>
                  )}
                </div>
                <div style={{
                  marginTop: 4,
                  fontFamily: "'JetBrains Mono', monospace", fontSize: 13,
                  color: "var(--ink)", letterSpacing: "0.04em",
                }}>{b.number}</div>
                <Mono style={{ marginTop: 4, display: "block" }}>a/n {b.name.toLowerCase()} · {b.branch.toLowerCase()}</Mono>
              </div>
              <Mono>edit →</Mono>
            </button>
            <div style={{ padding: "10px 16px", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }}>
              <Mono>{b.active ? "shown to members" : "hidden from members"}</Mono>
              <button onClick={() => toggleActive(b)} className="press" style={{
                padding: "6px 10px", border: "1px solid var(--rule)",
                background: b.active ? "var(--surface)" : "var(--ink)",
                color: b.active ? "var(--ink)" : "var(--bg)",
                fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
                letterSpacing: "0.08em", textTransform: "uppercase",
              }}>{b.active ? "deactivate" : "activate"}</button>
            </div>
          </div>
        ))}
      </div>
      <Sheet open={!!editing} onClose={() => setEditing(null)} maxHeight="90%">
        <BankAccountEditor bank={editing === "new" ? null : editing} onClose={() => setEditing(null)} showToast={showToast} />
      </Sheet>
    </div>
  );
}

function BankAccountEditor({ bank, onClose, showToast }) {
  const isNew = !bank;
  const [bankName, setBankName] = useState(bank?.bank || "");
  const [name, setName] = useState(bank?.name || "Nadi Yoga Studio");
  const [number, setNumber] = useState(bank?.number || "");
  const [branch, setBranch] = useState(bank?.branch || "Tangerang");
  const [active, setActive] = useState(bank ? !!bank.active : true);

  const save = () => {
    if (isNew) {
      const id = "b" + (window.NADI_ADMIN.BANK_ACCOUNTS.length + 1);
      window.NADI_ADMIN.BANK_ACCOUNTS.push({ id, bank: bankName, name, number, branch, active });
      showToast && showToast("Bank account added.");
    } else {
      bank.bank = bankName; bank.name = name; bank.number = number; bank.branch = branch; bank.active = active;
      showToast && showToast("Bank account saved.");
    }
    onClose();
  };

  const archive = () => {
    if (!bank) return;
    const list = window.NADI_ADMIN.BANK_ACCOUNTS;
    const i = list.indexOf(bank);
    if (i >= 0) list.splice(i, 1);
    showToast && showToast("Bank account removed.");
    onClose();
  };

  return (
    <div style={{ padding: "10px 22px 26px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <Mono>{isNew ? "new account" : `bank · #${bank.id}`}</Mono>
        <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
      </div>
      <h2 className="display" style={{ fontSize: 32, marginTop: 12 }}>{isNew ? "New account." : bank.bank}</h2>

      <div style={{ marginTop: 22, display: "flex", flexDirection: "column", gap: 18 }}>
        <div>
          <Mono>bank</Mono>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: 8 }}>
            {["BCA","Mandiri","BNI","BRI","Permata","CIMB","OCBC","Jago"].map((bnk) => (
              <Chip key={bnk} active={bankName === bnk} onClick={() => setBankName(bnk)}>{bnk.toLowerCase()}</Chip>
            ))}
          </div>
          <input value={bankName} onChange={(e) => setBankName(e.target.value)} placeholder="bank name"
            style={{
              marginTop: 10, width: "100%", padding: "10px 12px",
              border: "1px solid var(--rule)", background: "var(--bg)",
              fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink)",
            }} />
        </div>
        <Field label="Account holder" value={name} onChange={setName} placeholder="e.g. Nadi Yoga Studio" />
        <Field label="Account number" value={number} onChange={setNumber} placeholder="0000 0000 0000" />
        <Field label="Branch / city" value={branch} onChange={setBranch} placeholder="Tangerang" />

        <div style={{ padding: 14, background: "var(--surface)", border: "1px solid var(--rule)" }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }}>
            <div>
              <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>Active</div>
              <Mono>shown to members on checkout</Mono>
            </div>
            <ToggleSwitch defaultOn={active} key={String(active)} onChange={setActive} />
          </div>
        </div>

        <div style={{ padding: 14, background: "var(--bg)", border: "1px solid var(--rule)" }}>
          <Mono>member preview</Mono>
          <div style={{ marginTop: 8, display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 10 }}>
            <div style={{ fontFamily: "Newsreader, serif", fontSize: 18, color: "var(--ink)" }}>{bankName || "Bank"}</div>
            <Mono>{(branch || "—").toLowerCase()}</Mono>
          </div>
          <div style={{
            marginTop: 6, fontFamily: "'JetBrains Mono', monospace", fontSize: 14,
            color: "var(--ink)", letterSpacing: "0.04em",
          }}>{number || "0000 0000 0000"}</div>
          <Mono style={{ marginTop: 4, display: "block" }}>a/n {(name || "—").toLowerCase()}</Mono>
        </div>
      </div>

      <div style={{ marginTop: 24, display: "flex", gap: 8 }}>
        <Button variant="ghost" size="md" fullWidth onClick={onClose}>Cancel</Button>
        <Button variant="primary" size="md" fullWidth onClick={save}>{isNew ? "Create" : "Save"}</Button>
      </div>
      {!isNew && (
        <div style={{ marginTop: 14 }}>
          <Button variant="dangerGhost" size="sm" fullWidth onClick={archive}>Remove account</Button>
        </div>
      )}
    </div>
  );
}

// ── PACK PURCHASES CONFIRMATION ─────────────────────────────────
function AdminPackPurchasesScreen({ onBack, openMember, showToast }) {
  const [, force] = useState(0);
  const [tab, setTab] = useState("pending");
  const [reviewing, setReviewing] = useState(null);
  const list = window.NADI_ADMIN.PACK_PURCHASES;
  const filtered = list.filter((p) => p.status === tab || (tab === "pending" && p.status === "pending"));
  const tabs = [
    { id: "pending",   label: "Pending",   n: list.filter((p) => p.status === "pending").length },
    { id: "confirmed", label: "Confirmed", n: list.filter((p) => p.status === "confirmed").length },
    { id: "rejected",  label: "Rejected",  n: list.filter((p) => p.status === "rejected").length },
  ];

  const update = async (purchase, status) => {
    const token = localStorage.getItem("nadi_token");
    if (!token) return;
    try {
      const action = status === "confirmed" ? "confirm" : "reject";
      const res = await fetch(`/api/admin/payments/${purchase.id}/${action}`, {
        method: "POST",
        headers: { "Authorization": `Bearer ${token}` }
      });
      if (res.ok) {
        if (window.NADI_RELOAD_ADMIN_DATA) {
          await window.NADI_RELOAD_ADMIN_DATA();
        } else {
          purchase.status = status;
          purchase.decidedAt = new Date().toISOString().replace("T", " ").slice(0, 16);
        }
        force((n) => n + 1);
        setReviewing(null);
        showToast && showToast(
          status === "confirmed" ? `${purchase.packageName} confirmed for ${purchase.memberName.split(" ")[0]}.`
          : status === "rejected" ? `Purchase rejected.` : `Updated.`
        );
      } else {
        const err = await res.json();
        showToast && showToast(err.detail || "Action failed.");
      }
    } catch (e) {
      console.error(e);
      showToast && showToast("Error connecting to server.");
    }
  };

  return (
    <div className="screen-fade scroll" style={{ flex: 1 }}>
      <SubHeader title="Pack purchases" back={onBack} />

      <div style={{ padding: "0 22px 12px" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", border: "1px solid var(--rule)" }}>
          {tabs.map((tb) => (
            <button key={tb.id} onClick={() => setTab(tb.id)} className="press" style={{
              padding: "10px 6px",
              background: tab === tb.id ? "var(--ink)" : "transparent",
              color: tab === tb.id ? "var(--bg)" : "var(--ink-soft)",
              fontFamily: "'JetBrains Mono', monospace", fontSize: 10.5,
              letterSpacing: "0.1em", textTransform: "uppercase",
              display: "flex", alignItems: "center", justifyContent: "center", gap: 6,
            }}>
              <span>{tb.label}</span>
              <span style={{
                padding: "1px 6px", borderRadius: 8,
                background: tab === tb.id ? "var(--primary)" : "var(--rule)",
                color: tab === tb.id ? "var(--primary-ink)" : "var(--ink)",
                fontSize: 9,
              }}>{tb.n}</span>
            </button>
          ))}
        </div>
      </div>

      <div style={{ padding: "8px 22px 24px", display: "flex", flexDirection: "column", gap: 10 }}>
        {filtered.length === 0 && (
          <div style={{ padding: 26, textAlign: "center", border: "1px dashed var(--rule)" }}>
            <Mono>no {tab} purchases</Mono>
          </div>
        )}
        {filtered.map((p) => {
          const member = window.NADI_ADMIN.findMember(p.memberId);
          const bank = (window.NADI_ADMIN.BANK_ACCOUNTS || []).find((b) => b.id === p.bankId);
          return (
            <button key={p.id} onClick={() => setReviewing(p)} className="press" style={{
              width: "100%", textAlign: "left",
              background: "var(--bg)", border: "1px solid var(--rule)",
              padding: 16,
              display: "grid", gridTemplateColumns: "40px 1fr auto", gap: 12, alignItems: "center",
            }}>
              {member ? <Avatar name={member.name} initials={member.initials} tone={member.tone} size={40} /> : <span />}
              <div style={{ minWidth: 0 }}>
                <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>{p.memberName}</div>
                <Mono style={{ display: "block", marginTop: 2 }}>
                  {p.packageName} · {bank ? bank.bank.toLowerCase() : "any bank"} · {p.submitted.split(" ")[1]}
                </Mono>
              </div>
              <div style={{ textAlign: "right" }}>
                <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>{fmtIDR(p.amount)}</div>
                <Mono color={p.status === "pending" ? "var(--primary)" : p.status === "confirmed" ? "var(--accent)" : "var(--ink-soft)"}>
                  {p.status}
                </Mono>
              </div>
            </button>
          );
        })}
      </div>

      <Sheet open={!!reviewing} onClose={() => setReviewing(null)} maxHeight="94%">
        {reviewing && <PackPurchaseReviewer
          purchase={reviewing}
          onClose={() => setReviewing(null)}
          onConfirm={() => update(reviewing, "confirmed")}
          onReject={() => update(reviewing, "rejected")}
          openMember={(m) => { setReviewing(null); openMember && openMember(m); }}
        />}
      </Sheet>
    </div>
  );
}

function PackPurchaseReviewer({ purchase, onClose, onConfirm, onReject, openMember }) {
  const member = window.NADI_ADMIN.findMember(purchase.memberId);
  const bank = (window.NADI_ADMIN.BANK_ACCOUNTS || []).find((b) => b.id === purchase.bankId);
  const isPending = purchase.status === "pending";
  return (
    <div style={{ padding: "10px 22px 26px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <Mono>purchase · #{purchase.id}</Mono>
        <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
      </div>
      <h2 className="display" style={{ fontSize: 32, marginTop: 12 }}>{purchase.packageName}</h2>
      <Mono style={{ marginTop: 4 }}>
        {purchase.classes} credit{purchase.classes === 1 ? "" : "s"} · {fmtIDR(purchase.amount)} · submitted {purchase.submitted}
      </Mono>

      {/* Member */}
      <button onClick={() => member && openMember(member)} className="press" style={{
        marginTop: 18, width: "100%", textAlign: "left",
        background: "var(--surface)", border: "1px solid var(--rule)",
        padding: 14,
        display: "grid", gridTemplateColumns: "40px 1fr auto", gap: 12, alignItems: "center",
      }}>
        {member ? <Avatar name={member.name} initials={member.initials} tone={member.tone} size={40} /> : <span />}
        <div>
          <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>{purchase.memberName}</div>
          <Mono>{member ? member.email : "—"} · {member ? `${member.visits} visits` : ""}</Mono>
        </div>
        <Mono color="var(--primary)">open →</Mono>
      </button>

      {/* Bank */}
      <div style={{ marginTop: 14, padding: 14, background: "var(--bg)", border: "1px solid var(--rule)" }}>
        <Mono>transferred to</Mono>
        <div style={{ marginTop: 6, display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 8 }}>
          <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>{bank ? bank.bank : "—"}</div>
          <div style={{
            fontFamily: "'JetBrains Mono', monospace", fontSize: 12,
            color: "var(--ink-soft)", letterSpacing: "0.04em",
          }}>{bank ? bank.number : "—"}</div>
        </div>
        {purchase.note && <Mono style={{ marginTop: 8, display: "block" }}>"{purchase.note}"</Mono>}
      </div>

      {/* Receipt */}
      <div style={{ marginTop: 14 }}>
        <Eyebrow>receipt</Eyebrow>
        <div style={{
          marginTop: 10, border: "1px solid var(--rule)",
          background: "var(--ink)", color: "var(--bg)",
          minHeight: 220,
          display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 8,
          padding: 24,
        }}>
          {purchase.proof ? (
            <img src={purchase.proof} style={{ maxWidth: "100%", maxHeight: 280, objectFit: "contain", borderRadius: 4 }} alt="Receipt proof" />
          ) : (
            <>
              <svg width="42" height="42" viewBox="0 0 28 28" fill="none" stroke="rgba(248,241,225,0.5)" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round">
                <rect x="3" y="5" width="22" height="18"/>
                <path d="M3 19l6-6 5 5 4-4 7 7"/><circle cx="9" cy="11" r="1.4"/>
              </svg>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: "rgba(248,241,225,0.55)", letterSpacing: "0.08em", textTransform: "uppercase" }}>
                no-screenshot.jpg
              </div>
            </>
          )}
          <div style={{ fontFamily: "Newsreader, serif", fontSize: 15, color: "rgba(248,241,225,0.85)", fontStyle: "italic", marginTop: 8 }}>
            {fmtIDR(purchase.amount)} · {bank ? bank.bank : "—"}
          </div>
        </div>
        <Mono style={{ marginTop: 8, display: "block", textAlign: "center" }}>
          verify the amount, account & timestamp match
        </Mono>
      </div>

      {/* Actions */}
      {isPending ? (
        <div style={{ marginTop: 22, display: "flex", flexDirection: "column", gap: 10 }}>
          <Button variant="primary" size="lg" fullWidth onClick={onConfirm}>Confirm — activate credits</Button>
          <Button variant="dangerGhost" size="md" fullWidth onClick={onReject}>Reject purchase</Button>
        </div>
      ) : (
        <div style={{ marginTop: 22, padding: 14, background: "var(--surface)", border: "1px solid var(--rule)", textAlign: "center" }}>
          <Mono color={purchase.status === "confirmed" ? "var(--accent)" : "var(--primary)"}>{purchase.status} {purchase.decidedAt ? `· ${purchase.decidedAt}` : ""}</Mono>
        </div>
      )}
    </div>
  );
}

// ── Sub-header used by all secondary screens ─────────────────────
function SubHeader({ title, back, onAdd, addLabel }) {
  return (
    <div style={{ padding: "10px 18px 14px", display: "flex", alignItems: "center", justifyContent: "space-between", borderBottom: "1px solid var(--rule)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
        <button onClick={back} className="press" aria-label="Back" style={{
          width: 36, height: 36, marginLeft: -6,
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          color: "var(--ink)",
        }}>
          <svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3L4.5 9 12 15"/><path d="M4.5 9H16"/></svg>
        </button>
        <h1 style={{ fontFamily: "Newsreader, serif", fontWeight: 400, fontSize: 24, letterSpacing: "-0.01em", lineHeight: 1 }}>{title}</h1>
      </div>
      {onAdd && (
        <button onClick={onAdd} className="press" style={{
          padding: "6px 12px",
          background: "var(--ink)", color: "var(--bg)",
          fontFamily: "'JetBrains Mono', monospace", fontSize: 10.5,
          letterSpacing: "0.08em", textTransform: "lowercase",
          border: "1px solid var(--ink)",
        }}>{addLabel}</button>
      )}
    </div>
  );
}

Object.assign(window, {
  AdminMoreScreen, AdminPackagesScreen, AdminClassTypesScreen, AdminStudiosScreen,
  AdminAccountsScreen, AdminPaymentsScreen, AdminReportsScreen,
  AdminBankAccountsScreen, AdminPackPurchasesScreen,
  SubHeader,
});
