// LedgerBeaver � reusable React widgets

// React hooks accessed via React.useX for UMD compatibility
const useState_w = React.useState;
const useEffect_w = React.useEffect;
const useRef_w = React.useRef;
const useMemo_w = React.useMemo;

// ---------- formatters ----------
const fmt = (n) => n == null ? '�' :
  new Intl.NumberFormat('en-US', { style:'currency', currency:'USD', maximumFractionDigits: 0 }).format(n);
const fmtSigned = (n) => (n > 0 ? '+' : '') + fmt(n);

// ---------- KPI ----------
const KpiCard = ({ label, value, delta, accent = 'amber', loading = false }) => {
  const accents = {
    amber:    'var(--amber)',
    emerald:  'var(--ar)',
    purple:   'var(--gl)',
    cyan:     'var(--reports)',
    red:      'var(--err)',
    neutral:  'var(--text-hi)',
  };
  if (loading) {
    return (
      <div className="kpi">
        <div className="skel line" style={{ width: '50%' }} />
        <div className="skel" style={{ height: 30, width: '70%', marginTop: 8 }} />
        <div className="skel line" style={{ width: '40%', marginTop: 8 }} />
      </div>
    );
  }
  return (
    <div className="kpi">
      <div className="kpi-l">{label}</div>
      <div className="kpi-v" style={{ color: accents[accent] }}>{typeof value === 'number' ? fmt(value) : value}</div>
      {delta != null && (
        <div className={"kpi-d " + (delta >= 0 ? 'up' : 'dn')}>
          {delta >= 0 ? '?' : '?'} {fmtSigned(delta).replace('-', '')} this week
        </div>
      )}
    </div>
  );
};

// ---------- Status pill ----------
const StatusPill = ({ s }) => (
  <span className="s-pill" data-s={s}>{(s || '').toUpperCase()}</span>
);

// ---------- Agent attribution chip ----------
const AgentChip = ({ name = 'Claude' }) => (
  <span className="agent-chip">
    <span className="agent-chip-dot" />
    <Icon name="bot" size={10} />
    {name}
  </span>
);

// ---------- Section header ----------
const SectionHead = ({ kicker, title, sub, actions }) => (
  <div className="section-head">
    <div>
      <div className="eyebrow">{kicker}</div>
      <h1 className="section-title">{title}</h1>
      {sub && <div className="section-sub">{sub}</div>}
    </div>
    {actions && <div className="section-actions">{actions}</div>}
  </div>
);

// ---------- State helpers ----------
// Every data panel must handle Loading / Empty / Error.
// Use:  <Stateful state={state} onRetry={fn}>{children}</Stateful>
const Stateful = ({ state, onRetry, emptyKey, children }) => {
  if (state === 'loading') {
    return (
      <div className="card panel">
        <div className="skel title" />
        <div style={{ marginTop: 14 }}>
          <div className="skel line" style={{ width: '90%' }} />
          <div className="skel line" style={{ width: '75%' }} />
          <div className="skel line" style={{ width: '85%' }} />
          <div className="skel line" style={{ width: '65%' }} />
        </div>
      </div>
    );
  }
  if (state === 'empty') {
    return (
      <div className="state">
        <Beaver pose="think" size={110} halo="glow" anim="idle" />
        <h4>{LB.t('state.empty.h')}</h4>
        <p>{LB.t('state.empty.sub')}</p>
      </div>
    );
  }
  if (state === 'error') {
    return (
      <div className="state">
        <Beaver pose="failed-login" size={110} halo="glow" anim="idle" />
        <h4>{LB.t('state.error.h')}</h4>
        <p>{LB.t('state.error.sub')}</p>
        <button className="btn btn-primary" onClick={onRetry}>{LB.t('state.retry')}</button>
      </div>
    );
  }
  return children;
};

// ---------- Search box ----------
const SearchBox = () => {
  const [q, setQ] = useState_w('');
  const [open, setOpen] = useState_w(false);
  const ref = useRef_w(null);

  useEffect_w(() => {
    const onClick = (e) => { if (!ref.current?.contains(e.target)) setOpen(false); };
    document.addEventListener('click', onClick);
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        ref.current?.querySelector('input')?.focus();
        setOpen(true);
      }
    };
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('click', onClick); document.removeEventListener('keydown', onKey); };
  }, []);

  // SUPABASE WIRE:
  //   debounced: parallel queries to vendors, customers, ap_invoices, ar_invoices, gl_accounts, people
  //   each `WHERE name ILIKE '%q%' OR number ILIKE '%q%' LIMIT 5`
  const results = useMemo_w(() => {
    const qq = q.trim().toLowerCase();
    if (!qq) return [];
    // Combine static search index + Dam people
    const peopleHits = (window.LB_DAM?.people || []).filter(p =>
      p.name.toLowerCase().includes(qq) ||
      p.org.toLowerCase().includes(qq) ||
      (p.email || '').toLowerCase().includes(qq)
    ).map(p => ({ type: 'person', name: p.name, sub: `${p.role} � ${p.org}`, goto: 'dam', personId: p.id }));

    return [...peopleHits, ...LB_DATA.search.filter(r => r.name.toLowerCase().includes(qq) || r.sub.toLowerCase().includes(qq))]
      .slice(0, 10);
  }, [q]);

  const grouped = results.reduce((m, r) => { (m[r.type] = m[r.type] || []).push(r); return m; }, {});

  return (
    <div className="search" ref={ref}>
      <div className="search-input">
        <Icon name="search" size={14} />
        <input
          type="text"
          value={q}
          onChange={(e) => { setQ(e.target.value); setOpen(true); }}
          onFocus={() => setOpen(true)}
          placeholder={LB.t('app.search')}
        />
        <kbd>?K</kbd>
      </div>
      {open && q && (
        <div className="search-dropdown">
          {results.length === 0 && (
            <div style={{ padding: '14px 12px', color: 'var(--text-mid)', fontSize: 13, textAlign:'center' }}>
              No results for "<strong style={{color:'var(--text-hi)'}}>{q}</strong>"
            </div>
          )}
          {Object.entries(grouped).map(([type, items]) => (
            <React.Fragment key={type}>
              <div className="search-grp">{type}s</div>
              {items.map((r, i) => (
                <div className="search-result" key={i} onClick={() => {
                  window.dispatchEvent(new CustomEvent('lb-goto', { detail: { screen: r.goto } }));
                  if (r.personId) {
                    setTimeout(() => window.dispatchEvent(new CustomEvent('lb-dam-open', { detail: { personId: r.personId } })), 50);
                  }
                  setOpen(false); setQ('');
                }}>
                  <Icon name={r.type === 'person' ? 'user' : r.type === 'vendor' ? 'vendors' : r.type === 'customer' ? 'user' : r.type === 'invoice' ? 'ap' : r.type === 'journal' ? 'gl' : 'building'} size={14} style={{ color: r.type === 'person' ? 'var(--amber)' : 'var(--text-mid)' }} />
                  <div className="pri">{r.name}</div>
                  <div className="sec">{r.sub}</div>
                </div>
              ))}
            </React.Fragment>
          ))}
        </div>
      )}
    </div>
  );
};

// ---------- Quick actions toolbar ----------
const QuickActions = () => {
  const acts = [
    { key: 'newInvoice', icon: 'plus',     i18n: 'qa.newInvoice', goto: 'ap',       label: 'New invoice' },
    { key: 'pay',        icon: 'send',     i18n: 'qa.payVendors', goto: 'approvals',label: 'Pay vendors' },
    { key: 'report',     icon: 'reports',  i18n: 'qa.runReport',  goto: 'reports',  label: 'Run report' },
    { key: 'close',      icon: 'lock',     i18n: 'qa.closePeriod', goto: 'gl',      label: 'Close period' },
  ];
  return (
    <div className="qa-bar">
      {acts.map(a => (
        <button key={a.key} className="qa-btn" onClick={() => window.dispatchEvent(new CustomEvent('lb-goto', { detail: { screen: a.goto } }))}>
          <Icon name={a.icon} size={14} className="qa-icon" />
          <span data-i18n={a.i18n}>{a.label}</span>
        </button>
      ))}
    </div>
  );
};

// ---------- Notification bell ----------
const NotificationBell = ({ items }) => {
  const [open, setOpen] = useState_w(false);
  const ref = useRef_w(null);
  useEffect_w(() => {
    const onClick = (e) => { if (!ref.current?.contains(e.target)) setOpen(false); };
    document.addEventListener('click', onClick);
    return () => document.removeEventListener('click', onClick);
  }, []);
  const unread = items.length;
  const icoFor = (item) => {
    if (item.urg === 'urgent') return 'err';
    if (item.urg === 'action') return '';
    return 'info';
  };
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button className="top-icon" title="Notifications" onClick={() => setOpen(o => !o)}>
        <Icon name="bell" size={16} />
        {unread > 0 && <span className="count">{unread > 9 ? '9+' : unread}</span>}
      </button>
      {open && (
        <div className="noti-pop">
          <div className="noti-head">
            <h4 data-i18n="noti.h">Notifications</h4>
            <a data-i18n="noti.markAll">Mark all as read</a>
          </div>
          <div className="noti-body">
            {items.length === 0 ? (
              <div style={{ padding: '32px 20px', textAlign:'center' }}>
                <Beaver pose="achievement" size={84} halo="stamp" anim="pop-then-idle" />
                <div style={{ color: 'var(--text-hi)', fontWeight: 600, marginTop: 12 }} data-i18n="noti.empty">You're all caught up.</div>
                <div style={{ color: 'var(--text-mid)', fontSize: 12.5, marginTop: 4 }} data-i18n="noti.empty.sub">New approvals, flagged invoices, and overdue items will show up here.</div>
              </div>
            ) : items.map(n => (
              <div className="noti-item" key={n.id} onClick={() => {
                setOpen(false);
                window.dispatchEvent(new CustomEvent('lb-goto', { detail: { screen: n.goto } }));
              }}>
                <div className={"ico " + icoFor(n)}><Icon name={n.icon || 'alert'} size={14} /></div>
                <div style={{ flex: 1 }}>
                  <div className="t">{n.title}</div>
                  <div className="d">{n.desc}</div>
                </div>
                <time>{n.t}</time>
              </div>
            ))}
          </div>
          <div className="noti-foot">
            <a onClick={() => { setOpen(false); window.dispatchEvent(new CustomEvent('lb-goto', { detail: { screen: 'feed' } })); }}>
              View all activity ?
            </a>
          </div>
        </div>
      )}
    </div>
  );
};

// ---------- Sparkline ----------
const Sparkline = ({ data = [40,42,38,44,50,48,52,58,55,60,64,62,68,72,70,75,80,78,82,85,90,88,92,96,100,98,104] }) => {
  const w = 100, h = 40;
  const max = Math.max(...data), min = Math.min(...data);
  const path = data.map((p, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - ((p - min) / (max - min || 1)) * h;
    return (i === 0 ? 'M' : 'L') + x + ',' + y;
  }).join(' ');
  return (
    <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ width: '100%', height: 64, margin:'8px 0 12px' }}>
      <defs>
        <linearGradient id="sg" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="var(--amber)" stopOpacity="0.4" />
          <stop offset="100%" stopColor="var(--amber)" stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={`${path} L ${w},${h} L 0,${h} Z`} fill="url(#sg)" />
      <path d={path} fill="none" stroke="var(--amber)" strokeWidth="1.2" vectorEffect="non-scaling-stroke" />
    </svg>
  );
};

window.LBUI = {
  fmt, fmtSigned,
  KpiCard, StatusPill, AgentChip, SectionHead, Stateful,
  SearchBox, QuickActions, NotificationBell, Sparkline,
};
if (window.Beaver) window.LBUI.Beaver = window.Beaver;