// ─── GUSTAI LAB — Admin: Receipt Management ───────────────────────────────────
// Accessible only to the verified admin phone. Loads all payment_receipts,
// shows Gemini fraud-check results, and lets admin confirm or reject each one.

const ADMIN_PHONE = '+66954766235';   // ← owner's verified phone (E.164)

// ── Helpers ───────────────────────────────────────────────────────────────────
function timeAgo(isoStr) {
  if (!isoStr) return '';
  const secs = Math.floor((Date.now() - new Date(isoStr).getTime()) / 1000);
  if (secs < 60)    return `${secs}s ago`;
  if (secs < 3600)  return `${Math.floor(secs / 60)}m ago`;
  if (secs < 86400) return `${Math.floor(secs / 3600)}h ago`;
  return `${Math.floor(secs / 86400)}d ago`;
}

function fmtTime(isoStr) {
  if (!isoStr) return '—';
  const d = new Date(isoStr);
  return d.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false });
}

function fmtDate(isoStr) {
  if (!isoStr) return '—';
  return new Date(isoStr).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
}

const STATUS_META = {
  pending:        { label: 'Pending',        bg: '#FFF3CD', color: '#856404', dot: '#FFC107' },
  flagged:        { label: 'Flagged ⚠️',      bg: '#FDE8D0', color: '#7A3B00', dot: '#FF7A00' },
  auto_confirmed: { label: 'Auto-confirmed', bg: '#D4EDDA', color: '#155724', dot: '#28A745' },
  confirmed:      { label: 'Confirmed ✓',    bg: '#D4EDDA', color: '#155724', dot: '#28A745' },
  rejected:       { label: 'Rejected ✗',     bg: '#F8D7DA', color: '#721C24', dot: '#DC3545' },
};

function StatusBadge({ status, small }) {
  const m = STATUS_META[status] || { label: status, bg: GL.offwhite, color: GL.muted, dot: GL.muted };
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      padding: small ? '3px 8px' : '5px 10px',
      background: m.bg, color: m.color,
      fontSize: small ? 9 : 11, fontWeight: 800, letterSpacing: '0.08em',
      textTransform: 'uppercase',
    }}>
      <span style={{ width: 6, height: 6, borderRadius: '50%', background: m.dot, flexShrink: 0 }}/>
      {m.label}
    </span>
  );
}

// ── Receipt list item ─────────────────────────────────────────────────────────
function ReceiptRow({ r, onSelect }) {
  const g = r.gemini_result || {};
  return (
    <button
      onClick={() => onSelect(r)}
      style={{
        width: '100%', textAlign: 'left', background: '#fff', padding: '14px 16px',
        borderBottom: `1px solid ${GL.line}`, display: 'flex', gap: 12, alignItems: 'center',
        position: 'relative',
      }}
    >
      {/* Status stripe */}
      <div style={{
        position: 'absolute', left: 0, top: 0, bottom: 0, width: 4,
        background: (STATUS_META[r.status] || {}).dot || GL.muted,
      }}/>

      {/* Receipt icon */}
      <div style={{
        width: 42, height: 42, flexShrink: 0, background: GL.offwhite,
        border: `1.5px solid ${GL.line}`, display: 'grid', placeItems: 'center',
      }}>
        {r.receipt_mime?.startsWith('image/') ? (
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={GL.muted} strokeWidth="1.5"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-5-5L5 21"/></svg>
        ) : (
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={GL.muted} strokeWidth="1.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
        )}
      </div>

      {/* Main info */}
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3 }}>
          <span style={{ fontSize: 13, fontWeight: 800, color: GL.ink, fontFamily: 'monospace' }}>
            {r.order_no}
          </span>
          <StatusBadge status={r.status} small/>
        </div>
        <div style={{ fontSize: 12, color: GL.muted, display: 'flex', gap: 10 }}>
          <span style={{ fontWeight: 700, color: GL.ink }}>฿{parseFloat(r.amount).toLocaleString()}</span>
          <span>{timeAgo(r.created_at)}</span>
          {g.bank_name && <span>{g.bank_name}</span>}
        </div>
        {r.flag_reason && r.status === 'flagged' && (
          <div style={{ fontSize: 10, color: '#7A3B00', marginTop: 3, fontWeight: 600, fontStyle: 'italic' }}>
            ⚠ {r.flag_reason.slice(0, 60)}{r.flag_reason.length > 60 ? '…' : ''}
          </div>
        )}
      </div>

      {/* Confidence pill */}
      {r.gemini_confidence != null && (
        <div style={{
          fontSize: 10, fontWeight: 800, padding: '3px 7px',
          background: r.gemini_confidence >= 0.9 ? '#D4EDDA' : r.gemini_confidence >= 0.7 ? '#FFF3CD' : '#F8D7DA',
          color: r.gemini_confidence >= 0.9 ? '#155724' : r.gemini_confidence >= 0.7 ? '#856404' : '#721C24',
          flexShrink: 0,
        }}>
          {(r.gemini_confidence * 100).toFixed(0)}%
        </div>
      )}

      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={GL.muted} strokeWidth="2" style={{ flexShrink: 0 }}><path d="M9 18l6-6-6-6"/></svg>
    </button>
  );
}

// ── Receipt detail view ───────────────────────────────────────────────────────
function GLAdminReceiptDetail({ receipt: initialReceipt, onBack, onRefresh }) {
  const [receipt, setReceipt]   = React.useState(initialReceipt);
  const [imageUrl, setImageUrl] = React.useState(null);
  const [note, setNote]         = React.useState(receipt.admin_note || '');
  const [processing, setProcessing] = React.useState(false);
  const [msg, setMsg]           = React.useState('');

  // Get signed URL for the receipt image (private bucket)
  React.useEffect(() => {
    if (!receipt.receipt_path || receipt.receipt_mime === 'application/pdf') return;
    window.db.storage.from('receipts')
      .createSignedUrl(receipt.receipt_path, 600)  // 10-min signed URL
      .then(({ data }) => { if (data?.signedUrl) setImageUrl(data.signedUrl); })
      .catch(e => console.error('[admin] signedUrl error:', e));
  }, [receipt.receipt_path]);

  // Poll for Gemini result while status is still 'pending'
  React.useEffect(() => {
    if (receipt.status !== 'pending') return;
    const iv = setInterval(async () => {
      const { data } = await window.db.from('payment_receipts').select('*').eq('id', receipt.id).single();
      if (data && data.status !== 'pending') {
        setReceipt(data);
        clearInterval(iv);
      }
    }, 4000);
    return () => clearInterval(iv);
  }, [receipt.status]);

  const action = async (newStatus) => {
    setProcessing(true);
    setMsg('');
    try {
      const updates = {
        status: newStatus,
        admin_note: note || null,
        confirmed_at: (newStatus === 'confirmed') ? new Date().toISOString() : null,
      };
      const { error } = await window.db.from('payment_receipts').update(updates).eq('id', receipt.id);
      if (error) throw error;
      setReceipt(r => ({ ...r, ...updates }));
      setMsg(newStatus === 'confirmed' ? '✓ Payment confirmed — customer notified.' : '✗ Receipt rejected.');
      onRefresh();
    } catch (e) {
      setMsg('Error: ' + (e?.message || 'Unknown'));
    } finally {
      setProcessing(false);
    }
  };

  const g = receipt.gemini_result || {};
  const isSettled = ['confirmed', 'auto_confirmed', 'rejected'].includes(receipt.status);

  return (
    <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column' }}>
      <div style={{ height: 3, background: (STATUS_META[receipt.status] || {}).dot || GL.muted }}/>
      <GLTopBar
        onBack={onBack}
        center={<div className="gl-display" style={{ fontSize: 13, letterSpacing: '0.14em' }}>RECEIPT DETAIL</div>}
      />

      <div style={{ flex: 1, overflowY: 'auto', paddingBottom: 120 }} className="gl-noscroll">

        {/* Status + order header */}
        <div style={{ padding: '16px 20px', borderBottom: `1px solid ${GL.line}`, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <div style={{ fontSize: 10, color: GL.muted, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 4 }}>Order</div>
            <div style={{ fontSize: 16, fontWeight: 800, fontFamily: 'monospace', color: GL.ink }}>{receipt.order_no}</div>
            <div style={{ fontSize: 11, color: GL.muted, marginTop: 2 }}>{fmtDate(receipt.created_at)} · {fmtTime(receipt.created_at)}</div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <StatusBadge status={receipt.status}/>
            <div className="gl-display" style={{ fontSize: 26, color: GL.ink, marginTop: 6 }}>฿{parseFloat(receipt.amount).toLocaleString()}</div>
          </div>
        </div>

        {/* Receipt image */}
        <div style={{ padding: '16px 20px', borderBottom: `1px solid ${GL.line}` }}>
          <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.14em', color: GL.muted, textTransform: 'uppercase', marginBottom: 10 }}>Receipt Image</div>
          {receipt.receipt_mime === 'application/pdf' ? (
            <div style={{ padding: 20, background: GL.offwhite, textAlign: 'center', color: GL.muted, fontSize: 12 }}>
              📄 PDF receipt — open in browser to view
              {receipt.receipt_path && (
                <div style={{ marginTop: 8 }}>
                  <button onClick={async () => {
                    const { data } = await window.db.storage.from('receipts').createSignedUrl(receipt.receipt_path, 300);
                    if (data?.signedUrl) window.open(data.signedUrl, '_blank');
                  }} style={{ fontSize: 12, fontWeight: 700, color: GL.teal, textDecoration: 'underline', background: 'transparent', border: 'none', cursor: 'pointer' }}>
                    Open PDF ↗
                  </button>
                </div>
              )}
            </div>
          ) : imageUrl ? (
            <div style={{ border: `2px solid ${GL.ink}`, boxShadow: `4px 4px 0 ${GL.ink}`, background: '#fff' }}>
              <img
                src={imageUrl}
                alt="Payment receipt"
                style={{ width: '100%', height: 'auto', display: 'block', maxHeight: 400, objectFit: 'contain' }}
              />
            </div>
          ) : (
            <div style={{ height: 120, background: GL.offwhite, display: 'grid', placeItems: 'center', color: GL.muted, fontSize: 12 }}>
              {receipt.receipt_path ? 'Loading image…' : 'No image uploaded'}
            </div>
          )}
        </div>

        {/* Gemini analysis */}
        {receipt.status === 'pending' ? (
          <div style={{ padding: '20px', background: GL.offwhite, borderBottom: `1px solid ${GL.line}`, textAlign: 'center' }}>
            <div style={{ fontSize: 12, color: GL.muted, fontWeight: 600 }}>Gemini is analysing the receipt…</div>
            <div style={{ display: 'flex', justifyContent: 'center', gap: 4, marginTop: 10 }}>
              {[0,1,2].map(i => (
                <div key={i} style={{ width: 6, height: 6, borderRadius: '50%', background: GL.teal, opacity: 0.5, animation: `gl-pulse 1.2s ${i * 0.3}s infinite` }}/>
              ))}
            </div>
          </div>
        ) : receipt.gemini_result ? (
          <div style={{ padding: '16px 20px', borderBottom: `1px solid ${GL.line}` }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
              <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.14em', color: GL.muted, textTransform: 'uppercase' }}>Gemini Extracted</div>
              {receipt.gemini_confidence != null && (
                <div style={{
                  fontSize: 10, fontWeight: 800, padding: '3px 8px',
                  background: receipt.gemini_confidence >= 0.9 ? '#D4EDDA' : receipt.gemini_confidence >= 0.7 ? '#FFF3CD' : '#F8D7DA',
                  color: receipt.gemini_confidence >= 0.9 ? '#155724' : receipt.gemini_confidence >= 0.7 ? '#856404' : '#721C24',
                }}>
                  Confidence: {(receipt.gemini_confidence * 100).toFixed(0)}%
                </div>
              )}
            </div>

            <div style={{ display: 'flex', flexDirection: 'column', gap: 0, border: `1.5px solid ${GL.line}` }}>
              {[
                { label: 'Amount',        val: g.amount != null ? `฿${Number(g.amount).toFixed(2)}` : null,       check: g.amount != null && Math.abs(g.amount - parseFloat(receipt.amount)) <= 1 },
                { label: 'Transfer time', val: g.transfer_time ? fmtTime(g.transfer_time) + ' · ' + fmtDate(g.transfer_time) : null, check: !!g.transfer_time },
                { label: 'Recipient',     val: g.recipient_name || null,     check: typeof g.recipient_name === 'string' && (g.recipient_name.toUpperCase().includes('GUSTAI') || String(g.recipient_account || '').includes('954766235')) },
                { label: 'Account',       val: g.recipient_account || null,  check: String(g.recipient_account || '').includes('954766235') },
                { label: 'Reference',     val: g.reference_number || null,   check: !!g.reference_number },
                { label: 'Bank',          val: g.bank_name || null,          check: true },
                { label: 'Sender',        val: g.sender_name || null,        check: true },
                { label: 'Type',          val: g.transaction_type || null,   check: true },
              ].map(({ label, val, check }) => (
                <div key={label} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '9px 12px', borderBottom: `1px solid ${GL.line}` }}>
                  <span style={{ fontSize: 11, color: GL.muted, fontWeight: 600 }}>{label}</span>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                    <span style={{ fontSize: 11, fontWeight: 800, color: val ? GL.ink : GL.muted, fontFamily: 'monospace', textAlign: 'right', maxWidth: 180 }}>
                      {val ?? '—'}
                    </span>
                    {val && (
                      <span style={{ fontSize: 12 }}>{check ? '✓' : '✗'}</span>
                    )}
                  </div>
                </div>
              ))}
            </div>

            {receipt.flag_reason && (
              <div style={{ marginTop: 12, padding: '10px 12px', background: '#FDE8D0', border: '1px solid #FF7A00' }}>
                <div style={{ fontSize: 10, fontWeight: 800, color: '#7A3B00', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 4 }}>Flag Reason</div>
                <div style={{ fontSize: 12, color: '#7A3B00', fontWeight: 600, lineHeight: 1.5 }}>{receipt.flag_reason}</div>
              </div>
            )}
          </div>
        ) : null}

        {/* Admin note */}
        {!isSettled && (
          <div style={{ padding: '16px 20px', borderBottom: `1px solid ${GL.line}` }}>
            <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.14em', color: GL.muted, textTransform: 'uppercase', marginBottom: 8 }}>Admin Note (optional)</div>
            <textarea
              value={note}
              onChange={e => setNote(e.target.value)}
              placeholder="e.g. Customer called to confirm — amount matches"
              rows={2}
              style={{
                width: '100%', border: `2px solid ${GL.line}`, padding: '10px 12px', resize: 'none',
                fontSize: 12, fontFamily: 'inherit', outline: 'none', boxSizing: 'border-box',
              }}
            />
          </div>
        )}

        {receipt.admin_note && isSettled && (
          <div style={{ padding: '12px 20px', borderBottom: `1px solid ${GL.line}`, background: GL.offwhite }}>
            <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.12em', color: GL.muted, textTransform: 'uppercase', marginBottom: 4 }}>Admin Note</div>
            <div style={{ fontSize: 12, color: GL.ink, fontStyle: 'italic' }}>{receipt.admin_note}</div>
          </div>
        )}

        {msg && (
          <div style={{ margin: '12px 20px', padding: '10px 14px', background: msg.startsWith('✓') ? '#D4EDDA' : '#F8D7DA', color: msg.startsWith('✓') ? '#155724' : '#721C24', fontSize: 13, fontWeight: 700 }}>
            {msg}
          </div>
        )}
      </div>

      {/* Action buttons — hidden once settled */}
      {!isSettled && (
        <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: '12px 16px 24px', background: GL.paper, borderTop: `2px solid ${GL.ink}`, display: 'flex', gap: 10 }}>
          <button
            onClick={() => action('rejected')}
            disabled={processing}
            style={{
              flex: 1, height: 52, border: `2px solid ${GL.ink}`, background: '#fff',
              fontSize: 13, fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase',
              color: '#721C24', opacity: processing ? 0.5 : 1, cursor: processing ? 'not-allowed' : 'pointer',
            }}
          >
            ✗ Reject
          </button>
          <button
            onClick={() => action('confirmed')}
            disabled={processing}
            style={{
              flex: 2, height: 52, border: 'none', background: GL.ink,
              fontSize: 13, fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase',
              color: GL.teal, opacity: processing ? 0.5 : 1, cursor: processing ? 'not-allowed' : 'pointer',
            }}
          >
            {processing ? 'Processing…' : '✓ Confirm Payment'}
          </button>
        </div>
      )}
    </div>
  );
}

// ── Admin receipt list (main view) ────────────────────────────────────────────
function GLAdminReceipts({ app, go }) {
  const [receipts, setReceipts]     = React.useState([]);
  const [loading, setLoading]       = React.useState(true);
  const [search, setSearch]         = React.useState('');
  const [filter, setFilter]         = React.useState('all');
  const [stats, setStats]           = React.useState({ needsAction: 0, todayTotal: 0, todayCount: 0 });
  const [selected, setSelected]     = React.useState(null);
  const [lastRefresh, setLastRefresh] = React.useState(null);

  const FILTERS = [
    { id: 'all',            label: 'All' },
    { id: 'pending',        label: 'Pending' },
    { id: 'flagged',        label: 'Flagged ⚠' },
    { id: 'auto_confirmed', label: 'Auto ✓' },
    { id: 'confirmed',      label: 'Confirmed' },
    { id: 'rejected',       label: 'Rejected' },
  ];

  const load = React.useCallback(async () => {
    try {
      // Build query
      let q = window.db.from('payment_receipts').select('*').order('created_at', { ascending: false });
      if (filter !== 'all') q = q.eq('status', filter);
      if (search.trim())    q = q.ilike('order_no', `%${search.trim()}%`);
      q = q.limit(100);

      const { data, error } = await q;
      if (error) throw error;
      setReceipts(data || []);
      setLastRefresh(new Date());

      // Stats
      const today = new Date().toISOString().slice(0, 10);
      const { data: allToday } = await window.db
        .from('payment_receipts')
        .select('status, amount')
        .gte('created_at', today + 'T00:00:00+07:00');

      if (allToday) {
        const needsAction = allToday.filter(r => r.status === 'pending' || r.status === 'flagged').length;
        const confirmed   = allToday.filter(r => r.status === 'confirmed' || r.status === 'auto_confirmed');
        const todayTotal  = confirmed.reduce((s, r) => s + parseFloat(r.amount || 0), 0);
        setStats({ needsAction, todayTotal, todayCount: confirmed.length });
      }
    } catch (e) {
      console.error('[admin] Load error:', e);
    } finally {
      setLoading(false);
    }
  }, [filter, search]);

  // Initial load + auto-refresh every 30s
  React.useEffect(() => {
    load();
    const iv = setInterval(load, 30000);
    return () => clearInterval(iv);
  }, [load]);

  // Show detail view when a receipt is selected
  if (selected) {
    return (
      <GLAdminReceiptDetail
        receipt={selected}
        onBack={() => setSelected(null)}
        onRefresh={() => { setSelected(null); load(); }}
      />
    );
  }

  return (
    <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column' }}>
      <div style={{ height: 3, background: GL.teal }}/>
      <GLTopBar
        onBack={() => go('me')}
        center={<div className="gl-display" style={{ fontSize: 13, letterSpacing: '0.14em' }}>RECEIPTS</div>}
        right={
          <div style={{ display: 'flex', gap: 4 }}>
            <button onClick={() => go('admin-push')} style={{ width: 32, height: 32, display: 'grid', placeItems: 'center', color: GL.teal }}>
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
            </button>
            <button onClick={load} style={{ width: 32, height: 32, display: 'grid', placeItems: 'center', color: GL.muted }}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M23 4v6h-6M1 20v-6h6"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>
            </button>
          </div>
        }
      />

      {/* Stats bar */}
      <div style={{ display: 'flex', borderBottom: `2px solid ${GL.ink}`, background: GL.ink }}>
        {[
          { label: 'Needs Action', val: stats.needsAction, color: stats.needsAction > 0 ? '#FFC107' : GL.teal },
          { label: "Today's Revenue", val: `฿${stats.todayTotal.toLocaleString()}`, color: GL.teal },
          { label: 'Confirmed Today', val: stats.todayCount, color: GL.teal },
        ].map(s => (
          <div key={s.label} style={{ flex: 1, padding: '12px 8px', textAlign: 'center', borderRight: `1px solid rgba(255,255,255,0.1)` }}>
            <div className="gl-display" style={{ fontSize: 20, color: s.color }}>{s.val}</div>
            <div style={{ fontSize: 9, fontWeight: 700, color: 'rgba(255,255,255,0.45)', letterSpacing: '0.1em', textTransform: 'uppercase', marginTop: 2 }}>{s.label}</div>
          </div>
        ))}
      </div>

      {/* Search */}
      <div style={{ padding: '10px 14px', borderBottom: `1px solid ${GL.line}`, background: '#fff' }}>
        <div style={{ display: 'flex', border: `1.5px solid ${GL.line}`, background: GL.offwhite, alignItems: 'center', paddingLeft: 10 }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={GL.muted} strokeWidth="2" strokeLinecap="round" style={{ flexShrink: 0 }}><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
          <input
            value={search}
            onChange={e => setSearch(e.target.value)}
            placeholder="Search by order number…"
            style={{ flex: 1, border: 'none', background: 'transparent', outline: 'none', padding: '10px 10px', fontSize: 13 }}
          />
          {search && (
            <button onClick={() => setSearch('')} style={{ padding: '0 10px', color: GL.muted, background: 'transparent', border: 'none', fontSize: 16 }}>×</button>
          )}
        </div>
      </div>

      {/* Filter tabs */}
      <div style={{ display: 'flex', overflowX: 'auto', borderBottom: `2px solid ${GL.ink}`, background: '#fff' }} className="gl-noscroll">
        {FILTERS.map(f => (
          <button
            key={f.id}
            onClick={() => setFilter(f.id)}
            style={{
              flexShrink: 0, padding: '10px 14px', fontSize: 11, fontWeight: 800, letterSpacing: '0.1em',
              textTransform: 'uppercase', borderBottom: filter === f.id ? `3px solid ${GL.teal}` : '3px solid transparent',
              color: filter === f.id ? GL.ink : GL.muted, background: 'transparent', whiteSpace: 'nowrap',
            }}
          >
            {f.label}
          </button>
        ))}
      </div>

      {/* List */}
      <div style={{ flex: 1, overflowY: 'auto' }} className="gl-noscroll">
        {loading ? (
          <div style={{ padding: 40, textAlign: 'center', color: GL.muted, fontSize: 13 }}>Loading receipts…</div>
        ) : receipts.length === 0 ? (
          <div style={{ padding: 40, textAlign: 'center', color: GL.muted }}>
            <div style={{ fontSize: 32, marginBottom: 10 }}>📭</div>
            <div style={{ fontSize: 14, fontWeight: 700 }}>No receipts found</div>
            <div style={{ fontSize: 12, marginTop: 4 }}>
              {filter !== 'all' ? `No ${filter} receipts` : search ? `No results for "${search}"` : 'No receipts yet'}
            </div>
          </div>
        ) : (
          <>
            {receipts.map(r => (
              <ReceiptRow key={r.id} r={r} onSelect={setSelected}/>
            ))}
            {lastRefresh && (
              <div style={{ padding: '12px 16px', textAlign: 'center', fontSize: 10, color: GL.muted, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase' }}>
                Last updated {fmtTime(lastRefresh.toISOString())} · Auto-refreshes every 30s
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}

// ── Admin Push Notification Sender ────────────────────────────────────────────
function GLAdminPush({ onBack }) {
  const TEMPLATES = [
    { label: '🍝 New Drop',     title: 'New drop just landed',        body: 'Fresh pasta is ready. Order now before it sells out.' },
    { label: '👋 Miss You',     title: "We haven't seen you in a while", body: 'Your favourite pasta is waiting. Come back and order today.' },
    { label: '🔥 Flash Sale',   title: 'Flash sale — today only',     body: '20% off all orders this afternoon. Use code DROP20 at checkout.' },
    { label: '📦 Custom',       title: '',                             body: '' },
  ];

  const [tpl, setTpl]     = React.useState(0);
  const [title, setTitle] = React.useState(TEMPLATES[0].title);
  const [body, setBody]   = React.useState(TEMPLATES[0].body);
  const [sending, setSending] = React.useState(false);
  const [result, setResult]   = React.useState(null);

  const pickTemplate = (i) => {
    setTpl(i);
    setTitle(TEMPLATES[i].title);
    setBody(TEMPLATES[i].body);
    setResult(null);
  };

  const send = async () => {
    if (!title.trim() || !body.trim()) return;
    setSending(true); setResult(null);
    try {
      const res = await window.GLPush.sendToAll({ title: title.trim(), body: body.trim() });
      setResult({ ok: true, sent: res?.sent ?? 0, failed: res?.failed ?? 0 });
    } catch (e) {
      setResult({ ok: false, error: e?.message || String(e) });
    } finally { setSending(false); }
  };

  return (
    <div style={{ width: '100%', height: '100%', background: '#fff', display: 'flex', flexDirection: 'column' }}>
      <div style={{ height: 3, background: GL.teal }}/>
      <GLTopBar
        onBack={onBack}
        center={<div className="gl-display" style={{ fontSize: 13, letterSpacing: '0.14em' }}>SEND PUSH</div>}
      />

      <div style={{ flex: 1, overflowY: 'auto', padding: '24px 20px 48px' }} className="gl-noscroll">
        <h1 className="gl-display" style={{ fontSize: 36, lineHeight: 0.9, margin: '0 0 6px', color: GL.ink }}>
          Push<br/><span style={{ color: GL.teal }}>Broadcast</span>
        </h1>
        <p style={{ fontSize: 12, color: GL.muted, margin: '8px 0 24px', lineHeight: 1.6 }}>
          Sends to all subscribed users. Use for drops, promotions, and re-engagement.
        </p>

        {/* Templates */}
        <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.16em', textTransform: 'uppercase', color: GL.muted, marginBottom: 10 }}>Quick templates</div>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 24 }}>
          {TEMPLATES.map((t, i) => (
            <button key={i} onClick={() => pickTemplate(i)} style={{
              padding: '7px 12px', fontSize: 12, fontWeight: 700,
              border: `2px solid ${tpl === i ? GL.ink : GL.line}`,
              background: tpl === i ? GL.ink : '#fff',
              color: tpl === i ? '#fff' : GL.ink,
              cursor: 'pointer',
            }}>{t.label}</button>
          ))}
        </div>

        {/* Title */}
        <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.16em', textTransform: 'uppercase', color: GL.muted, marginBottom: 8 }}>Title</div>
        <input
          value={title}
          onChange={e => setTitle(e.target.value)}
          placeholder="e.g. New drop just landed"
          maxLength={60}
          style={{
            width: '100%', boxSizing: 'border-box', border: `2px solid ${GL.ink}`,
            padding: '12px 14px', fontSize: 14, fontWeight: 600, outline: 'none',
            marginBottom: 16, boxShadow: `3px 3px 0 ${GL.ink}`,
          }}
        />

        {/* Body */}
        <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.16em', textTransform: 'uppercase', color: GL.muted, marginBottom: 8 }}>Message</div>
        <textarea
          value={body}
          onChange={e => setBody(e.target.value)}
          placeholder="e.g. Fresh pasta is ready. Order now before it sells out."
          maxLength={140}
          rows={3}
          style={{
            width: '100%', boxSizing: 'border-box', border: `2px solid ${GL.ink}`,
            padding: '12px 14px', fontSize: 14, fontFamily: 'inherit', outline: 'none',
            resize: 'none', marginBottom: 6, boxShadow: `3px 3px 0 ${GL.ink}`,
          }}
        />
        <div style={{ fontSize: 11, color: GL.muted, textAlign: 'right', marginBottom: 24 }}>{body.length}/140</div>

        {/* Preview */}
        {(title || body) && (
          <div style={{ marginBottom: 24, padding: '14px 16px', background: '#F0F0F0', borderRadius: 12, display: 'flex', gap: 12, alignItems: 'flex-start' }}>
            <div style={{ width: 40, height: 40, borderRadius: 10, background: GL.ink, flexShrink: 0, display: 'grid', placeItems: 'center' }}>
              <div className="gl-display" style={{ fontSize: 18, color: GL.teal }}>G</div>
            </div>
            <div>
              <div style={{ fontSize: 13, fontWeight: 800, color: '#000', marginBottom: 2 }}>{title || 'Title…'}</div>
              <div style={{ fontSize: 12, color: '#555', lineHeight: 1.4 }}>{body || 'Message…'}</div>
            </div>
          </div>
        )}

        {/* Result */}
        {result && (
          <div style={{
            marginBottom: 20, padding: '12px 16px',
            background: result.ok ? '#D4EDDA' : '#F8D7DA',
            color: result.ok ? '#155724' : '#721C24',
            fontSize: 13, fontWeight: 700,
          }}>
            {result.ok
              ? `✓ Sent to ${result.sent} subscriber${result.sent !== 1 ? 's' : ''}${result.failed > 0 ? ` (${result.failed} failed)` : ''}`
              : `✗ Error: ${result.error}`
            }
          </div>
        )}

        {/* Send button */}
        <button
          onClick={send}
          disabled={sending || !title.trim() || !body.trim()}
          style={{
            width: '100%', height: 56, background: GL.ink, color: GL.teal,
            border: 'none', cursor: (sending || !title.trim() || !body.trim()) ? 'not-allowed' : 'pointer',
            fontSize: 14, fontWeight: 800, letterSpacing: '0.14em', textTransform: 'uppercase',
            opacity: (sending || !title.trim() || !body.trim()) ? 0.5 : 1,
            boxShadow: `4px 4px 0 ${GL.teal}33`,
          }}
        >
          {sending ? 'Sending…' : '📢 Send to All Subscribers'}
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { GLAdminReceipts, GLAdminReceiptDetail, GLAdminPush });
