// settings.jsx - account settings incl. embedded appearance preferences (exported to window)
const { useState: useStateS } = React;

const SETTINGS_NAV = [
  { id: "profile", label: "Profile", icon: "user" },
  { id: "appearance", label: "Appearance", icon: "sparkle" },
  { id: "billing", label: "Billing & Payments", icon: "quote" },
  { id: "notifications", label: "Notifications", icon: "bell" },
  { id: "security", label: "Security", icon: "vault" },
];

const ACCENT_SWATCHES = [
  { hex: "#5b3df5", name: "Violet" }, { hex: "#2a6fdb", name: "Azure" },
  { hex: "#0b9d6f", name: "Emerald" }, { hex: "#b5872a", name: "Gold" },
];

function Settings({ profile, userName, t, setTweak, setDark, openSec, assets, addToast, onPay, lang = "en", setLang, langs = [], plan = "free", setPlan, graph, onProfileSaved }) {
  const [sec, setSec] = useStateS(openSec || "profile");
  const { t: tr } = window.useT();
  const isMobile = window.useIsMobile ? window.useIsMobile() : false;
  const canTeam = plan === "pro" || plan === "business";
  const SETTINGS_NAV = [
    { id: "profile", label: tr("set.nav.profile"), icon: "user" },
    { id: "appearance", label: tr("set.nav.appearance"), icon: "sparkle" },
    { id: "billing", label: tr("set.nav.billing"), icon: "quote" },
    ...(canTeam ? [{ id: "team", label: "Team", icon: "building" }] : []),
    { id: "notifications", label: tr("set.nav.notifications"), icon: "bell" },
    { id: "security", label: tr("set.nav.security"), icon: "vault" },
  ];
  return (
    <div className="vc-page" style={{ padding: "28px 34px 60px", maxWidth: 1100, margin: "0 auto" }}>
      <h1 className="display" style={{ fontSize: 32 }}>{tr("set.title")}</h1>
      <p style={{ color: "var(--text-muted)", fontSize: 15, marginTop: 8 }}>{tr("set.subtitle")}</p>

      {/* On mobile the section picker is a dropdown (no cramped horizontal scroll). */}
      {isMobile && <SettingsDropdown nav={SETTINGS_NAV} sec={sec} setSec={setSec} />}

      <div className="vc-grid" style={{ display: "grid", gridTemplateColumns: "230px 1fr", gap: 24, marginTop: isMobile ? 14 : 24, alignItems: "start" }}>
        {/* sub-nav — desktop sidebar; mobile uses the dropdown above */}
        {!isMobile && (
          <nav className="vc-settings-nav" style={{ display: "grid", gap: 4, position: "sticky", top: 20 }}>
            {SETTINGS_NAV.map((s) => {
              const on = sec === s.id;
              return (
                <button key={s.id} onClick={() => setSec(s.id)} style={{
                  display: "flex", alignItems: "center", gap: 11, padding: "11px 14px", borderRadius: 12, fontSize: 14, fontWeight: 600, textAlign: "left",
                  background: on ? "var(--accent-soft)" : "transparent", color: on ? "var(--accent-ink)" : "var(--text-muted)", transition: "all .2s",
                }}><window.Icon name={s.icon} size={18} />{s.label}</button>
              );
            })}
          </nav>
        )}

        {/* content */}
        <div style={{ animation: "vc-fade-up .35s var(--ease) both" }} key={sec}>
          {sec === "profile" && <ProfileSec profile={profile} userName={userName} lang={lang} setLang={setLang} langs={langs} tr={tr} addToast={addToast} onProfileSaved={onProfileSaved} />}
          {sec === "appearance" && <AppearanceSec t={t} setTweak={setTweak} setDark={setDark} />}
          {sec === "billing" && <BillingSec assets={assets} onPay={onPay} plan={plan} setPlan={setPlan} graph={graph} profile={profile} userName={userName} />}
          {sec === "team" && <TeamSec plan={plan} addToast={addToast} />}
          {sec === "notifications" && <NotificationsSec />}
          {sec === "security" && <SecuritySec addToast={addToast} />}
        </div>
      </div>
    </div>
  );
}

// Mobile section picker: a native dropdown (styled) instead of a scrolling tab bar.
function SettingsDropdown({ nav, sec, setSec }) {
  const cur = nav.find((s) => s.id === sec) || nav[0];
  return (
    <div style={{ position: "relative", marginTop: 18 }}>
      <span style={{ position: "absolute", left: 14, top: "50%", transform: "translateY(-50%)", color: "var(--accent)", pointerEvents: "none" }}><window.Icon name={cur.icon} size={18} /></span>
      <select value={sec} onChange={(e) => setSec(e.target.value)} aria-label="Settings section" style={{
        width: "100%", appearance: "none", WebkitAppearance: "none", MozAppearance: "none",
        padding: "13px 42px 13px 44px", borderRadius: 12, border: "1.5px solid var(--border)",
        background: "var(--surface-2)", color: "var(--text)", fontSize: 15, fontWeight: 700, fontFamily: "inherit", cursor: "pointer",
      }}>
        {nav.map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}
      </select>
      <span style={{ position: "absolute", right: 14, top: "50%", transform: "translateY(-50%)", color: "var(--text-faint)", pointerEvents: "none" }}><window.Icon name="chevD" size={18} /></span>
    </div>
  );
}

/* ---------- shared ---------- */
function Card({ title, desc, children, style = {} }) {
  return (
    <section style={{ padding: 22, borderRadius: 20, background: "var(--surface)", border: "1px solid var(--border)", boxShadow: "var(--shadow-sm)", marginBottom: 16, ...style }}>
      {title && <h3 className="display" style={{ fontSize: 17 }}>{title}</h3>}
      {desc && <p style={{ fontSize: 13.5, color: "var(--text-muted)", marginTop: 5, marginBottom: 4 }}>{desc}</p>}
      <div style={{ marginTop: title ? 16 : 0 }}>{children}</div>
    </section>
  );
}
function SField({ label, value, icon, onChange, type = "text", placeholder }) {
  const controlled = onChange !== undefined;
  return (
    <label style={{ display: "block" }}>
      <span style={{ fontSize: 12.5, fontWeight: 600, color: "var(--text-muted)" }}>{label}</span>
      <div style={{ display: "flex", alignItems: "center", gap: 9, marginTop: 6, padding: "0 13px", borderRadius: 11, background: "var(--surface-2)", border: "1.5px solid var(--border)" }}>
        {icon && <window.Icon name={icon} size={16} style={{ color: "var(--text-faint)" }} />}
        <input type={type} placeholder={placeholder} {...(controlled ? { value: value || "", onChange: (e) => onChange(e.target.value) } : { defaultValue: value })}
          style={{ flex: 1, border: "none", outline: "none", background: "transparent", padding: "12px 0", fontSize: 14.5, color: "var(--text)" }} />
      </div>
    </label>
  );
}
function Toggle({ on, onClick }) {
  return (
    <button onClick={onClick} style={{ width: 46, height: 27, borderRadius: 999, background: on ? "var(--accent)" : "var(--surface-3)", position: "relative", transition: "background .25s", flexShrink: 0 }}>
      <span style={{ position: "absolute", top: 3, left: on ? 22 : 3, width: 21, height: 21, borderRadius: 999, background: "#fff", boxShadow: "var(--shadow-sm)", transition: "left .25s var(--ease)" }} />
    </button>
  );
}
// Preference toggles persist per-device (localStorage) so choices survive
// a refresh — pass a stable `pk` key to enable persistence.
const PREFS_KEY = "vc_prefs_v1";
function loadPref(pk, defOn) {
  try { const all = JSON.parse(localStorage.getItem(PREFS_KEY) || "{}"); return pk in all ? !!all[pk] : defOn; } catch (e) { return defOn; }
}
function savePref(pk, on) {
  try { const all = JSON.parse(localStorage.getItem(PREFS_KEY) || "{}"); all[pk] = on; localStorage.setItem(PREFS_KEY, JSON.stringify(all)); } catch (e) {}
}
function RowToggle({ title, desc, defOn, pk }) {
  const [on, setOn] = useStateS(() => (pk ? loadPref(pk, defOn) : defOn));
  const flip = () => { const next = !on; setOn(next); if (pk) savePref(pk, next); };
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 14, padding: "13px 0", borderTop: "1px solid var(--border)" }}>
      <div style={{ flex: 1 }}><div style={{ fontWeight: 600, fontSize: 14 }}>{title}</div><div style={{ fontSize: 12.5, color: "var(--text-faint)", marginTop: 2 }}>{desc}</div></div>
      <Toggle on={on} onClick={flip} />
    </div>
  );
}

/* ---------- Profile ---------- */
// Real, persisted profile: loads the signed-in account on mount and saves back to
// /api/profile. Name changes lift to the app so the dashboard greeting, schedules
// and certificates all update immediately.
function ProfileSec({ profile, userName, lang, setLang, langs = [], tr, addToast, onProfileSaved }) {
  const isBiz = profile === "business";
  const blank = { name: "", email: "", phone: "", address: "", dob: "", nin: "", rcNumber: "", businessName: "", avatar: "" };
  const [form, setForm] = useStateS(blank);
  const [loaded, setLoaded] = useStateS(false);
  const [saving, setSaving] = useStateS(false);
  const [dirty, setDirty] = useStateS(false);
  const set = (k) => (v) => { setForm((f) => ({ ...f, [k]: v })); setDirty(true); };
  const fileRef = React.useRef(null);

  // Avatar changes save immediately — picking a face shouldn't need a Save press.
  const saveAvatar = (avatar) => {
    setForm((f) => ({ ...f, avatar }));
    fetch("/api/profile", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ avatar }) })
      .then((r) => r.json().then((d) => ({ ok: r.ok, d })))
      .then(({ ok, d }) => {
        if (!ok) { addToast && addToast(d.error || "Couldn't update your photo.", "alert"); return; }
        onProfileSaved && onProfileSaved(d);
        addToast && addToast("Profile photo updated", "check");
      })
      .catch(() => addToast && addToast("Couldn't update your photo.", "alert"));
  };

  // Uploaded photos are resized to a small square client-side so the stored
  // data URL stays tiny (~10-20KB) and loads instantly everywhere.
  const onPickPhoto = (e) => {
    const file = e.target.files && e.target.files[0];
    e.target.value = "";
    if (!file) return;
    if (file.size > 2 * 1024 * 1024) { addToast && addToast("That image is over 2MB. Pick a smaller one.", "alert"); return; }
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      try {
        const S = 144;
        const c = document.createElement("canvas");
        c.width = S; c.height = S;
        const g = c.getContext("2d");
        const side = Math.min(img.width, img.height);
        g.drawImage(img, (img.width - side) / 2, (img.height - side) / 2, side, side, 0, 0, S, S);
        saveAvatar(c.toDataURL("image/jpeg", 0.85));
      } catch (err) { addToast && addToast("Couldn't read that image.", "alert"); }
      URL.revokeObjectURL(url);
    };
    img.onerror = () => { URL.revokeObjectURL(url); addToast && addToast("Couldn't read that image.", "alert"); };
    img.src = url;
  };

  const load = React.useCallback(() => {
    fetch("/api/profile").then((r) => (r.ok ? r.json() : null)).then((d) => {
      if (d) setForm({ ...blank, ...d, name: d.name && d.name !== "You" && d.name !== "Your Business" ? d.name : "" });
      setLoaded(true); setDirty(false);
    }).catch(() => setLoaded(true));
  }, []);
  React.useEffect(load, [load]);

  const save = () => {
    setSaving(true);
    const payload = { name: form.name, email: form.email, phone: form.phone, address: form.address };
    if (isBiz) { payload.businessName = form.businessName; payload.rcNumber = form.rcNumber; }
    else { payload.dob = form.dob; payload.nin = form.nin; }
    fetch("/api/profile", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) })
      .then((r) => r.json().then((d) => ({ ok: r.ok, d })))
      .then(({ ok, d }) => {
        setSaving(false);
        if (!ok) { addToast && addToast(d.error || "Could not save your profile.", "alert"); return; }
        setForm((f) => ({ ...f, ...d })); setDirty(false);
        onProfileSaved && onProfileSaved(d);
        addToast && addToast("Profile saved", "check");
      })
      .catch(() => { setSaving(false); addToast && addToast("Could not save your profile.", "alert"); });
  };

  return (
    <>
    <Card title="Profile" desc="This information personalises your vault and documents.">
      <div style={{ display: "flex", alignItems: "flex-start", gap: 18, marginBottom: 20, flexWrap: "wrap" }}>
        <window.Avatar avatar={form.avatar} name={form.name || userName} size={64} radius={18} />
        <div style={{ flex: 1, minWidth: 240 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
            {window.VC_AVATAR_PRESETS.map((p) => {
              const on = form.avatar === p.id;
              return (
                <button key={p.id} title={p.name} onClick={() => saveAvatar(p.id)} style={{ borderRadius: 12, boxShadow: on ? "0 0 0 2.5px var(--surface), 0 0 0 4.5px var(--accent)" : "none", transition: "box-shadow .2s" }}>
                  <window.Avatar avatar={p.id} size={38} radius={12} />
                </button>
              );
            })}
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 10 }}>
            <window.Btn variant="outline" size="sm" icon="plus" onClick={() => fileRef.current && fileRef.current.click()}>Upload photo</window.Btn>
            {form.avatar && <window.Btn variant="ghost" size="sm" onClick={() => saveAvatar("")}>Remove</window.Btn>}
            <input ref={fileRef} type="file" accept="image/png,image/jpeg,image/webp" onChange={onPickPhoto} style={{ display: "none" }} />
          </div>
          <div style={{ fontSize: 12, color: "var(--text-faint)", marginTop: 6 }}>Pick an avatar or upload a PNG/JPG up to 2MB.</div>
        </div>
      </div>
      <div className="vc-grid" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 13 }}>
        <SField label="Full name" value={form.name} onChange={set("name")} placeholder={isBiz ? "Contact name" : "e.g. Adebola Okafor"} icon="user" />
        <SField label="Email" value={form.email} onChange={set("email")} type="email" placeholder="you@email.com" icon="doc" />
        <SField label="Phone" value={form.phone} onChange={set("phone")} placeholder="+234 ..." />
        {isBiz
          ? <SField label="Business name" value={form.businessName} onChange={set("businessName")} placeholder="e.g. ABC Logistics Ltd." icon="building" />
          : <SField label="Date of birth" value={form.dob} onChange={set("dob")} placeholder="e.g. 14 Apr 1990" />}
        {isBiz
          ? <SField label="RC number" value={form.rcNumber} onChange={set("rcNumber")} placeholder="e.g. RC 1842203" />
          : <SField label="NIN" value={form.nin} onChange={set("nin")} placeholder="National ID number" icon="vault" />}
        <SField label="Address" value={form.address} onChange={set("address")} placeholder="Street, area, city" icon="home" />
      </div>
      <div style={{ display: "flex", gap: 10, marginTop: 20, alignItems: "center" }}>
        <window.Btn onClick={save} disabled={saving || !dirty}>{saving ? "Saving…" : "Save changes"}</window.Btn>
        <window.Btn variant="ghost" onClick={load} disabled={saving || !dirty}>Cancel</window.Btn>
        {!loaded && <span style={{ fontSize: 12.5, color: "var(--text-faint)" }}>Loading your details…</span>}
      </div>
    </Card>
    {langs.length > 0 && (
      <Card title={tr("set.language")} desc={tr("set.languageDesc")}>
        <div style={{ display: "flex", gap: 9, flexWrap: "wrap" }}>
          {langs.map((l) => {
            const on = lang === l.id;
            return (
              <button key={l.id} onClick={() => setLang && setLang(l.id)} style={{ padding: "9px 17px", borderRadius: 999, fontSize: 13.5, fontWeight: 700, background: on ? "var(--accent)" : "var(--surface-2)", color: on ? "#fff" : "var(--text-muted)", border: "1.5px solid " + (on ? "var(--accent)" : "var(--border)"), transition: "all .2s" }}>{l.native}</button>
            );
          })}
        </div>
      </Card>
    )}
    </>
  );
}

/* ---------- Appearance (embeds tweaks) ---------- */
function AppearanceSec({ t, setTweak, setDark }) {
  return (
    <>
      <Card title="Theme" desc="Choose how VaultCova looks. Your choice is saved to this device.">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          {[["light", "sun", "Light"], ["dark", "moon", "Dark"]].map(([id, ic, label]) => {
            const on = (id === "dark") === !!t.dark;
            return (
              <button key={id} onClick={() => (setDark || ((v) => setTweak("dark", v)))(id === "dark")} style={{ padding: 16, borderRadius: 16, textAlign: "left", background: "var(--surface-2)", border: "2px solid " + (on ? "var(--accent)" : "var(--border)"), transition: "all .2s" }}>
                <div style={{ height: 58, borderRadius: 10, marginBottom: 12, background: id === "dark" ? "linear-gradient(135deg,#0e1027,#1a1d3e)" : "linear-gradient(135deg,#fff,#eceef7)", border: "1px solid var(--border)", display: "flex", alignItems: "center", padding: 10, gap: 8 }}>
                  <span style={{ width: 18, height: 18, borderRadius: 6, background: "var(--accent)" }} />
                  <span style={{ flex: 1, height: 7, borderRadius: 9, background: id === "dark" ? "#2a2e52" : "#d4d8e8" }} />
                </div>
                <div style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 700, fontSize: 14.5 }}><window.Icon name={ic} size={16} style={{ color: on ? "var(--accent)" : "var(--text-faint)" }} />{label}{on && <window.Icon name="check" size={15} stroke={3} style={{ marginLeft: "auto", color: "var(--accent)" }} />}</div>
              </button>
            );
          })}
        </div>
      </Card>

      <Card title="Accent colour" desc="Sets the highlight colour across your whole vault.">
        <div style={{ display: "flex", gap: 14 }}>
          {ACCENT_SWATCHES.map((s) => {
            const on = t.accent === s.hex;
            return (
              <button key={s.hex} onClick={() => setTweak("accent", s.hex)} style={{ textAlign: "center" }}>
                <span style={{ display: "grid", placeItems: "center", width: 50, height: 50, borderRadius: 14, background: s.hex, color: "#fff", boxShadow: on ? `0 0 0 3px var(--surface), 0 0 0 5px ${s.hex}` : "var(--shadow-sm)", transition: "all .2s" }}>{on && <window.Icon name="check" size={22} stroke={3} />}</span>
                <div style={{ fontSize: 12, fontWeight: 600, marginTop: 8, color: on ? "var(--text)" : "var(--text-faint)" }}>{s.name}</div>
              </button>
            );
          })}
        </div>
      </Card>

      <CovaVoiceCard t={t} setTweak={setTweak} />
    </>
  );
}

/* ---------- Voice & mic ---------- */
// The YarnGPT Nigerian-voice picker is retired for now; Cova uses the device's
// built-in voice. This card controls spoken replies and how the mic behaves.
const VOICE_MODES = [
  ["off", "close", "Off"],
  ["dictate", "mic", "Dictate"],
  ["autosend", "send", "Auto-send"],
  ["conversation", "chat", "Hands-free"],
];
function CovaVoiceCard({ t, setTweak }) {
  const spoken = t.covaVoice !== "off";
  return (
    <Card title="Voice & mic" desc="Control whether Cova reads replies aloud and what happens when you tap the mic.">
      <div style={{ display: "flex", alignItems: "center", gap: 14, padding: "4px 0 16px" }}>
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 600, fontSize: 14 }}>Spoken replies</div>
          <div style={{ fontSize: 12.5, color: "var(--text-faint)", marginTop: 2 }}>Cova reads replies aloud in hands-free chat using your device's voice.</div>
        </div>
        <Toggle on={spoken} onClick={() => setTweak("covaVoice", spoken ? "off" : "on")} />
      </div>
      <div style={{ fontSize: 12.5, fontWeight: 700, color: "var(--text-muted)", marginBottom: 8 }}>When you tap the mic</div>
      <PickRow value={t.voiceMode || "autosend"} set={(v) => setTweak("voiceMode", v)} opts={VOICE_MODES} />
      <div style={{ fontSize: 12, color: "var(--text-faint)", marginTop: 10, lineHeight: 1.5 }}>
        <b>Dictate</b> types what you say. <b>Auto-send</b> sends it for you. <b>Hands-free</b> also reads Cova's replies aloud and reopens the mic, so you can talk back and forth.
      </div>
    </Card>
  );
}
function PickRow({ value, set, opts }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: `repeat(${opts.length},1fr)`, gap: 8 }}>
      {opts.map(([id, ic, label]) => {
        const on = value === id;
        return (
          <button key={id} onClick={() => set(id)} style={{ display: "grid", placeItems: "center", gap: 7, padding: "14px 8px", borderRadius: 13, background: on ? "var(--accent-soft)" : "var(--surface-2)", border: "1.5px solid " + (on ? "var(--accent)" : "var(--border)"), color: on ? "var(--accent-ink)" : "var(--text-muted)", transition: "all .2s" }}>
            <window.Icon name={ic} size={20} />
            <span style={{ fontSize: 12.5, fontWeight: 700 }}>{label}</span>
          </button>
        );
      })}
    </div>
  );
}

/* ---------- Billing ---------- */
function BillingSec({ assets, onPay, plan = "free", setPlan, graph, profile, userName }) {
  const D = window.VC_DATA;
  const [cycle, setCycle] = useStateS("monthly"); // monthly | annual
  const annual = cycle === "annual";
  const freeMonths = D.ANNUAL_MONTHS_FREE || 2;
  // Annual = pay for 10 months, 2 free. Display the effective per-month figure;
  // charge the exact 10-month total (no rounding drift) — wired to onPay below.
  const priceFor = (p) => annual ? D.annualPerMonth(p.price) : p.price;
  const chargeFor = (p) => annual ? D.annualTotal(p.price) : p.price;
  const up = graph && D.upgradeSignal ? D.upgradeSignal(plan, profile, assets, graph) : null;
  // Free VaultLog is capped; surface how close they are so the upgrade makes sense.
  const cap = D.FREE_ASSET_CAP || 35;
  const overCap = plan === "free" && assets.length >= cap;
  const nearCap = plan === "free" && assets.length >= cap - 5 && assets.length < cap;
  const insured = assets.filter((a) => a.insurer);
  const totalPremium = insured.reduce((s, a) => s + (a.premium || 0), 0);
  const monthly = Math.round(totalPremium / 12 / 1000) * 1000;
  const invoices = [
    { id: "INV-2026-014", date: "12 May 2026", amt: monthly, status: "Paid" },
    { id: "INV-2026-009", date: "12 Apr 2026", amt: monthly, status: "Paid" },
    { id: "INV-2026-004", date: "12 Mar 2026", amt: monthly, status: "Paid" },
  ];
  return (
    <>
      <Card title="Your plan" desc="Policies, claims and Cova are free for everyone. Free Vault covers up to 35 assets. Upgrade to raise the limit. Cova insights are on every tier.">
        {(overCap || nearCap) && (
          <div style={{ display: "flex", gap: 11, alignItems: "center", padding: 13, borderRadius: 13, background: overCap ? "var(--danger-soft)" : "var(--warning-soft)", border: "1px solid " + (overCap ? "var(--danger)" : "var(--warning)"), marginBottom: 14 }}>
            <window.Icon name="alert" size={18} style={{ color: overCap ? "var(--danger)" : "var(--warning)", flexShrink: 0 }} />
            <span style={{ fontSize: 13, fontWeight: 600, lineHeight: 1.5, color: "var(--text)" }}>
              {overCap
                ? `You've reached the ${cap}-asset Free Vault limit (${assets.length}). Upgrade to Individual Vault (₦800/mo) or higher to add more.`
                : `You're using ${assets.length} of ${cap} Free Vault assets. Individual Vault (₦800/mo) raises the limit.`}
            </span>
          </div>
        )}
        {up && !overCap && (
          <div style={{ display: "flex", gap: 11, alignItems: "center", padding: 13, borderRadius: 13, background: "var(--accent-soft)", border: "1px solid var(--accent)", marginBottom: 14 }}>
            <window.Icon name="sparkle" size={18} style={{ color: "var(--accent)", flexShrink: 0 }} />
            <span style={{ fontSize: 13, color: "var(--accent-ink)", fontWeight: 600, lineHeight: 1.5 }}>{up.reason}</span>
          </div>
        )}
        {/* billing cycle toggle */}
        <div style={{ display: "inline-flex", padding: 3, borderRadius: 999, background: "var(--surface-3)", marginBottom: 16 }}>
          {[["monthly", "Monthly"], ["annual", "Annual"]].map(([id, label]) => (
            <button key={id} onClick={() => setCycle(id)} style={{ display: "inline-flex", alignItems: "center", gap: 7, padding: "7px 16px", borderRadius: 999, fontSize: 12.5, fontWeight: 700, border: "none", cursor: "pointer", background: cycle === id ? "var(--surface)" : "transparent", color: cycle === id ? "var(--text)" : "var(--text-muted)", boxShadow: cycle === id ? "var(--shadow-sm)" : "none", transition: "all .2s" }}>
              {label}{id === "annual" && <span style={{ fontSize: 10, fontWeight: 800, padding: "2px 7px", borderRadius: 999, background: "var(--success-soft)", color: "var(--success)" }}>{freeMonths} MONTHS FREE</span>}
            </button>
          ))}
        </div>
        <div className="vc-grid" style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12 }}>
          {D.PLANS.map((p) => {
            const on = plan === p.id;
            const rec = (up && up.to === p.id) || (overCap && p.id === "individual");
            const popular = p.id === "pro"; // the standing recommendation, like most apps
            const price = priceFor(p);
            return (
              <div key={p.id} style={{ position: "relative", display: "flex", flexDirection: "column", padding: 16, borderRadius: 16, background: on ? "var(--accent-soft)" : "var(--surface-2)", border: "2px solid " + (on ? "var(--accent)" : rec ? "var(--accent-2)" : popular ? "var(--accent)" : "var(--border)") }}>
                {rec && !on && <span style={{ position: "absolute", top: -9, left: 14, fontSize: 9.5, fontWeight: 800, padding: "2px 9px", borderRadius: 999, background: "var(--accent)", color: "#fff" }}>SUGGESTED</span>}
                {popular && !on && !rec && <span style={{ position: "absolute", top: -9, right: 12, fontSize: 9.5, fontWeight: 800, padding: "2px 9px", borderRadius: 999, background: "var(--accent)", color: "#fff", letterSpacing: ".03em" }}>MOST POPULAR</span>}
                <div style={{ fontWeight: 800, fontSize: 13.5 }}>{p.name.replace("VaultCova ", "")}</div>
                <div style={{ marginTop: 6 }}>
                  <span className="display mono" style={{ fontSize: 21 }}>{p.price ? "₦" + price.toLocaleString() : "Free"}</span>
                  {p.price ? <span style={{ fontSize: 11, color: "var(--text-faint)", marginLeft: 4 }}>/mo</span> : <span style={{ fontSize: 11, color: "var(--text-faint)", marginLeft: 4 }}>{p.per}</span>}
                </div>
                {p.price > 0 && annual && <div style={{ fontSize: 10.5, color: "var(--success)", fontWeight: 700, marginTop: 2 }}>₦{chargeFor(p).toLocaleString()}/yr · {freeMonths} months free</div>}
                <div style={{ fontSize: 11, color: "var(--text-muted)", marginTop: 4, flex: "none" }}>{p.who}</div>
                <div style={{ display: "inline-flex", alignItems: "center", gap: 5, marginTop: 8, fontSize: 10.5, fontWeight: 800, padding: "3px 8px", borderRadius: 999, alignSelf: "flex-start", background: p.assetCap ? "var(--surface-3)" : "var(--success-soft)", color: p.assetCap ? "var(--text-muted)" : "var(--success)" }}>
                  <window.Icon name="vault" size={11} />{p.assetCap ? `Up to ${p.assetCap} assets` : "Unlimited assets"}
                </div>
                <div style={{ display: "grid", gap: 5, marginTop: 10, flex: 1 }}>
                  {p.feats.slice(0, 4).map((f) => (
                    <div key={f} style={{ display: "flex", gap: 6, alignItems: "flex-start", fontSize: 11.5, color: "var(--text-muted)" }}>
                      <window.Icon name="check" size={12} stroke={3} style={{ color: "var(--success)", flexShrink: 0, marginTop: 2 }} />{f}
                    </div>
                  ))}
                </div>
                {on ? (
                  <div style={{ marginTop: 12, textAlign: "center", fontSize: 12, fontWeight: 800, color: "var(--accent)" }}>CURRENT PLAN</div>
                ) : (
                  <window.Btn size="sm" variant={rec || popular ? "primary" : "outline"} style={{ width: "100%", justifyContent: "center", marginTop: 12 }} onClick={() => {
                    // Paid tiers apply only after checkout completes (pass the plan
                    // to the payment flow); the free tier applies directly.
                    if (p.price > 0) { onPay && onPay(chargeFor(p), p.name.replace("VaultCova ", "") + (annual ? ` · annual (${freeMonths} months free)` : " · monthly"), p.id); }
                    else { setPlan && setPlan(p.id); }
                  }}>Subscribe</window.Btn>
                )}
              </div>
            );
          })}
        </div>
      </Card>
      <Card>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 14 }}>
          <div>
            <div style={{ fontSize: 13, color: "var(--text-muted)", fontWeight: 600 }}>Next premium due</div>
            <div className="display mono" style={{ fontSize: 30, marginTop: 4 }}>{D.fmtFull(monthly)}</div>
            <div style={{ fontSize: 13, color: "var(--text-faint)", marginTop: 4 }}>on 12 Jun 2026 · {insured.length} active policies</div>
          </div>
          <window.Btn size="lg" icon="quote" onClick={() => onPay(monthly, "Monthly premium · " + insured.length + " policies")}>Pay now</window.Btn>
        </div>
      </Card>

      <PaymentMethodsCard />

      <Card title="Invoice history">
        <div style={{ display: "grid", gap: 2 }}>
          {invoices.map((inv) => (
            <div key={inv.id} style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr auto", gap: 12, alignItems: "center", padding: "12px 0", borderTop: "1px solid var(--border)" }}>
              <span className="mono" style={{ fontSize: 13, fontWeight: 600 }}>{inv.id}</span>
              <span style={{ fontSize: 13, color: "var(--text-muted)" }}>{inv.date}</span>
              <span className="mono" style={{ fontSize: 13.5, fontWeight: 700 }}>{D.fmtFull(inv.amt)}</span>
              <button onClick={() => window.downloadInvoice(inv, userName, profile)} style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 12.5, fontWeight: 700, color: "var(--accent)" }}><window.Icon name="download" size={14} />PDF</button>
            </div>
          ))}
        </div>
      </Card>
    </>
  );
}

/* ---------- Payment methods ---------- */
// Cards live per-device (localStorage) in this prototype — adding, defaulting
// and removing all work, so the flow is real even before a PSP is wired.
const CARDS_KEY = "vc_cards_v1";
function loadCards() {
  try {
    const c = JSON.parse(localStorage.getItem(CARDS_KEY) || "null");
    if (Array.isArray(c) && c.length) return c;
  } catch (e) {}
  return [{ id: "c1", brand: "Visa", last4: "4242", expiry: "08/28", isDefault: true }];
}
function PaymentMethodsCard() {
  const [cards, setCards] = useStateS(loadCards);
  const [adding, setAdding] = useStateS(false);
  const [num, setNum] = useStateS("");
  const [exp, setExp] = useStateS("");
  const persist = (next) => { setCards(next); try { localStorage.setItem(CARDS_KEY, JSON.stringify(next)); } catch (e) {} };

  const addCard = () => {
    const digits = num.replace(/\D/g, "");
    if (digits.length < 13 || digits.length > 19) return;
    if (!/^\d{2}\/\d{2}$/.test(exp)) return;
    const brand = digits.startsWith("4") ? "Visa" : digits.startsWith("5") ? "Mastercard" : digits.startsWith("506") || digits.startsWith("650") ? "Verve" : "Card";
    persist([...cards, { id: "c" + Date.now(), brand, last4: digits.slice(-4), expiry: exp, isDefault: cards.length === 0 }]);
    setNum(""); setExp(""); setAdding(false);
  };
  const makeDefault = (id) => persist(cards.map((c) => ({ ...c, isDefault: c.id === id })));
  const remove = (id) => {
    let next = cards.filter((c) => c.id !== id);
    if (next.length && !next.some((c) => c.isDefault)) next = next.map((c, i) => ({ ...c, isDefault: i === 0 }));
    persist(next);
  };

  const valid = num.replace(/\D/g, "").length >= 13 && /^\d{2}\/\d{2}$/.test(exp);
  return (
    <Card title="Payment methods">
      <div style={{ display: "grid", gap: 10 }}>
        {cards.map((c) => (
          <div key={c.id} style={{ display: "flex", alignItems: "center", gap: 13, padding: 14, borderRadius: 13, background: "var(--surface-2)", border: "1px solid var(--border)" }}>
            <span style={{ display: "grid", placeItems: "center", width: 42, height: 42, borderRadius: 11, background: "var(--accent)", color: "#fff" }}><window.Icon name="quote" size={19} /></span>
            <div style={{ flex: 1 }}><div style={{ fontWeight: 700, fontSize: 14 }}>{c.brand} ending {c.last4}</div><div style={{ fontSize: 12.5, color: "var(--text-faint)" }}>Expires {c.expiry}{c.isDefault ? " · default" : ""}</div></div>
            {c.isDefault
              ? <span style={{ fontSize: 11.5, fontWeight: 700, padding: "4px 10px", borderRadius: 999, background: "var(--success-soft)", color: "var(--success)" }}>Default</span>
              : <div style={{ display: "flex", gap: 8 }}>
                  <button onClick={() => makeDefault(c.id)} style={{ fontSize: 12, fontWeight: 700, color: "var(--accent)" }}>Make default</button>
                  <button onClick={() => remove(c.id)} style={{ fontSize: 12, fontWeight: 700, color: "var(--danger)" }}>Remove</button>
                </div>}
          </div>
        ))}
        {adding ? (
          <div style={{ padding: 14, borderRadius: 13, border: "1.5px solid var(--accent)", background: "var(--surface)", display: "grid", gap: 10 }}>
            <div className="vc-grid" style={{ display: "grid", gridTemplateColumns: "2fr 1fr", gap: 10 }}>
              <SField label="Card number" value={num} onChange={setNum} placeholder="4242 4242 4242 4242" icon="quote" />
              <SField label="Expiry (MM/YY)" value={exp} onChange={setExp} placeholder="08/28" />
            </div>
            <div style={{ display: "flex", gap: 8 }}>
              <window.Btn size="sm" onClick={addCard} disabled={!valid}>Save card</window.Btn>
              <window.Btn size="sm" variant="ghost" onClick={() => { setAdding(false); setNum(""); setExp(""); }}>Cancel</window.Btn>
            </div>
          </div>
        ) : (
          <button onClick={() => setAdding(true)} style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 8, padding: 14, borderRadius: 13, border: "1.5px dashed var(--border-strong)", color: "var(--accent)", fontWeight: 700, fontSize: 14 }}><window.Icon name="plus" size={17} />Add payment method</button>
        )}
      </div>
    </Card>
  );
}

/* ---------- Team members (Pro / Business) ---------- */
// The account holder assigns staff (name, designation, email, phone). They do
// not log in; this is a roster the main user manages. Seats: Pro 3, Business 5.
function TeamSec({ plan, addToast }) {
  const [members, setMembers] = useStateS([]);
  const [cap, setCap] = useStateS(plan === "business" ? 5 : 3);
  const [loaded, setLoaded] = useStateS(false);
  const [adding, setAdding] = useStateS(false);
  const [form, setForm] = useStateS({ name: "", designation: "", email: "", phone: "" });
  const [err, setErr] = useStateS("");
  const [busy, setBusy] = useStateS(false);
  const setF = (k) => (v) => setForm((f) => ({ ...f, [k]: v }));

  React.useEffect(() => {
    fetch("/api/team").then((r) => r.json()).then((d) => {
      if (d && Array.isArray(d.members)) { setMembers(d.members); if (typeof d.cap === "number") setCap(d.cap); }
      setLoaded(true);
    }).catch(() => setLoaded(true));
  }, []);

  const ready = form.name.trim().length >= 2 && form.designation.trim() && /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(form.email.trim()) && form.phone.replace(/\D/g, "").length >= 7;
  const full = members.length >= cap;

  const add = () => {
    if (!ready || busy) return;
    setBusy(true); setErr("");
    fetch("/api/team", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(form) })
      .then((r) => r.json().then((d) => ({ ok: r.ok, d })))
      .then(({ ok, d }) => {
        if (!ok) { setErr(d.error || "Couldn't add that member."); return; }
        setMembers((m) => [...m, d]); setForm({ name: "", designation: "", email: "", phone: "" }); setAdding(false);
        addToast && addToast("Team member added", "check");
      })
      .catch(() => setErr("Couldn't add that member."))
      .finally(() => setBusy(false));
  };
  const remove = (id) => {
    setMembers((m) => m.filter((x) => x.id !== id));
    fetch("/api/team/" + id, { method: "DELETE" }).catch(() => {});
    addToast && addToast("Team member removed", "check");
  };

  return (
    <Card title="Team members" desc={`Assign staff to your account, ${plan === "business" ? "Business" : "Pro"} includes ${cap} seats. They don't log in; you manage their details here.`}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 14 }}>
        <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--text-muted)" }}>{members.length} of {cap} seats used</span>
        <div style={{ flex: 1, height: 7, borderRadius: 999, background: "var(--surface-3)", overflow: "hidden", maxWidth: 220 }}>
          <div style={{ height: "100%", width: Math.min(100, (members.length / cap) * 100) + "%", background: "var(--accent)", borderRadius: 999 }} />
        </div>
      </div>

      {members.length > 0 && (
        <div style={{ display: "grid", gap: 8, marginBottom: 14 }}>
          {members.map((m) => (
            <div key={m.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "12px 14px", borderRadius: 13, background: "var(--surface-2)", border: "1px solid var(--border)" }}>
              <span style={{ display: "grid", placeItems: "center", width: 38, height: 38, borderRadius: 11, flexShrink: 0, background: "var(--accent-soft)", color: "var(--accent)", fontWeight: 800, fontSize: 15 }}>{(m.name || "?").trim().charAt(0).toUpperCase()}</span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 700, fontSize: 14 }}>{m.name} <span style={{ fontWeight: 600, color: "var(--text-muted)", fontSize: 12.5 }}>· {m.designation}</span></div>
                <div style={{ fontSize: 12, color: "var(--text-faint)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{m.email} · {m.phone}</div>
              </div>
              <button onClick={() => remove(m.id)} style={{ fontSize: 12.5, fontWeight: 700, color: "var(--danger)", padding: "6px 10px", borderRadius: 9 }}>Remove</button>
            </div>
          ))}
        </div>
      )}

      {loaded && !adding && !full && (
        <button onClick={() => setAdding(true)} style={{ width: "100%", padding: "12px 0", borderRadius: 12, border: "2px dashed var(--border)", background: "transparent", color: "var(--text-muted)", fontWeight: 700, fontSize: 13.5, cursor: "pointer" }}>+ Add team member</button>
      )}
      {full && !adding && <div style={{ fontSize: 12.5, color: "var(--text-faint)", textAlign: "center", padding: "8px 0" }}>All {cap} seats are in use{plan === "pro" ? ". Upgrade to Business for 5 seats." : "."}</div>}

      {adding && (
        <div style={{ padding: 16, borderRadius: 14, background: "var(--surface-2)", border: "1.5px solid var(--accent)" }}>
          {err && <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--danger)", marginBottom: 10 }}>{err}</div>}
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            <SField label="Full name" value={form.name} onChange={setF("name")} placeholder="e.g. Chioma Eze" />
            <SField label="Designation" value={form.designation} onChange={setF("designation")} placeholder="e.g. Operations Lead" />
            <SField label="Email" type="email" value={form.email} onChange={setF("email")} placeholder="name@company.com" />
            <SField label="Phone" value={form.phone} onChange={setF("phone")} placeholder="0803 000 0000" />
          </div>
          <div style={{ display: "flex", gap: 10, marginTop: 14 }}>
            <button onClick={add} disabled={!ready || busy} style={{ padding: "10px 18px", borderRadius: 999, background: ready ? "var(--accent)" : "var(--surface-3)", color: ready ? "#fff" : "var(--text-faint)", fontWeight: 700, fontSize: 13.5, border: "none", cursor: ready ? "pointer" : "default" }}>{busy ? "Adding…" : "Add member"}</button>
            <button onClick={() => { setAdding(false); setErr(""); }} style={{ padding: "10px 16px", borderRadius: 999, background: "transparent", color: "var(--text-muted)", fontWeight: 700, fontSize: 13.5 }}>Cancel</button>
          </div>
        </div>
      )}
    </Card>
  );
}

/* ---------- Notifications ---------- */
function NotificationsSec() {
  return (
    <Card title="Notifications" desc="Cova keeps you ahead of every renewal, gap and claim.">
      <RowToggle pk="notif.gaps" title="Coverage gap alerts" desc="When an asset becomes exposed or underinsured" defOn={true} />
      <RowToggle pk="notif.renewals" title="Renewal reminders" desc="14, 7 and 1 day before a policy lapses" defOn={true} />
      <RowToggle pk="notif.claims" title="Claim updates" desc="Every status change from notice to settlement" defOn={true} />
      <RowToggle pk="notif.receipts" title="Payment receipts" desc="Confirmations and upcoming-charge reminders" defOn={true} />
      <RowToggle pk="notif.suggestions" title="Cova suggestions" desc="Proactive tips to optimise your premiums" defOn={false} />
      <RowToggle pk="notif.offers" title="Product & offers" desc="New features and partner insurer deals" defOn={false} />
    </Card>
  );
}

/* ---------- Security ---------- */
function SecuritySec({ addToast }) {
  const [cur, setCur] = useStateS("");
  const [next, setNext] = useStateS("");
  const [busy, setBusy] = useStateS(false);
  const [sessions, setSessions] = useStateS([
    { id: 1, device: "This browser", detail: "This device · active now", current: true },
    { id: 2, device: "Chrome · MacBook", detail: "2 days ago", current: false },
  ]);

  const changePassword = () => {
    if (next.length < 8) { addToast && addToast("New password must be at least 8 characters.", "alert"); return; }
    setBusy(true);
    fetch("/api/profile/password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ current: cur, next }) })
      .then((r) => r.json().then((d) => ({ ok: r.ok, d })))
      .then(({ ok, d }) => {
        setBusy(false);
        if (!ok) { addToast && addToast(d.error || "Couldn't update your password.", "alert"); return; }
        setCur(""); setNext("");
        addToast && addToast("Password updated", "check");
      })
      .catch(() => { setBusy(false); addToast && addToast("Couldn't update your password.", "alert"); });
  };

  const endSession = (id) => {
    setSessions((ss) => ss.filter((x) => x.id !== id));
    addToast && addToast("Session signed out", "check");
  };

  return (
    <>
      <Card title="Password">
        <div style={{ display: "grid", gap: 13, maxWidth: 380 }}>
          <SField label="Current password" value={cur} onChange={setCur} type="password" icon="vault" />
          <SField label="New password (min 8 characters)" value={next} onChange={setNext} type="password" icon="vault" />
        </div>
        <div style={{ marginTop: 16 }}><window.Btn onClick={changePassword} disabled={busy || !next}>{busy ? "Updating…" : "Update password"}</window.Btn></div>
      </Card>
      <Card title="Two-factor & identity">
        <RowToggle pk="sec.2fa" title="Two-factor authentication" desc="Require an SMS code at every login" defOn={true} />
        <RowToggle pk="sec.biometric" title="Biometric unlock" desc="Use Face ID / fingerprint on this device" defOn={true} />
        <div style={{ display: "flex", alignItems: "center", gap: 14, padding: "13px 0", borderTop: "1px solid var(--border)" }}>
          <div style={{ flex: 1 }}><div style={{ fontWeight: 600, fontSize: 14 }}>BVN / NIN verification</div><div style={{ fontSize: 12.5, color: "var(--text-faint)", marginTop: 2 }}>Required for claim payouts</div></div>
          <span style={{ fontSize: 12, fontWeight: 700, padding: "5px 12px", borderRadius: 999, background: "var(--success-soft)", color: "var(--success)", display: "inline-flex", alignItems: "center", gap: 6 }}><window.Icon name="check" size={14} stroke={3} />Verified</span>
        </div>
      </Card>
      <Card title="Active sessions">
        <div style={{ display: "grid", gap: 12 }}>
          {sessions.map((s) => (
            <div key={s.id} style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <span style={{ display: "grid", placeItems: "center", width: 38, height: 38, borderRadius: 11, background: "var(--surface-3)", color: "var(--text-muted)" }}><window.Icon name="user" size={18} /></span>
              <div style={{ flex: 1 }}><div style={{ fontWeight: 600, fontSize: 13.5 }}>{s.device}</div><div style={{ fontSize: 12, color: "var(--text-faint)" }}>{s.detail}</div></div>
              {!s.current && <button onClick={() => endSession(s.id)} style={{ fontSize: 12.5, fontWeight: 700, color: "var(--danger)" }}>Sign out</button>}
            </div>
          ))}
        </div>
      </Card>
    </>
  );
}

Object.assign(window, { Settings });
