/* =============================================================
   CoreIQ Office — Head-office modules:
   Payment accounts · Promotions · Loyalty
   ============================================================= */
const { useState: hoUseState, useMemo: hoUseMemo } = React;

// -----------------------------------------------------------------
// Sample data for accounts, promos, loyalty
// -----------------------------------------------------------------
const HO_ACCOUNTS = [
  { id: "ACC-1042", type: "business", name: "Camberwell Aged Care Facility", abn: "49 122 884 207", store: "S-001", terms: "Net 30", creditLimit: 15000, balance: 8420.65, status: "active",     overdueDays: 0,  monthlyAvg: 9840, contact: "Joanne Pereira",  authorised: 24, lastCharge: "Today 14:12" },
  { id: "ACC-1108", type: "business", name: "Whitehorse Family Medical Centre", abn: "62 008 117 003", store: "S-001", terms: "Net 14", creditLimit: 5000,  balance: 1280.50, status: "active",     overdueDays: 0,  monthlyAvg: 2240, contact: "Dr S. Kapoor",    authorised: 0,  lastCharge: "Yesterday" },
  { id: "ACC-1214", type: "business", name: "Bridgewater NDIS Services", abn: "98 642 119 220", store: "S-002", terms: "Net 30", creditLimit: 10000, balance: 4152.00, status: "active",     overdueDays: 0,  monthlyAvg: 4200, contact: "Marta Voss",      authorised: 7,  lastCharge: "Today 11:30" },
  { id: "ACC-1018", type: "person",   name: "Whitlock, Henry",  abn: "—",            store: "S-001", terms: "Monthly", creditLimit: 1500,  balance:  890.40, status: "overdue",   overdueDays: 12, monthlyAvg:  410, contact: "Henry Whitlock", authorised: 1,  lastCharge: "3 days ago" },
  { id: "ACC-1320", type: "person",   name: "Costa, Ana",       abn: "—",            store: "S-003", terms: "Net 30",  creditLimit: 300,   balance:  145.20, status: "active",    overdueDays: 0,  monthlyAvg:  160, contact: "Ana Costa",      authorised: 1,  lastCharge: "Yesterday" },
  { id: "ACC-1190", type: "business", name: "Burke Road Community House", abn: "11 220 401 558", store: "S-001", terms: "Net 30", creditLimit: 2000,  balance: 1980.00, status: "over-limit", overdueDays: 0,  monthlyAvg: 1840, contact: "Linh Tran",       authorised: 8,  lastCharge: "Today 13:02" },
  { id: "ACC-1488", type: "business", name: "Yarra River Disability Support", abn: "76 119 882 044", store: "S-002", terms: "Net 30", creditLimit: 4000, balance: 0, status: "hold", overdueDays: 0, monthlyAvg: 0, contact: "Aleksei Markov", authorised: 0, lastCharge: "—" },
  { id: "ACC-1611", type: "business", name: "Eastland Medical Suites", abn: "33 991 002 117", store: "S-003", terms: "Net 14", creditLimit: 7500, balance: 3210.40, status: "active", overdueDays: 0, monthlyAvg: 3680, contact: "Dr R. Patel", authorised: 12, lastCharge: "Today 10:48" },
  { id: "ACC-1612", type: "business", name: "Glen Iris Day Centre", abn: "55 880 117 022", store: "S-002", terms: "Net 30", creditLimit: 6000, balance: 5418.20, status: "active", overdueDays: 0, monthlyAvg: 5240, contact: "Helen Yeo", authorised: 14, lastCharge: "Today 11:48" },
  { id: "ACC-1718", type: "person",   name: "Sharma, Priya",    abn: "—",            store: "S-001", terms: "Net 30",  creditLimit: 500,   balance:   88.10, status: "active",    overdueDays: 0,  monthlyAvg:  120, contact: "Priya Sharma",   authorised: 1,  lastCharge: "Yesterday" },
];

const HO_PROMOS = [
  { id: "PR-2026-001", name: "Summer Saver · Skincare", type: "percent", value: 30, target: "category", targetLabel: "Skincare", stores: ["S-001","S-002","S-003"], starts: "20/05/2026", ends: "31/05/2026", redemptions: 142, revenue: 2480.40, status: "active", priority: 1, requiresLoyalty: false },
  { id: "PR-2026-002", name: "Loyalty $5 off · Spend > $30", type: "amount", value: 5, target: "minSpend", targetLabel: "Spend ≥ $30", stores: ["S-001","S-002","S-003"], starts: "01/05/2026", ends: "30/06/2026", redemptions: 280, revenue: 1400.00, status: "active", priority: 2, requiresLoyalty: true },
  { id: "PR-2026-003", name: "Vitamins · Buy 2 save $4",   type: "bogo", value: 4, target: "category", targetLabel: "Vitamins · 2+", stores: ["S-001","S-002","S-003"], starts: "01/05/2026", ends: "31/05/2026", redemptions: 88, revenue: 1742.30, status: "active", priority: 3, requiresLoyalty: false },
  { id: "PR-2026-004", name: "Hayfever bundle",            type: "amount", value: 3, target: "bundle",    targetLabel: "Loratadine + Cetirizine", stores: ["S-001","S-002"], starts: "12/05/2026", ends: "10/06/2026", redemptions: 24, revenue: 412.20, status: "active", priority: 4, requiresLoyalty: false },
  { id: "PR-2026-005", name: "Mother's Day skincare",      type: "percent", value: 20, target: "category", targetLabel: "Skincare", stores: ["S-001","S-002","S-003"], starts: "01/05/2026", ends: "12/05/2026", redemptions: 312, revenue: 6420.80, status: "ended",  priority: 1, requiresLoyalty: false },
  { id: "PR-2026-006", name: "Winter Wellness · Coming",   type: "percent", value: 15, target: "category", targetLabel: "Cold & flu", stores: ["S-001","S-002","S-003"], starts: "01/06/2026", ends: "31/07/2026", redemptions: 0, revenue: 0, status: "scheduled", priority: 1, requiresLoyalty: false },
  { id: "PR-2026-007", name: "NDSS pen-needle saver",      type: "amount", value: 1, target: "product", targetLabel: "BD Pen Needles", stores: ["S-001","S-002","S-003"], starts: "01/04/2026", ends: "31/12/2026", redemptions: 188, revenue: 188.00, status: "active", priority: 5, requiresLoyalty: false },
  { id: "PR-2026-008", name: "Camberwell only · Spacers", type: "percent", value: 10, target: "product", targetLabel: "Salbutamol Spacer", stores: ["S-001"], starts: "15/05/2026", ends: "31/05/2026", redemptions: 12, revenue: 168.00, status: "active", priority: 6, requiresLoyalty: false },
];

const HO_LOYALTY_TIERS = [
  { id: "bronze", name: "Bronze",  members: 1842, color: "#a0683e", spendThreshold: 0,    discount: 2, perks: ["2% off non-PBS", "Birthday treat"] },
  { id: "silver", name: "Silver",  members:  642, color: "#7d9097", spendThreshold: 400,  discount: 5, perks: ["5% off non-PBS", "Free delivery on $50+", "Birthday treat"] },
  { id: "gold",   name: "Gold",    members:  118, color: "#b8893e", spendThreshold: 1200, discount: 5, perks: ["5% off non-PBS", "Free delivery", "Priority counsel", "Bonus 2× points"] },
];

const HO_LOYALTY_KPI = {
  totalMembers: 2602,
  newThisMonth: 184,
  activeRate: 0.62,
  avgBasketLift: 14,
  monthlyRedemption: 2840,
};

// =================================================================
// PAYMENT ACCOUNTS — list
// =================================================================
function OfficeAccounts() {
  const { setScreen, setScreenState, pushToast } = window.useOffice();
  const [filter, setFilter] = hoUseState("all");
  const [q, setQ] = hoUseState("");

  const FILTERS = [
    { key: "all",        label: "All",         pred: () => true },
    { key: "business",   label: "Business",    pred: a => a.type === "business" },
    { key: "person",     label: "Person",      pred: a => a.type === "person" },
    { key: "overdue",    label: "Overdue",     pred: a => a.status === "overdue" },
    { key: "over-limit", label: "Over limit",  pred: a => a.status === "over-limit" },
    { key: "hold",       label: "On hold",     pred: a => a.status === "hold" },
  ];

  const list = HO_ACCOUNTS.filter(a => {
    if (!FILTERS.find(f => f.key === filter).pred(a)) return false;
    if (!q) return true;
    return (a.name + " " + a.id + " " + (a.abn || "")).toLowerCase().includes(q.toLowerCase());
  });

  const totals = {
    receivable: HO_ACCOUNTS.reduce((s, a) => s + a.balance, 0),
    overdue:    HO_ACCOUNTS.filter(a => a.status === "overdue").reduce((s, a) => s + a.balance, 0),
    overLimit:  HO_ACCOUNTS.filter(a => a.status === "over-limit").length,
    business:   HO_ACCOUNTS.filter(a => a.type === "business").length,
    person:     HO_ACCOUNTS.filter(a => a.type === "person").length,
  };

  return (
    <div className="off-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <span className="off-screen-eyebrow">Head-office function</span>
          <h2 className="off-screen-title">Payment accounts</h2>
        </div>
        <div className="off-screen-actions">
          <button className="btn btn--ghost btn--sm">Statement run</button>
          <button className="btn btn--secondary btn--sm"><OIcon name="printer"/> Aged receivables</button>
          <button className="btn btn--primary btn--sm" onClick={() => pushToast({kind:'sched', icon:'plus', title:'New account', meta:'Wizard would open here'})}>
            <OIcon name="plus"/> New account
          </button>
        </div>
      </header>

      <div className="off-screen-body">
        <div className="off-kpi-grid">
          <KpiCard label="Total receivable" value={oMoney(totals.receivable)} delta={{text: `${HO_ACCOUNTS.length} accounts · group total`}}/>
          <KpiCard label="Overdue balance" value={oMoney(totals.overdue)} delta={{dir: "down", text: "Chase up overdue accounts"}}/>
          <KpiCard label="Over credit limit" value={totals.overLimit} delta={{dir: "down", text: "Block further charges"}}/>
          <KpiCard label="Account mix" value={`${totals.business} biz · ${totals.person} pers`} delta={{text: "Across all stores"}}/>
        </div>

        <div className="off-table">
          <div className="off-table-toolbar">
            <div className="input-wrap" style={{flex:1, maxWidth:300}}>
              <OIcon name="search" className="input-wrap-icon"/>
              <input className="input" placeholder="Find account, ABN, holder…" value={q} onChange={e => setQ(e.target.value)} style={{height:34, fontSize:13}}/>
            </div>
            <div className="off-table-toolbar-sep"/>
            <div className="off-filters">
              {FILTERS.map(f => {
                const c = HO_ACCOUNTS.filter(f.pred).length;
                return (
                  <button key={f.key} className={"off-filter" + (filter === f.key ? " off-filter--active" : "")} onClick={() => setFilter(f.key)}>
                    {f.label} <span className="off-filter-count">{c}</span>
                  </button>
                );
              })}
            </div>
            <div style={{marginLeft:'auto', fontSize:12, color:'var(--text-muted)'}}>{list.length} of {HO_ACCOUNTS.length}</div>
          </div>

          <div className="off-grid" style={{gridTemplateColumns:'110px 1.6fr 90px 100px 90px 180px 110px 130px'}}>
            <div className="off-grid-headcell">Account</div>
            <div className="off-grid-headcell">Holder</div>
            <div className="off-grid-headcell">Type</div>
            <div className="off-grid-headcell">Home store</div>
            <div className="off-grid-headcell">Terms</div>
            <div className="off-grid-headcell">Available · Limit</div>
            <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Balance</div>
            <div className="off-grid-headcell">Status</div>

            {list.map(a => {
              const used = a.creditLimit > 0 ? Math.min(1, a.balance / a.creditLimit) : 0;
              const usedPct = Math.round(used * 100);
              const store = findS(a.store);
              return (
                <div key={a.id} className="off-grid-row" onClick={() => { setScreenState({ activeAccountId: a.id }); setScreen("accountDetail"); }}>
                  <div className="off-grid-cell off-cell-mono off-cell-strong">{a.id}</div>
                  <div className="off-grid-cell">
                    <div style={{display:'flex', alignItems:'center', gap:10}}>
                      <div className="off-side-user-av" style={{width:26, height:26, background: a.type === "business" ? 'var(--navy-700)' : 'var(--brand)', color:'#fff'}}>
                        <OIcon name={a.type === "business" ? "users" : "user"} width={12} height={12}/>
                      </div>
                      <div style={{minWidth:0}}>
                        <div className="off-cell-strong" style={{fontSize:13}}>{a.name}</div>
                        <div className="off-cell-mono off-muted" style={{fontSize:11}}>{a.type === "business" ? `ABN ${a.abn}` : a.contact}</div>
                      </div>
                    </div>
                  </div>
                  <div className="off-grid-cell">
                    <span className="badge badge--neutral" style={{textTransform:'none'}}>
                      <OIcon name={a.type === "business" ? "users" : "user"} width={11} height={11}/>
                      {a.type === "business" ? "Business" : "Person"}
                    </span>
                  </div>
                  <div className="off-grid-cell off-cell-mono">{store?.code} · {store?.name}</div>
                  <div className="off-grid-cell off-cell-mono off-muted">{a.terms}</div>
                  <div className="off-grid-cell">
                    <div className="inv-stockbar-label" style={{marginBottom:4}}>
                      <span className="tabular">{oMoney(Math.max(0, a.creditLimit - a.balance))}</span> of {oMoney(a.creditLimit)}
                    </div>
                    <div className={"inv-stockbar" + (usedPct > 95 ? " inv-stockbar--bad" : usedPct > 75 ? " inv-stockbar--warn" : "")}>
                      <div style={{width: Math.min(100, usedPct) + "%"}}/>
                    </div>
                  </div>
                  <div className="off-grid-cell off-cell-num off-cell-strong" style={{color: a.balance === 0 ? 'var(--text-subtle)' : 'var(--text)'}}>
                    {oMoney(a.balance)}
                  </div>
                  <div className="off-grid-cell">
                    {a.status === "active"     && <span className="badge badge--paid"><span className="badge-dot"/> Active</span>}
                    {a.status === "overdue"    && <span className="badge badge--void"><span className="badge-dot"/> Overdue · {a.overdueDays}d</span>}
                    {a.status === "over-limit" && <span className="badge badge--hold"><span className="badge-dot"/> Over limit</span>}
                    {a.status === "hold"       && <span className="badge badge--neutral"><span className="badge-dot"/> On hold</span>}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}

// =================================================================
// PAYMENT ACCOUNT — detail (compact admin view)
// =================================================================
function OfficeAccountDetail() {
  const { setScreen, screenState, pushToast } = window.useOffice();
  const a = HO_ACCOUNTS.find(x => x.id === screenState.activeAccountId) || HO_ACCOUNTS[0];
  const usedPct = a.creditLimit > 0 ? Math.round((a.balance / a.creditLimit) * 100) : 0;

  return (
    <div className="off-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <span className="off-screen-eyebrow">Account · {a.id}</span>
          <h2 className="off-screen-title">{a.name}</h2>
        </div>
        <div className="off-screen-actions">
          <button className="btn btn--ghost btn--sm" onClick={() => setScreen("accounts")}>
            <OIcon name="chevron-right" style={{transform:'rotate(180deg)'}}/> Accounts
          </button>
          <button className="btn btn--secondary btn--sm"><OIcon name="printer"/> Statement</button>
          <button className="btn btn--primary btn--sm" onClick={() => pushToast({kind:'paid', icon:'check-circle', title:`Payment recorded · ${a.name}`})}>
            <OIcon name="card"/> Receive payment
          </button>
        </div>
      </header>

      <div className="off-screen-body">
        <div className="off-kpi-grid">
          <KpiCard label="Current balance" value={oMoney(a.balance)} delta={{text: `Last charge ${a.lastCharge}`}}/>
          <KpiCard label="Credit limit" value={oMoney(a.creditLimit)} delta={{text: `${usedPct}% used`}}/>
          <KpiCard label="Available" value={oMoney(Math.max(0, a.creditLimit - a.balance))} delta={{dir: usedPct > 95 ? "down" : "up", text: usedPct > 95 ? "Over limit" : "Within terms"}}/>
          <KpiCard label="Monthly average" value={oMoney(a.monthlyAvg)} delta={{text: "Last 6 months"}}/>
        </div>

        <div style={{display:'grid', gridTemplateColumns:'2fr 1fr', gap:14}}>
          <div className="off-card">
            <div className="off-card-header">
              <h3 className="off-card-title">Recent activity</h3>
              <button className="btn btn--ghost btn--sm">View full ledger</button>
            </div>
            <div className="off-grid" style={{gridTemplateColumns:'110px 110px 1fr 60px 110px 110px'}}>
              <div className="off-grid-headcell">When</div>
              <div className="off-grid-headcell">Type</div>
              <div className="off-grid-headcell">Description</div>
              <div className="off-grid-headcell">By</div>
              <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Amount</div>
              <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Balance</div>
              {[
                { ts:"Today 14:12", kind:"charge",  who:"SK", desc:"Metformin XR · M. Tan (room 14)",      amt: 31.40, bal: a.balance },
                { ts:"Today 11:48", kind:"charge",  who:"RP", desc:"Dispense ×3 · Ana Costa (room 09)",    amt: 92.20, bal: a.balance - 31.40 },
                { ts:"Today 10:14", kind:"charge",  who:"JL", desc:"DAA refill week 22 · 12 residents",    amt: 144.00, bal: a.balance - 123.60 },
                { ts:"Yesterday",   kind:"charge",  who:"SK", desc:"Webster pack · H. Whitlock (room 22)", amt: 84.00, bal: a.balance - 267.60 },
                { ts:"20/05/2026",  kind:"charge",  who:"JL", desc:"Dispense ×6 · weekly batch",           amt: 412.65, bal: a.balance - 351.60 },
                { ts:"18/05/2026",  kind:"credit",  who:"SK", desc:"Damaged stock credit · S. Wilson",     amt: -28.20, bal: a.balance - 764.25 },
                { ts:"12/05/2026",  kind:"payment", who:"—",  desc:"Payment received · BPay",              amt: -4800.00, bal: a.balance - 736.05 },
              ].map((t, i) => (
                <div key={i} className="off-grid-row">
                  <div className="off-grid-cell off-mono off-muted">{t.ts}</div>
                  <div className="off-grid-cell">
                    {t.kind === "charge"  && <span className="badge badge--neutral"><span className="badge-dot"/> Charge</span>}
                    {t.kind === "payment" && <span className="badge badge--paid"><span className="badge-dot"/> Payment</span>}
                    {t.kind === "credit"  && <span className="badge badge--hold"><span className="badge-dot"/> Credit</span>}
                  </div>
                  <div className="off-grid-cell">{t.desc}</div>
                  <div className="off-grid-cell"><span className="audit-actor" style={{background:'var(--brand)', color:'#fff'}}>{t.who}</span></div>
                  <div className="off-grid-cell off-cell-num" style={{color: t.amt < 0 ? 'var(--paid)' : 'var(--text)', fontWeight:500}}>{oMoney(t.amt)}</div>
                  <div className="off-grid-cell off-cell-num off-cell-strong">{oMoney(t.bal)}</div>
                </div>
              ))}
            </div>
          </div>

          <div style={{display:'flex', flexDirection:'column', gap:14}}>
            <div className="off-card">
              <h3 className="off-card-title">Account details</h3>
              <div style={{display:'flex', flexDirection:'column', gap:10, fontSize:13}}>
                <Row label="Type"        value={a.type === "business" ? "Business" : "Person"}/>
                {a.abn !== "—" && <Row label="ABN" value={a.abn} mono/>}
                <Row label="Home store"  value={findS(a.store)?.name}/>
                <Row label="Terms"       value={a.terms}/>
                <Row label="Contact"     value={a.contact}/>
                <Row label="Authorised"  value={`${a.authorised} ${a.authorised === 1 ? "person" : "people"}`}/>
              </div>
            </div>

            {a.status === "overdue" && (
              <div className="off-card" style={{borderColor:'var(--void-border)', background:'var(--void-bg)'}}>
                <h3 className="off-card-title" style={{color:'var(--void)'}}>Overdue · {a.overdueDays} days</h3>
                <div style={{fontSize:13, color:'var(--void-text)'}}>
                  Charges blocked until payment received. SMS reminder sent — no response.
                </div>
                <div style={{display:'flex', gap:6}}>
                  <button className="btn btn--secondary btn--sm" style={{flex:1}}>Reminder</button>
                  <button className="btn btn--primary btn--sm" style={{flex:1, background:'var(--void)'}}>Receive payment</button>
                </div>
              </div>
            )}

            <div className="off-card">
              <h3 className="off-card-title">Quick actions</h3>
              <button className="btn btn--secondary btn--block btn--sm"><OIcon name="printer"/> Print statement</button>
              <button className="btn btn--secondary btn--block btn--sm"><OIcon name="users"/> Manage authorised</button>
              <button className="btn btn--secondary btn--block btn--sm"><OIcon name="edit"/> Change credit limit</button>
              <button className="btn btn--ghost btn--block btn--sm" style={{color:'var(--void)'}}>Suspend charges</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function Row({ label, value, mono }) {
  return (
    <div style={{display:'flex', justifyContent:'space-between', alignItems:'baseline', gap:12}}>
      <span style={{color:'var(--text-muted)'}}>{label}</span>
      <span style={{fontWeight:500, color:'var(--text)', fontFamily: mono ? 'var(--font-mono)' : 'inherit', fontSize: mono ? 12 : 13}}>{value}</span>
    </div>
  );
}

// =================================================================
// PROMOTIONS — list + designer
// =================================================================
function Promotions() {
  const { setScreen, setScreenState, pushToast } = window.useOffice();
  const [tab, setTab] = hoUseState("active");

  const FILTER = {
    active:    p => p.status === "active",
    scheduled: p => p.status === "scheduled",
    ended:     p => p.status === "ended",
    all:       () => true,
  };

  const list = HO_PROMOS.filter(FILTER[tab]);
  const totals = {
    redemptionsMTD: HO_PROMOS.reduce((s, p) => s + p.redemptions, 0),
    revenue:        HO_PROMOS.reduce((s, p) => s + p.revenue, 0),
    active:         HO_PROMOS.filter(p => p.status === "active").length,
    scheduled:      HO_PROMOS.filter(p => p.status === "scheduled").length,
  };

  return (
    <div className="off-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <span className="off-screen-eyebrow">Head-office function</span>
          <h2 className="off-screen-title">Promotions</h2>
        </div>
        <div className="off-screen-actions">
          <button className="btn btn--ghost btn--sm">Export</button>
          <button className="btn btn--primary btn--sm" onClick={() => setScreen("promoNew")}>
            <OIcon name="plus"/> New promotion
          </button>
        </div>
      </header>

      <div className="off-subtabs">
        <button className={"off-subtab" + (tab === "active" ? " off-subtab--active" : "")} onClick={() => setTab("active")}>
          Active <span style={{marginLeft:6, fontSize:10, background:'var(--paid)', color:'var(--paid-fg)', padding:'1px 6px', borderRadius:99, fontWeight:600}}>{totals.active}</span>
        </button>
        <button className={"off-subtab" + (tab === "scheduled" ? " off-subtab--active" : "")} onClick={() => setTab("scheduled")}>
          Scheduled <span style={{marginLeft:6, fontSize:10, background:'var(--hold)', color:'var(--hold-fg)', padding:'1px 6px', borderRadius:99, fontWeight:600}}>{totals.scheduled}</span>
        </button>
        <button className={"off-subtab" + (tab === "ended" ? " off-subtab--active" : "")} onClick={() => setTab("ended")}>Ended</button>
        <button className={"off-subtab" + (tab === "all" ? " off-subtab--active" : "")} onClick={() => setTab("all")}>All</button>
      </div>

      <div className="off-screen-body">
        <div className="off-kpi-grid">
          <KpiCard label="Redemptions · 30d"     value={totals.redemptionsMTD.toLocaleString()} delta={{dir:"up", text:"▲ 22% vs prior month"}}/>
          <KpiCard label="Promo-driven revenue"  value={oMoney(totals.revenue)} delta={{text: "Across all stores"}}/>
          <KpiCard label="Active promotions"     value={totals.active} delta={{text: `${totals.scheduled} scheduled to start`}}/>
          <KpiCard label="Avg lift on basket"    value="+14%" delta={{dir:"up", text:"Promo vs non-promo"}}/>
        </div>

        <div className="off-table">
          <div className="off-grid" style={{gridTemplateColumns:'1.6fr 110px 130px 1fr 130px 100px 110px 110px'}}>
            <div className="off-grid-headcell">Promotion</div>
            <div className="off-grid-headcell">Discount</div>
            <div className="off-grid-headcell">Applies to</div>
            <div className="off-grid-headcell">Stores</div>
            <div className="off-grid-headcell">Dates</div>
            <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Redeems</div>
            <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Revenue</div>
            <div className="off-grid-headcell">Status</div>

            {list.map(p => (
              <div key={p.id} className="off-grid-row" onClick={() => { setScreenState({ activePromoId: p.id }); setScreen("promoNew"); }}>
                <div className="off-grid-cell off-cell-strong">
                  {p.name}
                  <div className="off-mono off-muted" style={{fontSize:11, marginTop:2}}>{p.id}</div>
                </div>
                <div className="off-grid-cell off-cell-strong">
                  {p.type === "percent" ? `${p.value}%` : p.type === "amount" ? `$${p.value} off` : p.type === "bogo" ? `$${p.value} bundle` : `$${p.value}`}
                </div>
                <div className="off-grid-cell">{p.targetLabel}{p.requiresLoyalty && <span className="badge badge--brand" style={{marginLeft:6, fontSize:10}}>Loyalty</span>}</div>
                <div className="off-grid-cell off-mono off-muted">
                  {p.stores.length === 3 ? "All stores" : p.stores.map(id => findS(id)?.code).join(", ")}
                </div>
                <div className="off-grid-cell off-mono off-muted">{p.starts} → {p.ends.split("/").slice(0,2).join("/")}</div>
                <div className="off-grid-cell off-cell-num">{p.redemptions}</div>
                <div className="off-grid-cell off-cell-num off-cell-strong">{p.revenue > 0 ? oMoney(p.revenue) : "—"}</div>
                <div className="off-grid-cell">
                  {p.status === "active"    && <span className="badge badge--paid"><span className="badge-dot"/> Active</span>}
                  {p.status === "scheduled" && <span className="badge badge--hold"><span className="badge-dot"/> Scheduled</span>}
                  {p.status === "ended"     && <span className="badge badge--neutral"><span className="badge-dot"/> Ended</span>}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function PromoNew() {
  const { setScreen, pushToast, screenState } = window.useOffice();
  const editing = screenState.activePromoId ? HO_PROMOS.find(p => p.id === screenState.activePromoId) : null;
  const [form, setForm] = hoUseState(editing || {
    name: "", type: "percent", value: 10, target: "category", targetLabel: "Vitamins",
    stores: ["S-001","S-002","S-003"], starts: "27/05/2026", ends: "30/06/2026",
    requiresLoyalty: false, priority: 5,
  });

  function set(k, v) { setForm(f => ({ ...f, [k]: v })); }
  function toggleStore(id) { setForm(f => ({ ...f, stores: f.stores.includes(id) ? f.stores.filter(x => x !== id) : [...f.stores, id] })); }

  function submit() {
    pushToast({ kind:'paid', icon:'check-circle', title:`Promotion ${editing ? 'updated' : 'created'} · ${form.name}`, meta: `${form.type === "percent" ? form.value + "%" : "$" + form.value + " off"} · ${form.stores.length} stores` });
    setScreen("promotions");
  }

  return (
    <div className="off-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <span className="off-screen-eyebrow">Promotions</span>
          <h2 className="off-screen-title">{editing ? `Edit · ${editing.name}` : "New promotion"}</h2>
        </div>
        <div className="off-screen-actions">
          <button className="btn btn--ghost btn--sm" onClick={() => setScreen("promotions")}>Cancel</button>
          <button className="btn btn--secondary btn--sm">Save as draft</button>
          <button className="btn btn--primary btn--sm" onClick={submit} disabled={!form.name}>
            <OIcon name="check"/> {editing ? "Save changes" : "Launch promotion"}
          </button>
        </div>
      </header>

      <div className="off-screen-body" style={{maxWidth:1100, margin:'0 auto', width:'100%'}}>
        <div style={{display:'grid', gridTemplateColumns:'1fr 320px', gap:16}}>
          <div style={{display:'flex', flexDirection:'column', gap:14}}>
            <div className="off-card">
              <div className="wiz-step-header"><span className="wiz-step-number">1</span><h3 className="wiz-step-title">Name &amp; identification</h3></div>
              <div className="field">
                <label className="field-label">Promotion name <span className="field-required">*</span></label>
                <input className="input" value={form.name} onChange={e => set("name", e.target.value)} placeholder="e.g. Winter Wellness 15% off" autoFocus/>
              </div>
            </div>

            <div className="off-card">
              <div className="wiz-step-header"><span className="wiz-step-number">2</span><h3 className="wiz-step-title">Discount</h3></div>
              <div style={{display:'grid', gridTemplateColumns:'repeat(2, 1fr)', gap:14}}>
                <div className="field">
                  <label className="field-label">Type</label>
                  <select className="input select" value={form.type} onChange={e => set("type", e.target.value)}>
                    <option value="percent">% off</option>
                    <option value="amount">$ off</option>
                    <option value="bogo">Bundle / multi-buy</option>
                  </select>
                </div>
                <div className="field">
                  <label className="field-label">Value</label>
                  <input className="input tabular" value={form.value} onChange={e => set("value", parseFloat(e.target.value) || 0)} placeholder={form.type === "percent" ? "15" : "5.00"}/>
                </div>
              </div>
            </div>

            <div className="off-card">
              <div className="wiz-step-header"><span className="wiz-step-number">3</span><h3 className="wiz-step-title">Applies to</h3></div>
              <div style={{display:'grid', gridTemplateColumns:'repeat(2, 1fr)', gap:14}}>
                <div className="field">
                  <label className="field-label">Target</label>
                  <select className="input select" value={form.target} onChange={e => set("target", e.target.value)}>
                    <option value="category">Whole category</option>
                    <option value="product">Single product</option>
                    <option value="bundle">Bundle (2+ items)</option>
                    <option value="minSpend">Minimum basket</option>
                  </select>
                </div>
                <div className="field">
                  <label className="field-label">{form.target === "category" ? "Category" : form.target === "product" ? "Product" : form.target === "minSpend" ? "Minimum spend" : "Bundle"}</label>
                  {form.target === "category" ? (
                    <select className="input select" value={form.targetLabel} onChange={e => set("targetLabel", e.target.value)}>
                      {[...new Set(OD.PRODUCTS.map(p => p.category))].map(c => <option key={c}>{c}</option>)}
                    </select>
                  ) : (
                    <input className="input" value={form.targetLabel} onChange={e => set("targetLabel", e.target.value)}/>
                  )}
                </div>
              </div>
              <div style={{marginTop:8}}>
                <label className="checkbox">
                  <input type="checkbox" checked={form.requiresLoyalty} onChange={e => set("requiresLoyalty", e.target.checked)}/>
                  <span className="checkbox-box"><OIcon name="check" width={14} height={14}/></span>
                  <span>Loyalty members only</span>
                </label>
              </div>
            </div>

            <div className="off-card">
              <div className="wiz-step-header"><span className="wiz-step-number">4</span><h3 className="wiz-step-title">Stores &amp; dates</h3></div>
              <div className="field">
                <label className="field-label">Stores</label>
                <div style={{display:'flex', gap:8, flexWrap:'wrap'}}>
                  {OD.STORES.map(s => (
                    <label key={s.id} style={{display:'flex', alignItems:'center', gap:8, padding:'8px 12px', border:'1px solid ' + (form.stores.includes(s.id) ? 'var(--brand)' : 'var(--border)'), background: form.stores.includes(s.id) ? 'var(--brand-bg)' : 'transparent', borderRadius:8, cursor:'pointer'}}>
                      <input type="checkbox" checked={form.stores.includes(s.id)} onChange={() => toggleStore(s.id)}/>
                      <span style={{fontSize:13, fontWeight:500}}>{s.name}</span>
                    </label>
                  ))}
                </div>
              </div>
              <div style={{display:'grid', gridTemplateColumns:'repeat(2, 1fr)', gap:14}}>
                <div className="field">
                  <label className="field-label">Starts</label>
                  <input className="input tabular" value={form.starts} onChange={e => set("starts", e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Ends</label>
                  <input className="input tabular" value={form.ends} onChange={e => set("ends", e.target.value)}/>
                </div>
              </div>
            </div>
          </div>

          {/* Right — preview */}
          <div style={{display:'flex', flexDirection:'column', gap:14, position:'sticky', top:0}}>
            <div className="off-card">
              <div className="off-card-title">Preview · shelf flag</div>
              <div style={{background:'linear-gradient(135deg, var(--teal-700), var(--teal-800))', color:'#fff', padding:18, borderRadius:10}}>
                <div style={{fontSize:11, textTransform:'uppercase', letterSpacing:'0.08em', opacity:0.8, fontWeight:500}}>Special</div>
                <div style={{fontSize:32, fontWeight:600, letterSpacing:'-0.025em', lineHeight:1, marginTop:4}}>
                  {form.type === "percent" ? `${form.value}%` : `$${form.value}`}
                </div>
                <div style={{fontSize:14, marginTop:2, opacity:0.9}}>{form.type === "percent" ? "off" : "off"} · {form.targetLabel}</div>
                <div style={{fontSize:11, opacity:0.6, marginTop:10, paddingTop:8, borderTop:'1px solid rgba(255,255,255,0.18)'}}>
                  Until {form.ends}{form.requiresLoyalty && " · Loyalty members"}
                </div>
              </div>
            </div>

            <div className="off-card">
              <div className="off-card-title">When it goes live</div>
              <div style={{fontSize:13, color:'var(--text-muted)', lineHeight:1.5}}>
                <strong style={{color:'var(--text)'}}>{form.name || "This promotion"}</strong> will activate at <strong style={{color:'var(--text)'}}>{form.stores.length} {form.stores.length === 1 ? "store" : "stores"}</strong> from <strong style={{color:'var(--text)'}}>{form.starts}</strong> to <strong style={{color:'var(--text)'}}>{form.ends}</strong>.
                <br/><br/>POS will auto-apply at checkout. Receipts show the line-item discount.
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// =================================================================
// LOYALTY
// =================================================================
function Loyalty() {
  const { pushToast } = window.useOffice();
  const [tab, setTab] = hoUseState("tiers");

  return (
    <div className="off-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <span className="off-screen-eyebrow">Head-office function</span>
          <h2 className="off-screen-title">Loyalty programme</h2>
        </div>
        <div className="off-screen-actions">
          <button className="btn btn--ghost btn--sm">Export members</button>
          <button className="btn btn--primary btn--sm" onClick={() => pushToast({kind:'paid', icon:'check', title:'Programme settings saved'})}>
            <OIcon name="check"/> Save changes
          </button>
        </div>
      </header>

      <div className="off-subtabs">
        <button className={"off-subtab" + (tab === "tiers" ? " off-subtab--active" : "")} onClick={() => setTab("tiers")}>Tiers &amp; perks</button>
        <button className={"off-subtab" + (tab === "earn" ? " off-subtab--active" : "")} onClick={() => setTab("earn")}>Earn rules</button>
        <button className={"off-subtab" + (tab === "rewards" ? " off-subtab--active" : "")} onClick={() => setTab("rewards")}>Rewards</button>
        <button className={"off-subtab" + (tab === "members" ? " off-subtab--active" : "")} onClick={() => setTab("members")}>Members</button>
        <button className={"off-subtab" + (tab === "campaigns" ? " off-subtab--active" : "")} onClick={() => setTab("campaigns")}>Campaigns</button>
      </div>

      <div className="off-screen-body">
        <div className="off-kpi-grid">
          <KpiCard label="Total members" value={HO_LOYALTY_KPI.totalMembers.toLocaleString()} delta={{dir:"up", text:`+${HO_LOYALTY_KPI.newThisMonth} this month`}}/>
          <KpiCard label="Active rate · 90d" value={`${Math.round(HO_LOYALTY_KPI.activeRate * 100)}%`} delta={{text:"Visited at least once"}}/>
          <KpiCard label="Avg basket lift" value={`+${HO_LOYALTY_KPI.avgBasketLift}%`} delta={{dir:"up", text:"Members vs non-members"}}/>
          <KpiCard label="Redemptions MTD" value={`$${HO_LOYALTY_KPI.monthlyRedemption.toLocaleString()}`} delta={{text:"Discounts attributed"}}/>
        </div>

        {tab === "tiers" && (
          <div style={{display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:14}}>
            {HO_LOYALTY_TIERS.map(t => (
              <div key={t.id} className="off-card" style={{borderTop: `4px solid ${t.color}`}}>
                <div style={{display:'flex', alignItems:'center', gap:12}}>
                  <div style={{width:44, height:44, borderRadius:99, background:t.color, color:'#fff', display:'grid', placeItems:'center'}}>
                    <OIcon name="loyalty" width={20} height={20}/>
                  </div>
                  <div>
                    <div style={{fontSize:18, fontWeight:600, letterSpacing:'-0.015em'}}>{t.name}</div>
                    <div style={{fontSize:12, color:'var(--text-muted)'}}>{t.members.toLocaleString()} members</div>
                  </div>
                </div>
                <div style={{display:'flex', flexDirection:'column', gap:8, fontSize:13, paddingTop:6, borderTop:'1px solid var(--border-subtle)'}}>
                  <div style={{display:'flex', justifyContent:'space-between'}}>
                    <span style={{color:'var(--text-muted)'}}>Spend threshold</span>
                    <strong className="tabular">${t.spendThreshold}/year</strong>
                  </div>
                  <div style={{display:'flex', justifyContent:'space-between'}}>
                    <span style={{color:'var(--text-muted)'}}>Standard discount</span>
                    <strong className="tabular">{t.discount}%</strong>
                  </div>
                </div>
                <div>
                  <div style={{fontSize:11, textTransform:'uppercase', letterSpacing:'0.06em', color:'var(--text-subtle)', fontWeight:500, marginBottom:6}}>Perks</div>
                  <ul style={{margin:0, paddingLeft:18, fontSize:13, color:'var(--text-muted)', lineHeight:1.7}}>
                    {t.perks.map((p, i) => <li key={i}>{p}</li>)}
                  </ul>
                </div>
                <button className="btn btn--secondary btn--block btn--sm"><OIcon name="edit"/> Edit tier</button>
              </div>
            ))}
          </div>
        )}

        {tab === "earn" && (
          <div className="off-card" style={{maxWidth:720}}>
            <h3 className="off-card-title">Points &amp; earn rules</h3>
            <div className="settings-row">
              <div><div className="settings-row-title">Earn rate</div><div className="settings-row-desc">Points per dollar spent on non-PBS items.</div></div>
              <input className="input tabular" defaultValue="1 point per $1"/>
            </div>
            <div className="settings-row">
              <div><div className="settings-row-title">PBS items</div><div className="settings-row-desc">Whether PBS prescriptions earn points.</div></div>
              <select className="input select" defaultValue="no"><option value="no">Don't earn</option><option value="yes">Earn at half rate</option></select>
            </div>
            <div className="settings-row">
              <div><div className="settings-row-title">Points expiry</div><div className="settings-row-desc">After how long unused points expire.</div></div>
              <select className="input select" defaultValue="12"><option>6 months</option><option value="12">12 months</option><option>24 months</option><option>Never</option></select>
            </div>
            <div className="settings-row">
              <div><div className="settings-row-title">Birthday bonus</div><div className="settings-row-desc">Double points in member's birthday month.</div></div>
              <label className="toggle"><input type="checkbox" defaultChecked/><span className="toggle-track"><span className="toggle-thumb"/></span><span style={{fontSize:13}}>Enabled</span></label>
            </div>
            <div className="settings-row">
              <div><div className="settings-row-title">Sign-up bonus</div><div className="settings-row-desc">Points credited to new members.</div></div>
              <input className="input tabular" defaultValue="50 points"/>
            </div>
          </div>
        )}

        {tab === "rewards" && (
          <div className="off-table">
            <div className="off-grid" style={{gridTemplateColumns:'1.6fr 110px 130px 130px 100px 110px'}}>
              <div className="off-grid-headcell">Reward</div>
              <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Points cost</div>
              <div className="off-grid-headcell">Tier required</div>
              <div className="off-grid-headcell">Type</div>
              <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Redeems</div>
              <div className="off-grid-headcell">Status</div>
              {[
                { name: "$5 off voucher", cost: 100,  tier: "Any",    type: "Voucher", redeems: 482, status: "active" },
                { name: "$10 off voucher", cost: 200, tier: "Any",    type: "Voucher", redeems: 312, status: "active" },
                { name: "Free delivery",   cost: 150, tier: "Any",    type: "Service", redeems: 188, status: "active" },
                { name: "Multivitamin · free", cost: 400, tier: "Silver+", type: "Product", redeems: 22, status: "active" },
                { name: "MedsCheck consult", cost: 600, tier: "Gold",     type: "Service", redeems: 8,  status: "active" },
                { name: "Sunscreen bundle", cost: 300, tier: "Any",   type: "Product", redeems: 0,  status: "scheduled" },
              ].map((r, i) => (
                <div key={i} className="off-grid-row">
                  <div className="off-grid-cell off-cell-strong">{r.name}</div>
                  <div className="off-grid-cell off-cell-num">{r.cost}</div>
                  <div className="off-grid-cell">{r.tier}</div>
                  <div className="off-grid-cell"><span className="badge badge--neutral">{r.type}</span></div>
                  <div className="off-grid-cell off-cell-num">{r.redeems}</div>
                  <div className="off-grid-cell">
                    {r.status === "active" ? <span className="badge badge--paid"><span className="badge-dot"/> Active</span> : <span className="badge badge--hold"><span className="badge-dot"/> Scheduled</span>}
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {tab === "members" && (
          <div className="off-table">
            <div className="off-grid" style={{gridTemplateColumns:'40px 1.4fr 1fr 80px 100px 110px 120px'}}>
              <div className="off-grid-headcell"></div>
              <div className="off-grid-headcell">Member</div>
              <div className="off-grid-headcell">Home store</div>
              <div className="off-grid-headcell">Tier</div>
              <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Points</div>
              <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>YTD spend</div>
              <div className="off-grid-headcell">Last visit</div>
              {[
                { id:"u01", first:"Mei",     last:"Tan",       tier:"Silver", store:"S-001", points: 432, ytd: 1240, lastVisit:"3 days ago" },
                { id:"u02", first:"Jordan",  last:"Riley",     tier:"Bronze", store:"S-001", points: 88,  ytd: 320,  lastVisit:"Today" },
                { id:"u03", first:"Ana",     last:"Costa",     tier:"Gold",   store:"S-003", points: 1840,ytd: 2410, lastVisit:"Yesterday" },
                { id:"u05", first:"Priya",   last:"Sharma",    tier:"Silver", store:"S-001", points: 318, ytd:  680, lastVisit:"5 days ago" },
                { id:"u06", first:"Nadia",   last:"Khoury",    tier:"Bronze", store:"S-001", points: 142, ytd:  220, lastVisit:"Today" },
                { id:"u09", first:"Henry",   last:"Whitlock",  tier:"Gold",   store:"S-001", points: 2210,ytd: 3120, lastVisit:"2 days ago" },
                { id:"u10", first:"Beatrix", last:"Lim",       tier:"Bronze", store:"S-002", points: 64,  ytd:  140, lastVisit:"Today" },
              ].map(m => {
                const tier = HO_LOYALTY_TIERS.find(t => t.name === m.tier);
                return (
                  <div key={m.id} className="off-grid-row">
                    <div className="off-grid-cell"><div className="off-side-user-av" style={{width:28,height:28,background:'var(--brand)', color:'#fff'}}>{(m.first[0]+m.last[0]).toUpperCase()}</div></div>
                    <div className="off-grid-cell off-cell-strong">{m.first} {m.last}</div>
                    <div className="off-grid-cell off-cell-mono">{findS(m.store)?.code} · {findS(m.store)?.name}</div>
                    <div className="off-grid-cell"><span className="badge" style={{background: tier.color + "22", color: tier.color, border: "1px solid " + tier.color + "44"}}>{m.tier}</span></div>
                    <div className="off-grid-cell off-cell-num off-cell-strong">{m.points.toLocaleString()}</div>
                    <div className="off-grid-cell off-cell-num">${m.ytd.toLocaleString()}</div>
                    <div className="off-grid-cell off-mono off-muted">{m.lastVisit}</div>
                  </div>
                );
              })}
            </div>
          </div>
        )}

        {tab === "campaigns" && (
          <div className="off-table">
            <div className="off-grid" style={{gridTemplateColumns:'1.6fr 130px 120px 130px 110px 110px'}}>
              <div className="off-grid-headcell">Campaign</div>
              <div className="off-grid-headcell">Channel</div>
              <div className="off-grid-headcell">Audience</div>
              <div className="off-grid-headcell">Sent</div>
              <div className="off-grid-headcell" style={{justifyContent:'flex-end'}}>Redeems</div>
              <div className="off-grid-headcell">Status</div>
              {[
                { name: "Mother's Day · Gold members",   ch: "SMS", aud: "Gold",  sent: "08/05/2026", reds: 64,  status: "complete" },
                { name: "Bronze re-engage · no visit 60d", ch: "Email", aud: "Bronze · inactive", sent: "15/05/2026", reds: 38, status: "complete" },
                { name: "Hayfever bundle · all members", ch: "SMS", aud: "All",   sent: "12/05/2026", reds: 24,  status: "complete" },
                { name: "Winter Wellness · launch",      ch: "Email",aud: "All",   sent: "Scheduled 01/06", reds: 0, status: "scheduled" },
                { name: "Birthday bonus · May",          ch: "SMS",  aud: "Birthdays", sent: "01/05/2026", reds: 122, status: "complete" },
              ].map((c, i) => (
                <div key={i} className="off-grid-row">
                  <div className="off-grid-cell off-cell-strong">{c.name}</div>
                  <div className="off-grid-cell"><span className="badge badge--neutral">{c.ch}</span></div>
                  <div className="off-grid-cell">{c.aud}</div>
                  <div className="off-grid-cell off-mono off-muted">{c.sent}</div>
                  <div className="off-grid-cell off-cell-num">{c.reds}</div>
                  <div className="off-grid-cell">
                    {c.status === "complete" ? <span className="badge badge--paid"><span className="badge-dot"/> Complete</span> : <span className="badge badge--hold"><span className="badge-dot"/> Scheduled</span>}
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

window.OFFICE_SCREENS = Object.assign(window.OFFICE_SCREENS || {}, {
  accounts: OfficeAccounts,
  accountDetail: OfficeAccountDetail,
  promotions: Promotions,
  promoNew: PromoNew,
  loyalty: Loyalty,
});
