// Wallet.jsx — credit wallet system for The Amos Project.
//
// One credit = $0.10.  Packs: 50 cr ($5) · 200 cr ($20, +10% bonus) · 1000 cr ($100, +20% bonus).
//
// Exports on window:
//   useWallet()              — hook, returns { balance, history, addCredits, spend, open, close, ... }
//   WalletProvider           — wraps the app, holds state + persists to localStorage
//   WalletChip               — topbar pill showing balance (click → opens WalletPanel)
//   WalletPanel              — slide-out panel with balance, recent spend, top-up CTA
//   AddCreditsModal          — three-pack purchase modal
//   ConfirmSpendSheet        — confirm-to-spend sheet (shown before paid actions run)
//   creditFmt(credits)       — "95 cr" formatter
//   dollarsToCreditsCost(d)  — convert a dollar amount (API cost) to marked-up credit price
//                              (markup is 100%: if API costs $0.10, we charge $0.20 = 2 cr)

(function(){
  const CREDIT_CENT_VALUE = 10;    // 1 credit = $0.10 → 10 cents
  const MARKUP             = 2.0;   // 100% markup on API cost
  const STORE_KEY          = 'amos.wallet.v1';

  // ── Catalog of purchasable packs ─────────────────────────
  const PACKS = [
    {
      id: 'starter',
      label: 'Starter',
      dollars: 5,
      credits: 50,
      bonus: 0,
      tagline: 'Try a few pericopes',
      perks: [
        'Up to ~20 single-verse deep dives',
        'Or 1 full chapter with apparatus',
        'Credits never expire'
      ]
    },
    {
      id: 'scholar',
      label: 'Scholar',
      dollars: 20,
      credits: 220,                  // 200 + 10% bonus = 220
      baseCredits: 200,
      bonus: 20,
      bonusPct: 10,
      tagline: 'Most commissions in one go',
      popular: true,
      perks: [
        'A full pericope analysis every week',
        'Or a preterocanonical book translation',
        '10% bonus credits included'
      ]
    },
    {
      id: 'patron',
      label: 'Patron',
      dollars: 100,
      credits: 1200,                 // 1000 + 20% bonus = 1200
      baseCredits: 1000,
      bonus: 200,
      bonusPct: 20,
      tagline: 'Underwrite a whole book',
      perks: [
        'Commission a complete Bible book',
        'Or a Ge\u02bcez edition with apparatus',
        '20% bonus credits — the best value'
      ]
    }
  ];

  // ── Helpers ──────────────────────────────────────────────
  function creditFmt(n) {
    const v = Math.round(n);
    return v.toLocaleString() + ' cr';
  }
  function dollarsToCreditsCost(dollars) {
    // Charge = API cost × markup.  Convert to credits (1 cr = $0.10).
    const charge = dollars * MARKUP;
    return Math.max(1, Math.round(charge / (CREDIT_CENT_VALUE / 100)));
  }

  // ── State persistence ────────────────────────────────────
  function loadState() {
    try {
      const raw = localStorage.getItem(STORE_KEY);
      if (raw) return JSON.parse(raw);
    } catch (e) {}
    // Default: signed-in Jordan Reed starts with a Starter pack worth to show state.
    return {
      balance: 137,
      history: [
        { id: 'h3', kind: 'spend',    label: 'Odes → Catalan translation',        credits: -19, at: Date.now() - 1000*60*60*24*6 },
        { id: 'h2', kind: 'spend',    label: 'Rom 9:1–5 · Full pericope analysis', credits: -11, at: Date.now() - 1000*60*60*24*2 },
        { id: 'h1', kind: 'purchase', label: 'Scholar pack',                      credits: +220, at: Date.now() - 1000*60*60*24*9 }
      ]
    };
  }
  function saveState(s) {
    try { localStorage.setItem(STORE_KEY, JSON.stringify(s)); } catch (e) {}
  }

  // ── Context ──────────────────────────────────────────────
  const WalletCtx = React.createContext(null);
  function useWallet() { return React.useContext(WalletCtx); }

  function WalletProvider({ children }) {
    const [state, setState] = React.useState(loadState);
    const [panelOpen, setPanelOpen] = React.useState(false);
    const [topUpOpen, setTopUpOpen] = React.useState(false);
    const [confirmSpend, setConfirmSpend] = React.useState(null); // { cost, label, description, onConfirm }
    const [toast, setToast] = React.useState(null);

    // Persist on every change
    React.useEffect(() => { saveState(state); }, [state]);

    // Auto-dismiss toast
    React.useEffect(() => {
      if (!toast) return;
      const id = setTimeout(() => setToast(null), 3400);
      return () => clearTimeout(id);
    }, [toast]);

    function addCredits(pack) {
      const entry = {
        id: 'p' + Date.now(),
        kind: 'purchase',
        label: pack.label + ' pack',
        credits: +pack.credits,
        dollars: pack.dollars,
        at: Date.now()
      };
      setState(s => ({
        balance: s.balance + pack.credits,
        history: [entry, ...s.history].slice(0, 50)
      }));
      setToast({ kind: 'success', text: '+' + pack.credits + ' credits added to your wallet' });
      setTopUpOpen(false);
      setPanelOpen(true);
    }

    function spend({ credits, label }) {
      if (state.balance < credits) {
        setToast({ kind: 'warn', text: 'Not enough credits — top up to continue' });
        setTopUpOpen(true);
        return false;
      }
      const entry = {
        id: 's' + Date.now(),
        kind: 'spend',
        label,
        credits: -credits,
        at: Date.now()
      };
      setState(s => ({
        balance: s.balance - credits,
        history: [entry, ...s.history].slice(0, 50)
      }));
      setToast({ kind: 'success', text: 'Spent ' + credits + ' cr · ' + label });
      return true;
    }

    function requestSpend({ credits, label, description, onConfirm }) {
      setConfirmSpend({ credits, label, description, onConfirm });
    }

    const value = {
      balance: state.balance,
      history: state.history,
      packs: PACKS,
      addCredits,
      spend,
      requestSpend,
      open: () => setPanelOpen(true),
      close: () => setPanelOpen(false),
      panelOpen,
      openTopUp: () => setTopUpOpen(true),
      closeTopUp: () => setTopUpOpen(false),
      topUpOpen,
      confirmSpend,
      setConfirmSpend,
      creditFmt,
      dollarsToCreditsCost
    };

    return React.createElement(WalletCtx.Provider, { value },
      children,
      panelOpen    && React.createElement(WalletPanel, null),
      topUpOpen    && React.createElement(AddCreditsModal, null),
      confirmSpend && React.createElement(ConfirmSpendSheet, null),
      toast        && React.createElement(WalletToast, { toast })
    );
  }

  // ── Topbar chip ──────────────────────────────────────────
  function WalletChip() {
    const w = useWallet();
    if (!w) return null;
    const low = w.balance < 20;
    return React.createElement('button', {
      className: 'amos-pill wallet' + (low ? ' low' : ''),
      onClick: w.open,
      title: 'Your credit wallet'
    },
      React.createElement('span', { className: 'wallet-ico', 'aria-hidden': true },
        // lightning/coin hybrid — simple readable glyph
        React.createElement('svg', { width: 14, height: 14, viewBox: '0 0 24 24', fill: 'none' },
          React.createElement('circle', { cx: 12, cy: 12, r: 9, stroke: 'currentColor', strokeWidth: 1.6 }),
          React.createElement('path', { d: 'M13 6l-4 7h3l-1 5 4-7h-3l1-5z', fill: 'currentColor' })
        )
      ),
      React.createElement('span', { className: 'wallet-amount' }, w.balance.toLocaleString()),
      React.createElement('span', { className: 'wallet-unit' }, 'cr')
    );
  }

  // ── Panel ────────────────────────────────────────────────
  function WalletPanel() {
    const w = useWallet();
    const recent = w.history.slice(0, 8);

    // "What you've invested" roll-up — tells the patronage story back to the user
    const spent   = w.history.filter(h => h.kind === 'spend');
    const totalSpent   = spent.reduce((s, h) => s + Math.abs(h.credits), 0);
    const totalPurchased = w.history.filter(h => h.kind === 'purchase').reduce((s, h) => s + h.credits, 0);
    const commissionsCount = spent.length;
    // Rough breakdown: labels that contain 'book', 'translation', 'analysis'
    const byKind = spent.reduce((acc, h) => {
      const l = (h.label || '').toLowerCase();
      const k = /book|edition|commission/.test(l) && /book|edition/.test(l) ? 'books'
              : /analysis|apparatus|pericope/.test(l) ? 'analyses'
              : /translation|→|ca |es |en /.test(l) ? 'translations'
              : 'other';
      acc[k] = (acc[k] || 0) + 1;
      return acc;
    }, {});

    return React.createElement('div', {
      className: 'amos-wallet-backdrop',
      onClick: w.close
    },
      React.createElement('aside', {
        className: 'amos-wallet-panel',
        onClick: (e) => e.stopPropagation()
      },
        React.createElement('header', { className: 'wp-head' },
          React.createElement('div', { className: 'wp-kicker' }, 'Your wallet'),
          React.createElement('button', { className: 'amos-icon-btn', onClick: w.close },
            window.I ? window.I.x(16) : '×'
          )
        ),
        React.createElement('div', { className: 'wp-balance' },
          React.createElement('div', { className: 'wp-bal-num' },
            w.balance.toLocaleString(),
            React.createElement('span', { className: 'wp-bal-unit' }, 'cr')
          ),
          React.createElement('div', { className: 'wp-bal-sub' },
            '≈ $', (w.balance * 0.10).toFixed(2).replace(/\.00$/, ''),
            ' · 1 credit = $0.10'
          )
        ),
        React.createElement('button', {
          className: 'wp-topup-cta',
          onClick: () => { w.close(); w.openTopUp(); }
        }, 'Add credits'),
        React.createElement('div', { className: 'wp-quick' },
          w.packs.map(p => React.createElement('button', {
            key: p.id,
            className: 'wp-quick-pack',
            onClick: () => { w.close(); w.openTopUp(); }
          },
            React.createElement('span', { className: 'wp-qp-label' }, p.label),
            React.createElement('span', { className: 'wp-qp-credits' },
              '+', p.credits.toLocaleString(), ' cr'
            ),
            React.createElement('span', { className: 'wp-qp-price' }, '$', p.dollars)
          ))
        ),

        // ── Patronage story: what you've built ───────────────
        commissionsCount > 0 && React.createElement('div', { className: 'wp-patronage' },
          React.createElement('div', { className: 'wp-patronage-head' }, 'Your contributions to the Library'),
          React.createElement('div', { className: 'wp-patronage-body' },
            'You\u2019ve commissioned ',
            React.createElement('strong', null, commissionsCount, ' ', commissionsCount === 1 ? 'work' : 'works'),
            ' — ',
            Object.entries(byKind).filter(([k,v]) => v > 0).map(([k,v], i, arr) =>
              React.createElement(React.Fragment, { key: k },
                React.createElement('strong', null, v), ' ', k,
                i < arr.length - 1 ? ', ' : ''
              )
            ),
            ' — now readable by everyone. Total invested: ',
            React.createElement('strong', null, totalSpent.toLocaleString(), ' cr'),
            ' ($', (totalSpent * 0.10).toFixed(2).replace(/\.00$/, ''), ').'
          ),
          React.createElement('div', { className: 'wp-patronage-meters' },
            React.createElement('div', { className: 'wp-meter' },
              React.createElement('div', { className: 'wp-meter-k' }, 'Purchased'),
              React.createElement('div', { className: 'wp-meter-v' }, totalPurchased.toLocaleString(), ' cr')
            ),
            React.createElement('div', { className: 'wp-meter' },
              React.createElement('div', { className: 'wp-meter-k' }, 'Spent on commissions'),
              React.createElement('div', { className: 'wp-meter-v' }, totalSpent.toLocaleString(), ' cr')
            ),
            React.createElement('div', { className: 'wp-meter' },
              React.createElement('div', { className: 'wp-meter-k' }, 'Current balance'),
              React.createElement('div', { className: 'wp-meter-v' }, w.balance.toLocaleString(), ' cr')
            )
          )
        ),

        React.createElement('div', { className: 'wp-section-head' }, 'Recent activity'),
        recent.length === 0
          ? React.createElement('div', { className: 'wp-empty' }, 'No activity yet. Your purchases and commissions will appear here.')
          : React.createElement('ul', { className: 'wp-history' },
              recent.map(h => React.createElement('li', {
                key: h.id,
                className: 'wp-h-row ' + (h.kind === 'purchase' ? 'in' : 'out')
              },
                React.createElement('div', { className: 'wp-h-main' },
                  React.createElement('div', { className: 'wp-h-label' }, h.label),
                  React.createElement('div', { className: 'wp-h-when' }, relTime(h.at))
                ),
                React.createElement('div', { className: 'wp-h-amt' },
                  (h.credits > 0 ? '+' : '') + h.credits.toLocaleString() + ' cr'
                )
              ))
            ),
        React.createElement('div', { className: 'wp-foot' },
          'Credits never expire. They pay for translations, commentary commissions, and analytical studies — nothing auto-renews.'
        )
      )
    );
  }

  // ── Add-credits modal ────────────────────────────────────
  function AddCreditsModal() {
    const w = useWallet();
    return React.createElement('div', {
      className: 'amos-modal-backdrop wallet-add',
      onClick: w.closeTopUp
    },
      React.createElement('div', {
        className: 'amos-modal wallet-add-modal',
        onClick: (e) => e.stopPropagation(),
        style: { maxWidth: 820 }
      },
        React.createElement('div', { className: 'amos-modal-head' },
          React.createElement('div', null,
            React.createElement('div', { className: 'mh-kicker' }, 'Top up your wallet'),
            React.createElement('h3', null, 'Choose a credit pack'),
            React.createElement('div', { className: 'mh-sub' },
              'One credit = $0.10. Bigger packs include bonus credits. Credits never expire.'
            )
          ),
          React.createElement('button', { className: 'amos-icon-btn', onClick: w.closeTopUp },
            window.I ? window.I.x(16) : '×'
          )
        ),
        React.createElement('div', { className: 'wallet-pack-grid' },
          w.packs.map(p => React.createElement('article', {
            key: p.id,
            className: 'wallet-pack' + (p.popular ? ' popular' : '')
          },
            p.popular && React.createElement('span', { className: 'wallet-pack-flag' }, 'Most popular'),
            p.bonus > 0 && React.createElement('span', { className: 'wallet-pack-bonus' },
              '+', p.bonusPct, '% bonus'
            ),
            React.createElement('div', { className: 'wallet-pack-label' }, p.label),
            React.createElement('div', { className: 'wallet-pack-credits' },
              p.credits.toLocaleString(),
              React.createElement('span', { className: 'cr-unit' }, 'credits')
            ),
            p.bonus > 0 && React.createElement('div', { className: 'wallet-pack-math' },
              p.baseCredits.toLocaleString(), ' base + ', p.bonus, ' bonus'
            ),
            React.createElement('div', { className: 'wallet-pack-price' }, '$', p.dollars),
            React.createElement('div', { className: 'wallet-pack-tag' }, p.tagline),
            React.createElement('ul', { className: 'wallet-pack-perks' },
              p.perks.map((perk, i) => React.createElement('li', { key: i }, perk))
            ),
            React.createElement('button', {
              className: 'wallet-pack-buy' + (p.popular ? ' primary' : ''),
              onClick: () => w.addCredits(p)
            }, 'Buy ', p.label)
          ))
        ),
        React.createElement('div', { className: 'wallet-add-foot' },
          React.createElement('div', { className: 'wallet-add-foot-line' },
            React.createElement('strong', null, 'How pricing works.'),
            ' A commission\u2019s credit cost reflects the analytical work involved plus editorial review.',
            ' You\u2019ll see the exact cost before anything is charged.'
          ),
          React.createElement('div', { className: 'wallet-add-foot-trust' },
            React.createElement('span', null, '🔒 Stripe-processed'),
            React.createElement('span', null, '· Cancel anytime'),
            React.createElement('span', null, '· Refunds on unused credits within 30 days')
          )
        )
      )
    );
  }

  // ── Confirm-spend sheet ──────────────────────────────────
  function ConfirmSpendSheet() {
    const w = useWallet();
    const cs = w.confirmSpend;
    if (!cs) return null;
    const close = () => w.setConfirmSpend(null);
    const insufficient = w.balance < cs.credits;
    const afterBalance = Math.max(0, w.balance - cs.credits);

    return React.createElement('div', {
      className: 'amos-modal-backdrop wallet-confirm',
      onClick: close
    },
      React.createElement('div', {
        className: 'amos-confirm-sheet',
        onClick: (e) => e.stopPropagation()
      },
        React.createElement('div', { className: 'cs-head' },
          React.createElement('div', { className: 'cs-kicker' }, 'Confirm spend'),
          React.createElement('button', { className: 'amos-icon-btn', onClick: close },
            window.I ? window.I.x(16) : '×'
          )
        ),
        React.createElement('h3', { className: 'cs-title' }, cs.label),
        cs.description && React.createElement('p', { className: 'cs-desc' }, cs.description),
        React.createElement('div', { className: 'cs-lines' },
          React.createElement('div', { className: 'cs-line' },
            React.createElement('span', null, 'This commission'),
            React.createElement('strong', null, '−', cs.credits.toLocaleString(), ' cr')
          ),
          React.createElement('div', { className: 'cs-line muted' },
            React.createElement('span', null, 'Current balance'),
            React.createElement('span', null, w.balance.toLocaleString(), ' cr')
          ),
          React.createElement('div', { className: 'cs-line total' },
            React.createElement('span', null, 'Balance after'),
            React.createElement('strong', { className: insufficient ? 'neg' : '' },
              afterBalance.toLocaleString(), ' cr'
            )
          )
        ),
        insufficient && React.createElement('div', { className: 'cs-warn' },
          'You need ',
          React.createElement('strong', null, (cs.credits - w.balance).toLocaleString(), ' more credits'),
          ' to run this. Top up first — your progress is saved.'
        ),
        React.createElement('div', { className: 'cs-actions' },
          React.createElement('button', {
            className: 'btn btn-outline btn-sm',
            onClick: close
          }, 'Cancel'),
          insufficient
            ? React.createElement('button', {
                className: 'btn btn-primary',
                onClick: () => { close(); w.openTopUp(); }
              }, 'Top up credits')
            : React.createElement('button', {
                className: 'btn btn-primary',
                onClick: () => {
                  const ok = w.spend({ credits: cs.credits, label: cs.label });
                  close();
                  if (ok && cs.onConfirm) cs.onConfirm();
                }
              }, 'Confirm · spend ', cs.credits.toLocaleString(), ' cr')
        )
      )
    );
  }

  // ── Toast ────────────────────────────────────────────────
  function WalletToast({ toast }) {
    return React.createElement('div', {
      className: 'amos-wallet-toast ' + (toast.kind || '')
    }, toast.text);
  }

  // ── Relative-time ────────────────────────────────────────
  function relTime(ts) {
    const diff = Date.now() - ts;
    const mins = Math.round(diff / 60000);
    if (mins < 1)    return 'just now';
    if (mins < 60)   return mins + ' min ago';
    const hrs = Math.round(mins / 60);
    if (hrs < 24)    return hrs + ' h ago';
    const days = Math.round(hrs / 24);
    if (days < 7)    return days + ' d ago';
    const wks = Math.round(days / 7);
    if (wks < 4)     return wks + ' w ago';
    const mons = Math.round(days / 30);
    return mons + ' mo ago';
  }

  Object.assign(window, {
    WalletProvider,
    useWallet,
    WalletChip,
    WalletPanel,
    AddCreditsModal,
    ConfirmSpendSheet,
    creditFmt,
    dollarsToCreditsCost
  });
})();
