/* Admin — SMS Center (MsgOwl integration + automation). */

/* ── Activity chart ── */
var CHART_COLORS = ['#f97316','#3b82f6','#22c55e','#a855f7','#ef4444','#14b8a6','#f59e0b','#6366f1'];
// Shop operation hours: 9 AM – 10 PM Maldivian time
var SHOP_HOURS   = Array.from({ length: 14 }, function(_, i) { return i + 9; }); // [9..22]
var TIME_PERIODS = [
  { start: 9,  end: 11, label: 'Morning',   icon: '☕' },
  { start: 12, end: 16, label: 'Afternoon', icon: '☀️' },
  { start: 17, end: 19, label: 'Late Aftn', icon: '🌤' },
  { start: 20, end: 22, label: 'Evening',   icon: '🌆' },
];

function SmsActivityChart({ data }) {
  if (!data || data.grandTotal === 0) {
    return (
      <div style={{ padding: '18px 0', textAlign: 'center', color: 'var(--grey-400)', fontSize: 12.5 }}>
        No sent triggers yet — chart appears after automation sends its first messages.
      </div>
    );
  }

  var hourlyByOutlet = data.hourlyByOutlet;
  var outletTotals   = data.outletTotals;
  var topOutlets     = data.topOutlets || [];

  // Assign colors
  var outletColors = {};
  topOutlets.forEach(function(o, i) { outletColors[o] = CHART_COLORS[i % CHART_COLORS.length]; });

  // Max hourly total for bar scaling — shop hours only
  var maxHourly = 1;
  SHOP_HOURS.forEach(function(h) {
    var hTotal = Object.values(hourlyByOutlet[h] || {}).reduce(function(s, v) { return s + v; }, 0);
    if (hTotal > maxHourly) maxHourly = hTotal;
  });
  var maxOutlet = Math.max.apply(null, Object.values(outletTotals).concat([1]));

  var BAR_H = 110;
  var X_LABELS = { 9: '09', 12: '12', 15: '15', 18: '18', 21: '21', 22: '22' };

  return (
    <div>
      {/* ── 24-hour bar chart ── */}
      <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 12 }}>
        Trigger activity · Hour of day (Maldives time)
      </div>

      <div style={{ position: 'relative', height: BAR_H + 32, marginBottom: 10 }}>
        {/* Gridlines */}
        {[0.25, 0.5, 0.75, 1].map(function(pct) {
          return (
            <div key={pct} style={{ position: 'absolute', bottom: 32 + BAR_H * pct, left: 0, right: 0, borderTop: '1px dashed var(--grey-100)', zIndex: 0 }} />
          );
        })}

        {/* Bars */}
        <div style={{ position: 'absolute', bottom: 32, left: 0, right: 0, height: BAR_H, display: 'flex', alignItems: 'flex-end', gap: 2 }}>
          {SHOP_HOURS.map(function(hr) {
            var hourData = hourlyByOutlet[hr] || {};
            var total    = Object.values(hourData).reduce(function(s, v) { return s + v; }, 0);
            var barH     = total === 0 ? 0 : Math.max(3, Math.round((total / maxHourly) * BAR_H));
            var allOutlets = topOutlets.concat(
              Object.keys(hourData).filter(function(o) { return topOutlets.indexOf(o) === -1; })
            );
            return (
              <div key={hr} style={{ flex: 1, height: '100%', display: 'flex', alignItems: 'flex-end' }}
                title={'Hour ' + String(hr).padStart(2, '0') + ':00–' + String(hr).padStart(2,'0') + ':59 · ' + total + ' triggers'}>
                <div style={{ width: '100%', height: barH, borderRadius: '2px 2px 0 0', overflow: 'hidden', display: 'flex', flexDirection: 'column-reverse' }}>
                  {allOutlets.map(function(outlet) {
                    var count = hourData[outlet] || 0;
                    if (!count) return null;
                    var segH = Math.round((count / total) * barH);
                    return <div key={outlet} style={{ height: segH, background: outletColors[outlet] || '#94a3b8', flexShrink: 0 }} />;
                  })}
                </div>
              </div>
            );
          })}
        </div>

        {/* X-axis hour labels */}
        <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 28, display: 'flex', alignItems: 'center' }}>
          {SHOP_HOURS.map(function(hr) {
            return (
              <div key={hr} style={{ flex: 1, textAlign: 'center', fontSize: 9, fontWeight: 700, color: X_LABELS[hr] ? 'var(--grey-600)' : 'transparent', userSelect: 'none' }}>
                {X_LABELS[hr] || '·'}
              </div>
            );
          })}
        </div>
      </div>

      {/* Period summary chips */}
      <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap', marginBottom: 18 }}>
        {TIME_PERIODS.map(function(p) {
          var periodTotal = 0;
          for (var h = p.start; h <= p.end; h++) {
            periodTotal += Object.values(hourlyByOutlet[h] || {}).reduce(function(s, v) { return s + v; }, 0);
          }
          var pct = data.grandTotal > 0 ? Math.round((periodTotal / data.grandTotal) * 100) : 0;
          return (
            <span key={p.label} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11, fontWeight: 700, background: 'var(--grey-50)', border: '1px solid var(--grey-200)', borderRadius: 5, padding: '4px 10px', color: 'var(--grey-700)' }}>
              {p.icon} {p.label}
              <span style={{ color: 'var(--grey-400)', fontWeight: 500 }}>{periodTotal} ({pct}%)</span>
            </span>
          );
        })}
      </div>

      {/* Legend */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, marginBottom: 20 }}>
        {topOutlets.slice(0, 8).map(function(outlet) {
          return (
            <span key={outlet} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 11.5, fontWeight: 600, color: 'var(--grey-700)' }}>
              <span style={{ width: 9, height: 9, borderRadius: 2, background: outletColors[outlet], flexShrink: 0 }} />
              {outlet}
            </span>
          );
        })}
      </div>

      {/* ── Outlet performance bars ── */}
      <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 10 }}>
        Outlet performance
      </div>
      {topOutlets.slice(0, 10).map(function(outlet) {
        var total   = outletTotals[outlet] || 0;
        var pct     = data.grandTotal > 0 ? Math.round((total / data.grandTotal) * 100) : 0;
        var barW    = maxOutlet > 0 ? (total / maxOutlet) * 100 : 0;
        return (
          <div key={outlet} style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
            <div style={{ width: 130, fontSize: 12, fontWeight: 600, color: 'var(--ink)', flexShrink: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={outlet}>
              {outlet}
            </div>
            <div style={{ flex: 1, height: 10, background: 'var(--grey-100)', borderRadius: 20, overflow: 'hidden' }}>
              <div style={{ width: barW + '%', height: '100%', background: outletColors[outlet] || '#94a3b8', borderRadius: 20, transition: 'width 0.5s ease' }} />
            </div>
            <div style={{ width: 66, textAlign: 'right', fontSize: 11.5, fontWeight: 700, color: 'var(--grey-600)', flexShrink: 0, whiteSpace: 'nowrap' }}>
              {total} <span style={{ color: 'var(--grey-400)', fontWeight: 500 }}>({pct}%)</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ── Automation sub-component ── */
var PIP_SMS_QUIPS = [
  '📡 All quiet... watching for new bills!',
  '🐧 Automation is live and standing by!',
  '📊 Stats updated — looking good so far!',
  '🔍 Scanning... no new triggers since last check.',
  '⏱ 20 seconds down, still on watch!',
];

function SmsAutomation({ adminToken, mascotRef }) {
  var [stats, setStats]         = useState(null);
  var [log, setLog]             = useState([]);
  var [settings, setSettings]   = useState({});
  var [loading, setLoading]     = useState(true);
  var [toggling, setToggling]   = useState(false);
  var [running, setRunning]     = useState(false);
  var [runResult, setRunResult] = useState(null);
  var [editTpl, setEditTpl]     = useState(false);
  var [tplDraft, setTplDraft]   = useState('');
  var [chartData, setChartData] = useState(null);
  var [logOpen, setLogOpen]     = useState(false);

  var prevSentRef      = useRef(null);
  var prevFailedRef    = useRef(null);
  var refreshCountRef  = useRef(0);

  var h = { 'x-admin-key': adminToken };

  function pipSay(msg) {
    if (mascotRef && mascotRef.current && mascotRef.current.say) {
      mascotRef.current.say(msg);
    }
  }

  function loadAll() {
    setLoading(true);
    Promise.all([
      fetch('/api/sms-automation?action=stats',  { headers: h }).then(function(r) { return r.json(); }),
      fetch('/api/sms-automation?action=log',    { headers: h }).then(function(r) { return r.json(); }),
      fetch('/api/sms-automation?action=chart',  { headers: h }).then(function(r) { return r.json(); }),
    ]).then(function(res) {
      var s = res[0], l = res[1], c = res[2];
      if (s && s.counts) setStats(s.counts);
      if (s && s.settings) setSettings(s.settings);
      if (Array.isArray(l)) setLog(l);
      if (c && c.hourlyByOutlet) setChartData(c);
      setLoading(false);

      // Pip reactions
      refreshCountRef.current++;
      var isEnabled = s && s.settings && s.settings['enabled'] === 'true';
      var newSent    = s && s.counts ? s.counts.sent   : null;
      var newFailed  = s && s.counts ? s.counts.failed : null;

      if (newSent !== null && prevSentRef.current !== null && newSent > prevSentRef.current) {
        var diff = newSent - prevSentRef.current;
        pipSay('📲 ' + diff + ' new SMS just fired! Automation is working! 🔥');
      } else if (newFailed !== null && prevFailedRef.current !== null && newFailed > prevFailedRef.current) {
        var fails = newFailed - prevFailedRef.current;
        pipSay('⚠️ ' + fails + ' SMS failed this round. Check MsgOwl balance or number.');
      } else if (refreshCountRef.current > 1 && refreshCountRef.current % 4 === 0) {
        var q = isEnabled
          ? PIP_SMS_QUIPS[Math.floor(Math.random() * PIP_SMS_QUIPS.length)]
          : '💤 Automation is OFF — enable to start auto-SMS!';
        pipSay(q);
      }

      if (newSent   !== null) prevSentRef.current   = newSent;
      if (newFailed !== null) prevFailedRef.current = newFailed;
    }).catch(function() { setLoading(false); });
  }

  useEffect(function() {
    loadAll();
    var t = setInterval(loadAll, 20000);
    return function() { clearInterval(t); };
  }, []);

  var enabled = settings['enabled'] === 'true';
  var templateBody = settings['template_body'] || '';
  var lastRun = settings['last_run_at'] || null;

  function handleToggle() {
    setToggling(true);
    fetch('/api/sms-automation', {
      method: 'POST',
      headers: Object.assign({ 'Content-Type': 'application/json' }, h),
      body: JSON.stringify({ action: 'toggle', enabled: !enabled }),
    }).then(function(r) { return r.json(); }).then(function() {
      setSettings(function(s) { return Object.assign({}, s, { enabled: (!enabled).toString() }); });
      setToggling(false);
    }).catch(function() { setToggling(false); });
  }

  function handleRunNow() {
    setRunning(true);
    setRunResult(null);
    fetch('/api/sms-trigger-check', {
      method: 'POST',
      headers: h,
    }).then(function(r) { return r.json(); }).then(function(d) {
      setRunResult(d);
      setRunning(false);
      setTimeout(loadAll, 800);
    }).catch(function() { setRunning(false); });
  }

  function handleSaveTpl() {
    fetch('/api/sms-automation', {
      method: 'POST',
      headers: Object.assign({ 'Content-Type': 'application/json' }, h),
      body: JSON.stringify({ action: 'template', template_body: tplDraft }),
    }).then(function() {
      setSettings(function(s) { return Object.assign({}, s, { template_body: tplDraft }); });
      setEditTpl(false);
    });
  }

  var tplStat = tplDraft ? { chars: tplDraft.length, parts: Math.max(1, Math.ceil(tplDraft.length / 160)) } : null;

  return (
    <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 10, overflow: 'hidden', marginBottom: 22 }}>
      {/* Header */}
      <div style={{ background: enabled ? '#166534' : 'var(--ink)', color: '#fff', padding: '14px 18px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <span style={{ fontSize: 13.5, fontWeight: 700 }}>⚡ Automation</span>
          <span style={{
            background: enabled ? '#bbf7d0' : 'rgba(255,255,255,0.15)',
            color: enabled ? '#166534' : '#fff',
            borderRadius: 4, padding: '2px 9px', fontSize: 10.5, fontWeight: 800, letterSpacing: '0.1em',
          }}>
            {enabled ? 'LIVE' : 'OFF'}
          </span>
        </div>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          <button onClick={handleRunNow} disabled={running}
            style={{ background: 'rgba(255,255,255,0.15)', border: '1px solid rgba(255,255,255,0.3)', borderRadius: 5, padding: '5px 14px', fontSize: 11.5, fontWeight: 700, color: '#fff', cursor: running ? 'default' : 'pointer' }}>
            {running ? 'Running…' : '▶ Run Now'}
          </button>
          <button onClick={handleToggle} disabled={toggling}
            style={{ background: enabled ? '#ef4444' : 'var(--orange)', border: 'none', borderRadius: 5, padding: '6px 16px', fontSize: 12, fontWeight: 800, color: '#fff', cursor: 'pointer', letterSpacing: '0.04em' }}>
            {toggling ? '…' : enabled ? 'Disable' : 'Enable'}
          </button>
        </div>
      </div>

      <div style={{ padding: 18 }}>
        {/* Run result banner */}
        {runResult && (
          <div style={{ padding: '10px 14px', borderRadius: 6, marginBottom: 14, fontSize: 12.5, fontWeight: 600, background: runResult.error ? '#fee2e2' : '#f0fdf4', color: runResult.error ? '#991b1b' : '#166534', border: '1px solid ' + (runResult.error ? '#fecaca' : '#bbf7d0') }}>
            {runResult.error
              ? '❌ Error: ' + runResult.error
              : '✅ Processed ' + (runResult.processed || 0) + ' entries — Sent: ' + (runResult.sent || 0) + ' · Skipped: ' + (runResult.skipped || 0) + ' · Failed: ' + (runResult.failed || 0)
            }
          </div>
        )}

        {/* Stats + template row */}
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginBottom: 16 }} className="sms-auto-grid">

          {/* Counts */}
          <div>
            <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 10 }}>Trigger counts (all time)</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
              {[
                { key: 'total',   label: 'Total',   color: 'var(--ink)' },
                { key: 'sent',    label: 'Sent',    color: '#22c55e' },
                { key: 'skipped', label: 'Skipped', color: 'var(--grey-400)' },
                { key: 'failed',  label: 'Failed',  color: '#ef4444' },
              ].map(function(c) {
                return (
                  <div key={c.key} style={{ background: 'var(--grey-50)', borderRadius: 6, padding: '10px 8px', textAlign: 'center' }}>
                    <div style={{ fontSize: 22, fontWeight: 800, color: c.color, fontFamily: 'Nunito, sans-serif', lineHeight: 1.1 }}>
                      {loading ? '—' : (stats ? (stats[c.key] || 0) : '—')}
                    </div>
                    <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--grey-500)', marginTop: 3, letterSpacing: '0.06em', textTransform: 'uppercase' }}>{c.label}</div>
                  </div>
                );
              })}
            </div>
            {lastRun && (
              <div style={{ fontSize: 11, color: 'var(--grey-400)', marginTop: 8 }}>
                Last run: {new Date(lastRun).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: true })}
              </div>
            )}
          </div>

          {/* Template */}
          <div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
              <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)' }}>Active template</div>
              {!editTpl && (
                <button onClick={function() { setEditTpl(true); setTplDraft(templateBody); }}
                  style={{ background: 'none', border: '1px solid var(--grey-200)', borderRadius: 4, padding: '3px 10px', fontSize: 11, fontWeight: 600, color: 'var(--grey-600)', cursor: 'pointer' }}>
                  Edit
                </button>
              )}
            </div>
            {editTpl ? (
              <div>
                <textarea value={tplDraft} onChange={function(e) { setTplDraft(e.target.value); }}
                  rows={4}
                  style={{ width: '100%', boxSizing: 'border-box', padding: '8px 10px', border: '1px solid var(--orange)', borderRadius: 6, fontSize: 12.5, color: 'var(--ink)', outline: 'none', resize: 'vertical', lineHeight: 1.5 }} />
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 6 }}>
                  <span style={{ fontSize: 11, fontWeight: 700, color: tplStat && tplStat.parts > 1 ? '#ef4444' : 'var(--grey-400)' }}>
                    {tplStat ? tplStat.chars + ' chars · ' + tplStat.parts + ' SMS' : ''}
                  </span>
                  <div style={{ display: 'flex', gap: 6 }}>
                    <button onClick={function() { setEditTpl(false); }}
                      style={{ background: 'var(--grey-100)', border: 'none', borderRadius: 4, padding: '5px 12px', fontSize: 11.5, fontWeight: 700, color: 'var(--grey-600)', cursor: 'pointer' }}>Cancel</button>
                    <button onClick={handleSaveTpl}
                      style={{ background: 'var(--ink)', border: 'none', borderRadius: 4, padding: '5px 14px', fontSize: 11.5, fontWeight: 800, color: '#fff', cursor: 'pointer' }}>Save</button>
                  </div>
                </div>
              </div>
            ) : (
              <div style={{ background: 'var(--grey-50)', border: '1px solid var(--grey-200)', borderRadius: 6, padding: '10px 12px', fontSize: 12.5, color: 'var(--grey-700)', lineHeight: 1.5, wordBreak: 'break-word' }}>
                {templateBody || <span style={{ color: 'var(--grey-400)' }}>No template set</span>}
                {templateBody && (
                  <div style={{ marginTop: 6, fontSize: 11, fontWeight: 700, color: Math.ceil(templateBody.length / 160) > 1 ? '#ef4444' : 'var(--grey-400)' }}>
                    {templateBody.length} chars · {Math.max(1, Math.ceil(templateBody.length / 160))} SMS
                  </div>
                )}
              </div>
            )}
          </div>
        </div>

        {/* ── Activity chart ── */}
        <div style={{ borderTop: '1px solid var(--grey-100)', paddingTop: 18, marginBottom: 20 }}>
          <SmsActivityChart data={chartData} />
        </div>

        {/* Trigger log — collapsible */}
        <div style={{ border: '1px solid var(--grey-200)', borderRadius: 8, overflow: 'hidden' }}>
          <button
            onClick={function() { setLogOpen(function(v) { return !v; }); }}
            style={{ width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '11px 14px', background: 'var(--grey-50)', border: 'none', cursor: 'pointer', textAlign: 'left' }}>
            <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)' }}>
              Trigger log (last 50){log.length > 0 ? ' · ' + log.length + ' entries' : ''}
            </span>
            <span style={{ fontSize: 13, color: 'var(--grey-400)', transform: logOpen ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 0.2s', display: 'inline-block' }}>▾</span>
          </button>

          {logOpen && (
            <div style={{ padding: '12px 14px' }}>
              <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 10 }}>
                <button onClick={loadAll} style={{ background: 'none', border: '1px solid var(--grey-200)', borderRadius: 4, padding: '3px 10px', fontSize: 11, fontWeight: 600, color: 'var(--grey-600)', cursor: 'pointer' }}>
                  ↻ Refresh
                </button>
              </div>
              {loading ? (
                <div style={{ fontSize: 12.5, color: 'var(--grey-400)', padding: '8px 0' }}>Loading…</div>
              ) : log.length === 0 ? (
                <div style={{ fontSize: 12.5, color: 'var(--grey-400)', padding: '8px 0' }}>
                  No triggers yet. Enable automation and new bill entries with valid mobile numbers will be logged here.
                </div>
              ) : (
                <div style={{ overflowX: 'auto' }}>
                  <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
                    <thead>
                      <tr style={{ borderBottom: '1.5px solid var(--grey-200)' }}>
                        {['Time', 'Bill #', 'Mobile', 'Status', 'Detail'].map(function(col) {
                          return <th key={col} style={{ padding: '6px 10px', textAlign: 'left', fontSize: 10.5, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--grey-500)', whiteSpace: 'nowrap' }}>{col}</th>;
                        })}
                      </tr>
                    </thead>
                    <tbody>
                      {log.map(function(row) {
                        var d = new Date(row.triggered_at);
                        var dateStr = d.toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: true });
                        var mobileMasked = row.mobile_e164 ? row.mobile_e164.slice(0, -4).replace(/./g, '•') + row.mobile_e164.slice(-4) : '—';
                        var statusColor = row.status === 'sent' ? '#22c55e' : row.status === 'failed' ? '#ef4444' : 'var(--grey-400)';
                        return (
                          <tr key={row.id} style={{ borderBottom: '1px solid var(--grey-100)' }}>
                            <td style={{ padding: '7px 10px', color: 'var(--grey-500)', whiteSpace: 'nowrap' }}>{dateStr}</td>
                            <td style={{ padding: '7px 10px', fontWeight: 600, color: 'var(--ink)' }}>{row.bill_number || '—'}</td>
                            <td style={{ padding: '7px 10px', fontFamily: 'monospace', color: 'var(--grey-600)' }}>{mobileMasked}</td>
                            <td style={{ padding: '7px 10px' }}>
                              <span style={{ color: statusColor, fontWeight: 700, textTransform: 'capitalize' }}>{row.status}</span>
                            </td>
                            <td style={{ padding: '7px 10px', color: 'var(--grey-400)', fontSize: 11 }}>
                              {row.status === 'sent' && row.msgowl_id ? 'ID #' + row.msgowl_id : row.skip_reason || '—'}
                            </td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ── Default templates (seed on first load) ── */
var SMS_DEFAULT_TEMPLATES = [
  {
    id: 'instant-notice',
    name: 'Instant Notice',
    body: "You've purchased over MVR 1000, get a chance to Win daily Pizzas by JELLY, weekly prizes & GRAND MVR 50,000 SUNFRONT voucher. Join now: worldcup.sunfront.com.mv",
  },
  {
    id: 'sms-blast',
    name: 'SMS Blast',
    body: "Spend MVR 1000 and stand a chance to Win daily Pizzas by JELLY, weekly prizes & GRAND MVR 50,000 SUNFRONT voucher. Join now: worldcup.sunfront.com.mv",
  },
];

var SMS_TPL_KEY = 'sf_sms_templates';

function loadTemplates() {
  try {
    var raw = localStorage.getItem(SMS_TPL_KEY);
    if (raw) return JSON.parse(raw);
  } catch (e) {}
  return SMS_DEFAULT_TEMPLATES.map(function(t) { return Object.assign({}, t); });
}

function saveTemplates(list) {
  try { localStorage.setItem(SMS_TPL_KEY, JSON.stringify(list)); } catch (e) {}
}

function smsCount(text) {
  var len = (text || '').length;
  return { chars: len, parts: len === 0 ? 0 : Math.ceil(len / 160) };
}

/* ── Status map ── */
var STATUS_MAP = {
  1: { label: 'Queued',    color: '#94a3b8' },
  2: { label: 'Sending',   color: 'var(--orange)' },
  3: { label: 'Sent',      color: '#2563eb' },
  4: { label: 'Delivered', color: '#22c55e' },
};

function SmsStatusDot({ status }) {
  var s = STATUS_MAP[status] || { label: 'Unknown', color: '#94a3b8' };
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11, fontWeight: 700, color: s.color }}>
      <span style={{ width: 7, height: 7, borderRadius: '50%', background: s.color, flexShrink: 0 }} />
      {s.label}
    </span>
  );
}

/* ── CharBadge ── */
function CharBadge({ text }) {
  var stat = smsCount(text);
  if (stat.chars === 0) return null;
  var over = stat.parts > 1;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      fontSize: 11, fontWeight: 700,
      color: over ? '#ef4444' : 'var(--grey-500)',
    }}>
      {stat.chars} chars
      <span style={{
        background: over ? '#fee2e2' : 'var(--grey-100)',
        color: over ? '#ef4444' : 'var(--grey-600)',
        borderRadius: 4, padding: '1px 7px', fontSize: 10.5, fontWeight: 800,
      }}>
        {stat.parts} SMS
      </span>
    </span>
  );
}

/* ── Template card ── */
function SmsTemplateCard({ tpl, onUse, onSave, onDelete, isEditing, editDraft, setEditDraft, onEdit, onCancelEdit }) {
  var draftStat = smsCount(isEditing ? editDraft.body : '');

  if (isEditing) {
    return (
      <div style={{ background: '#fff', border: '2px solid var(--orange)', borderRadius: 8, padding: 14 }}>
        <input
          value={editDraft.name}
          onChange={function(e) { setEditDraft(function(d) { return Object.assign({}, d, { name: e.target.value }); }); }}
          placeholder="Template name"
          style={{ width: '100%', boxSizing: 'border-box', padding: '8px 10px', border: '1px solid var(--grey-200)', borderRadius: 5, fontSize: 13, fontWeight: 700, color: 'var(--ink)', outline: 'none', marginBottom: 10 }}
        />
        <textarea
          value={editDraft.body}
          onChange={function(e) { setEditDraft(function(d) { return Object.assign({}, d, { body: e.target.value }); }); }}
          rows={4}
          placeholder="Message body…"
          style={{ width: '100%', boxSizing: 'border-box', padding: '8px 10px', border: '1px solid var(--grey-200)', borderRadius: 5, fontSize: 12.5, color: 'var(--ink)', outline: 'none', resize: 'vertical', lineHeight: 1.5 }}
        />
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 10 }}>
          <CharBadge text={editDraft.body} />
          <div style={{ display: 'flex', gap: 7 }}>
            <button onClick={onCancelEdit}
              style={{ background: 'var(--grey-100)', border: 'none', borderRadius: 5, padding: '6px 14px', fontSize: 12, fontWeight: 700, color: 'var(--grey-600)', cursor: 'pointer' }}>
              Cancel
            </button>
            <button onClick={function() { onSave(editDraft); }}
              disabled={!editDraft.name.trim() || !editDraft.body.trim()}
              style={{ background: !editDraft.name.trim() || !editDraft.body.trim() ? 'var(--grey-200)' : 'var(--ink)', border: 'none', borderRadius: 5, padding: '6px 18px', fontSize: 12, fontWeight: 800, color: !editDraft.name.trim() || !editDraft.body.trim() ? 'var(--grey-400)' : '#fff', cursor: !editDraft.name.trim() || !editDraft.body.trim() ? 'not-allowed' : 'pointer' }}>
              Save
            </button>
          </div>
        </div>
      </div>
    );
  }

  var stat = smsCount(tpl.body);
  return (
    <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 8, padding: 14, display: 'flex', flexDirection: 'column', gap: 8 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 8 }}>
        <div style={{ fontSize: 13, fontWeight: 800, color: 'var(--ink)' }}>{tpl.name}</div>
        <div style={{ display: 'flex', gap: 5, flexShrink: 0 }}>
          <button onClick={function() { onUse(tpl.body); }}
            style={{ background: 'var(--orange)', border: 'none', borderRadius: 5, padding: '4px 12px', fontSize: 11.5, fontWeight: 800, color: '#fff', cursor: 'pointer', letterSpacing: '0.04em' }}>
            Use
          </button>
          <button onClick={function() { onEdit(tpl); }}
            style={{ background: 'var(--grey-100)', border: 'none', borderRadius: 5, padding: '4px 10px', fontSize: 11.5, fontWeight: 700, color: 'var(--grey-700)', cursor: 'pointer' }}>
            Edit
          </button>
          <button onClick={function() { onDelete(tpl.id); }}
            title="Delete template"
            style={{ background: 'none', border: '1px solid var(--grey-200)', borderRadius: 5, padding: '4px 8px', fontSize: 12, color: '#ef4444', cursor: 'pointer', lineHeight: 1 }}>
            ×
          </button>
        </div>
      </div>
      <div style={{ fontSize: 12.5, color: 'var(--grey-600)', lineHeight: 1.5, wordBreak: 'break-word' }}>
        {tpl.body}
      </div>
      <div>
        <CharBadge text={tpl.body} />
      </div>
    </div>
  );
}

/* ── Main component ── */
function AdminSMS({ ctx }) {
  var adminToken = ctx.adminToken;
  var livePredictions = ctx.livePredictions;

  /* ── Template state ── */
  var [templates, setTemplates]     = useState(function() { return loadTemplates(); });
  var [editingId, setEditingId]     = useState(null); // null | 'new' | tpl.id
  var [editDraft, setEditDraft]     = useState({ name: '', body: '' });

  function persistTemplates(list) {
    setTemplates(list);
    saveTemplates(list);
  }

  function handleUseTemplate(body) {
    setBody(body);
    var composeEl = document.getElementById('sms-compose-panel');
    if (composeEl) composeEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }

  function handleEditTemplate(tpl) {
    setEditingId(tpl.id);
    setEditDraft({ name: tpl.name, body: tpl.body });
  }

  function handleSaveTemplate(draft) {
    if (editingId === 'new') {
      var newTpl = { id: 'tpl_' + Date.now(), name: draft.name.trim(), body: draft.body.trim() };
      persistTemplates([newTpl].concat(templates));
    } else {
      persistTemplates(templates.map(function(t) {
        return t.id === editingId ? Object.assign({}, t, { name: draft.name.trim(), body: draft.body.trim() }) : t;
      }));
    }
    setEditingId(null);
  }

  function handleDeleteTemplate(id) {
    if (!window.confirm('Delete this template?')) return;
    persistTemplates(templates.filter(function(t) { return t.id !== id; }));
  }

  function handleCancelEdit() {
    setEditingId(null);
  }

  function handleNewTemplate() {
    setEditingId('new');
    setEditDraft({ name: '', body: '' });
  }

  /* ── Compose state ── */
  var [body, setBody]                     = useState('');
  var [senderId, setSenderId]             = useState('');
  var [recipientMode, setRecipientMode]   = useState('manual');
  var [manualNumbers, setManualNumbers]   = useState('');
  var [selectedOutlet, setSelectedOutlet] = useState('');
  var [excelNumbers, setExcelNumbers]     = useState([]);
  var [excelFileName, setExcelFileName]   = useState('');
  var [excelStats, setExcelStats]         = useState(null);
  var [excelParsing, setExcelParsing]     = useState(false);
  var [excelError, setExcelError]         = useState('');
  var [sending, setSending]               = useState(false);
  var [sendResult, setSendResult]         = useState(null);

  /* ── Dashboard data ── */
  var [balance, setBalance]   = useState(null);
  var [senders, setSenders]   = useState([]);
  var [messages, setMessages] = useState([]);
  var [loading, setLoading]   = useState(true);
  var [apiMissing, setApiMissing] = useState(false);

  function loadData() {
    setLoading(true);
    var h = { 'x-admin-key': adminToken };
    Promise.all([
      fetch('/api/sms-proxy?action=balance',  { headers: h }).then(function(r) { return r.json(); }),
      fetch('/api/sms-proxy?action=senders',  { headers: h }).then(function(r) { return r.json(); }),
      fetch('/api/sms-proxy?action=messages', { headers: h }).then(function(r) { return r.json(); }),
    ]).then(function(results) {
      var bal = results[0], snds = results[1], msgs = results[2];
      if (bal && bal.error && bal.error.indexOf('MSGOWL_API_KEY') !== -1) setApiMissing(true);
      if (bal && bal.balance != null) setBalance(parseFloat(bal.balance).toFixed(2));
      if (Array.isArray(snds)) {
        setSenders(snds);
        if (snds.length > 0) setSenderId(function(prev) { return prev || snds[0].name || String(snds[0].id || ''); });
      }
      if (Array.isArray(msgs)) setMessages(msgs);
      setLoading(false);
    }).catch(function() { setLoading(false); });
  }

  useEffect(function() { loadData(); }, []);

  /* ── Excel file parser ── */
  function handleExcelFile(file) {
    if (!file) return;
    if (!window.XLSX) { setExcelError('Excel library not loaded — refresh and try again.'); return; }
    setExcelParsing(true); setExcelError(''); setExcelNumbers([]); setExcelStats(null);
    var reader = new FileReader();
    reader.onload = function(e) {
      try {
        var wb = window.XLSX.read(new Uint8Array(e.target.result), { type: 'array' });
        var valid = [], seen = {}, invalidCount = 0;
        wb.SheetNames.forEach(function(name) {
          var rows = window.XLSX.utils.sheet_to_json(wb.Sheets[name], { header: 1, defval: '' });
          rows.forEach(function(row) {
            (row || []).forEach(function(cell) {
              var raw = String(cell || '').trim();
              if (!raw) return;
              var stripped = raw.replace(/[\s\-().]/g, '').replace(/^\+/, '');
              if (!/^\d{7,12}$/.test(stripped)) return; // not digit-only
              var norm;
              if (/^960[79]\d{6}$/.test(stripped)) { norm = stripped; }
              else if (/^[79]\d{6}$/.test(stripped)) { norm = '960' + stripped; }
              else { invalidCount++; return; }
              if (!seen[norm]) { seen[norm] = true; valid.push(norm); }
            });
          });
        });
        setExcelNumbers(valid);
        setExcelStats({ valid: valid.length, invalid: invalidCount });
        setExcelFileName(file.name);
        setExcelParsing(false);
      } catch (err) {
        setExcelError('Parse error: ' + (err.message || 'Unknown'));
        setExcelParsing(false);
      }
    };
    reader.readAsArrayBuffer(file);
  }

  function clearExcel() {
    setExcelNumbers([]); setExcelFileName(''); setExcelStats(null); setExcelError('');
  }

  /* ── Recipients ── */
  var recipientPhones = useMemo(function() {
    if (recipientMode === 'excel') return excelNumbers;
    if (recipientMode === 'all') {
      var s = {};
      (livePredictions || []).forEach(function(p) { if (p.customerPhone) s[String(p.customerPhone).replace(/^\+/, '')] = true; });
      return Object.keys(s);
    }
    if (recipientMode === 'outlet') {
      var o = {};
      (livePredictions || []).filter(function(p) { return p.outlet === selectedOutlet; }).forEach(function(p) {
        if (p.customerPhone) o[String(p.customerPhone).replace(/^\+/, '')] = true;
      });
      return Object.keys(o);
    }
    return manualNumbers.split(/[,\n]+/).map(function(n) { return n.trim().replace(/^\+/, ''); }).filter(Boolean);
  }, [recipientMode, manualNumbers, selectedOutlet, livePredictions, excelNumbers]);

  var outlets = useMemo(function() {
    var s = {};
    (livePredictions || []).forEach(function(p) { if (p.outlet) s[p.outlet] = true; });
    return Object.keys(s).sort();
  }, [livePredictions]);

  var uniquePhoneCount = useMemo(function() {
    var s = {};
    (livePredictions || []).forEach(function(p) { if (p.customerPhone) s[p.customerPhone] = true; });
    return Object.keys(s).length;
  }, [livePredictions]);

  var bodyStat = smsCount(body);

  /* ── Send ── */
  function handleSend() {
    if (!body.trim() || recipientPhones.length === 0 || !senderId) return;
    setSending(true);
    setSendResult(null);
    fetch('/api/sms-proxy', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'x-admin-key': adminToken },
      body: JSON.stringify({ action: 'send', recipients: recipientPhones.join(','), sender_id: senderId, body: body.trim() }),
    }).then(function(r) {
      return r.json().then(function(d) { return { ok: r.ok, d: d }; });
    }).then(function(res) {
      if (res.ok) {
        setSendResult({ ok: true, message: 'Sent! Message ID: ' + (res.d.id || '—') });
        setTimeout(loadData, 2000);
      } else {
        setSendResult({ ok: false, message: res.d.message || res.d.error || 'Send failed' });
      }
      setSending(false);
    }).catch(function() {
      setSendResult({ ok: false, message: 'Network error — check connection' });
      setSending(false);
    });
  }

  /* ── API key missing ── */
  if (apiMissing) {
    return (
      <div style={{ maxWidth: 560, margin: '40px auto', padding: '0 16px' }}>
        <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderLeft: '4px solid var(--orange)', borderRadius: 8, padding: 28 }}>
          <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--ink)', marginBottom: 10 }}>⚙️ MsgOwl API Key Required</div>
          <ol style={{ fontSize: 13, color: 'var(--grey-600)', lineHeight: 2.2, paddingLeft: 20, margin: '0 0 14px' }}>
            <li>Log in to <strong>msgowl.com</strong> → Settings → API Keys</li>
            <li>Create key — scopes: <code style={{ background: 'var(--grey-100)', padding: '1px 5px', borderRadius: 3 }}>message.write message.read account.balance.read sms_headers.read</code></li>
            <li>Vercel → Project → Settings → Environment Variables</li>
            <li>Add <strong>MSGOWL_API_KEY</strong> = your key, then redeploy</li>
          </ol>
          <button onClick={loadData} style={{ background: 'var(--ink)', color: '#fff', border: 'none', borderRadius: 6, padding: '9px 20px', fontSize: 12.5, fontWeight: 700, cursor: 'pointer' }}>
            Retry
          </button>
        </div>
      </div>
    );
  }

  var sendDisabled = sending || !body.trim() || recipientPhones.length === 0 || !senderId;

  return (
    <div style={{ maxWidth: 1080, margin: '0 auto' }}>

      {/* ── Automation ── */}
      <SmsAutomation adminToken={adminToken} mascotRef={ctx.mascotRef} />

      {/* ── Stat cards ── */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14, marginBottom: 26 }} className="sms-stats-grid">
        <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderTop: '3px solid var(--orange)', borderRadius: '0 0 8px 8px', padding: '14px 18px' }}>
          <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 6 }}>MsgOwl Balance</div>
          <div style={{ fontSize: 28, fontWeight: 800, color: 'var(--ink)', fontFamily: 'Nunito, sans-serif' }}>
            {loading ? '…' : balance != null ? 'MVR ' + balance : '—'}
          </div>
        </div>
        <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderTop: '3px solid #2563eb', borderRadius: '0 0 8px 8px', padding: '14px 18px' }}>
          <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 6 }}>Messages Logged</div>
          <div style={{ fontSize: 28, fontWeight: 800, color: 'var(--ink)', fontFamily: 'Nunito, sans-serif' }}>{loading ? '…' : messages.length}</div>
        </div>
        <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderTop: '3px solid #22c55e', borderRadius: '0 0 8px 8px', padding: '14px 18px' }}>
          <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 6 }}>Unique Predictors</div>
          <div style={{ fontSize: 28, fontWeight: 800, color: 'var(--ink)', fontFamily: 'Nunito, sans-serif' }}>{uniquePhoneCount}</div>
        </div>
      </div>

      {/* ── Templates section ── */}
      <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 10, overflow: 'hidden', marginBottom: 22 }}>
        <div style={{ background: 'var(--ink)', color: '#fff', padding: '14px 18px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span style={{ fontSize: 13.5, fontWeight: 700 }}>📋 SMS Templates</span>
          <button onClick={handleNewTemplate} disabled={editingId === 'new'}
            style={{ background: editingId === 'new' ? 'rgba(255,255,255,0.15)' : 'var(--orange)', border: 'none', borderRadius: 5, padding: '6px 14px', fontSize: 12, fontWeight: 800, color: '#fff', cursor: editingId === 'new' ? 'default' : 'pointer', letterSpacing: '0.05em' }}>
            + New Template
          </button>
        </div>
        <div style={{ padding: 16 }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 12 }} className="sms-tpl-grid">

            {/* New template editor card */}
            {editingId === 'new' && (
              <SmsTemplateCard
                tpl={null}
                isEditing={true}
                editDraft={editDraft}
                setEditDraft={setEditDraft}
                onSave={handleSaveTemplate}
                onCancelEdit={handleCancelEdit}
                onUse={null}
                onEdit={null}
                onDelete={null}
              />
            )}

            {templates.map(function(tpl) {
              return (
                <SmsTemplateCard
                  key={tpl.id}
                  tpl={tpl}
                  isEditing={editingId === tpl.id}
                  editDraft={editDraft}
                  setEditDraft={setEditDraft}
                  onUse={handleUseTemplate}
                  onEdit={handleEditTemplate}
                  onSave={handleSaveTemplate}
                  onDelete={handleDeleteTemplate}
                  onCancelEdit={handleCancelEdit}
                />
              );
            })}

            {templates.length === 0 && editingId !== 'new' && (
              <div style={{ gridColumn: '1/-1', padding: '24px', textAlign: 'center', color: 'var(--grey-400)', fontSize: 13 }}>
                No templates yet. Click <strong>+ New Template</strong> to create one.
              </div>
            )}
          </div>
        </div>
      </div>

      {/* ── Compose + History grid ── */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20, alignItems: 'start' }} className="sms-main-grid">

        {/* Compose */}
        <div id="sms-compose-panel" style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 10, overflow: 'hidden' }}>
          <div style={{ background: 'var(--ink)', color: '#fff', padding: '14px 18px', fontSize: 13.5, fontWeight: 700 }}>
            📤 Compose SMS
          </div>
          <div style={{ padding: 18 }}>

            {/* Sender ID */}
            <div style={{ marginBottom: 14 }}>
              <label style={{ display: 'block', fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 6 }}>Sender ID</label>
              {senders.length > 0 ? (
                <select value={senderId} onChange={function(e) { setSenderId(e.target.value); }}
                  style={{ width: '100%', padding: '9px 10px', border: '1px solid var(--grey-200)', borderRadius: 6, fontSize: 13, fontWeight: 600, color: 'var(--ink)', background: '#fff', outline: 'none', boxSizing: 'border-box' }}>
                  {senders.map(function(s) { var v = s.name || String(s.id || ''); return <option key={v} value={v}>{v}</option>; })}
                </select>
              ) : (
                <input value={senderId} onChange={function(e) { setSenderId(e.target.value); }}
                  placeholder="e.g. SunFront"
                  style={{ width: '100%', boxSizing: 'border-box', padding: '9px 10px', border: '1px solid var(--grey-200)', borderRadius: 6, fontSize: 13, color: 'var(--ink)', outline: 'none' }} />
              )}
            </div>

            {/* Recipients */}
            <div style={{ marginBottom: 14 }}>
              <label style={{ display: 'block', fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 8 }}>Recipients</label>
              <div style={{ display: 'flex', gap: 5, marginBottom: 10, flexWrap: 'wrap' }}>
                {[['manual','✏️ Manual'], ['all','👥 All Predictors'], ['outlet','🏪 By Outlet'], ['excel','📊 Excel Upload']].map(function(pair) {
                  var k = pair[0], l = pair[1];
                  return (
                    <button key={k} onClick={function() { setRecipientMode(k); }}
                      style={{ background: recipientMode === k ? 'var(--ink)' : '#fff', color: recipientMode === k ? '#fff' : 'var(--grey-600)', border: '1.5px solid ' + (recipientMode === k ? 'var(--ink)' : 'var(--grey-200)'), borderRadius: 5, padding: '5px 11px', fontSize: 11.5, fontWeight: 700, cursor: 'pointer' }}>
                      {l}
                    </button>
                  );
                })}
              </div>
              {recipientMode === 'manual' && (
                <textarea value={manualNumbers} onChange={function(e) { setManualNumbers(e.target.value); }}
                  placeholder={'9609999999, 9608888888\nOne per line or comma-separated'}
                  rows={3}
                  style={{ width: '100%', boxSizing: 'border-box', padding: '9px 10px', border: '1px solid var(--grey-200)', borderRadius: 6, fontSize: 12.5, color: 'var(--ink)', outline: 'none', resize: 'vertical', fontFamily: 'monospace' }} />
              )}
              {recipientMode === 'outlet' && (
                <select value={selectedOutlet} onChange={function(e) { setSelectedOutlet(e.target.value); }}
                  style={{ width: '100%', padding: '9px 10px', border: '1px solid var(--grey-200)', borderRadius: 6, fontSize: 13, fontWeight: 600, color: 'var(--ink)', background: '#fff', outline: 'none', boxSizing: 'border-box' }}>
                  <option value="">— pick an outlet —</option>
                  {outlets.map(function(o) { return <option key={o} value={o}>{o}</option>; })}
                </select>
              )}
              {recipientMode === 'all' && (
                <div style={{ fontSize: 12, color: 'var(--grey-500)', padding: '6px 0' }}>All predictors with a phone number on file.</div>
              )}

              {recipientMode === 'excel' && (
                <div>
                  <input id="sms-excel-input" type="file" accept=".xlsx,.xls,.csv" style={{ display: 'none' }}
                    onChange={function(e) { var f = e.target.files[0]; if (f) handleExcelFile(f); e.target.value = ''; }} />

                  {!excelFileName && !excelParsing && (
                    <div
                      onClick={function() { document.getElementById('sms-excel-input').click(); }}
                      onDragOver={function(e) { e.preventDefault(); e.currentTarget.style.borderColor = 'var(--orange)'; }}
                      onDragLeave={function(e) { e.currentTarget.style.borderColor = 'var(--grey-300)'; }}
                      onDrop={function(e) { e.preventDefault(); e.currentTarget.style.borderColor = 'var(--grey-300)'; var f = e.dataTransfer.files[0]; if (f) handleExcelFile(f); }}
                      style={{ border: '2px dashed var(--grey-300)', borderRadius: 7, padding: '22px 16px', textAlign: 'center', cursor: 'pointer', background: 'var(--grey-50)', transition: 'border-color 0.15s' }}>
                      <div style={{ fontSize: 26, marginBottom: 6 }}>📊</div>
                      <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--grey-600)', marginBottom: 4 }}>Click to upload or drag &amp; drop</div>
                      <div style={{ fontSize: 11, color: 'var(--grey-400)' }}>Supports .xlsx · .xls · .csv</div>
                      <div style={{ fontSize: 11, color: 'var(--grey-400)', marginTop: 3 }}>Column with mobile numbers will be auto-detected</div>
                    </div>
                  )}

                  {excelParsing && (
                    <div style={{ padding: '14px 0', textAlign: 'center', fontSize: 13, color: 'var(--grey-500)' }}>
                      Parsing file…
                    </div>
                  )}

                  {excelError && (
                    <div style={{ padding: '9px 12px', background: '#fee2e2', borderRadius: 5, fontSize: 12.5, color: '#991b1b', fontWeight: 600 }}>
                      ❌ {excelError}
                    </div>
                  )}

                  {excelStats && !excelParsing && (
                    <div style={{ background: '#f0fdf4', border: '1px solid #86efac', borderRadius: 6, padding: '10px 14px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10 }}>
                      <div>
                        <div style={{ fontSize: 13, fontWeight: 800, color: '#166534' }}>
                          ✅ {excelStats.valid} valid number{excelStats.valid !== 1 ? 's' : ''} loaded
                        </div>
                        <div style={{ fontSize: 11, color: '#15803d', marginTop: 3 }}>
                          {excelFileName}
                          {excelStats.invalid > 0 ? ' · ' + excelStats.invalid + ' invalid / non-Maldivian skipped' : ' · all valid'}
                        </div>
                      </div>
                      <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
                        <button onClick={function() { document.getElementById('sms-excel-input').click(); }}
                          style={{ background: 'none', border: '1px solid #86efac', borderRadius: 4, padding: '4px 10px', fontSize: 11, fontWeight: 700, color: '#166534', cursor: 'pointer' }}>
                          Replace
                        </button>
                        <button onClick={clearExcel}
                          style={{ background: 'none', border: '1px solid #fca5a5', borderRadius: 4, padding: '4px 10px', fontSize: 11, fontWeight: 700, color: '#ef4444', cursor: 'pointer' }}>
                          Clear
                        </button>
                      </div>
                    </div>
                  )}
                </div>
              )}
              {recipientPhones.length > 0 && (
                <div style={{ marginTop: 6, fontSize: 12, color: '#2563eb', fontWeight: 700 }}>
                  {recipientPhones.length} recipient{recipientPhones.length !== 1 ? 's' : ''} selected
                </div>
              )}
            </div>

            {/* Message body */}
            <div style={{ marginBottom: 14 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
                <label style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)' }}>Message</label>
                <CharBadge text={body} />
              </div>
              <textarea value={body} onChange={function(e) { setBody(e.target.value); }}
                rows={5}
                placeholder="Type your message or use a template above…"
                style={{ width: '100%', boxSizing: 'border-box', padding: '10px 12px', border: '1px solid var(--grey-200)', borderRadius: 6, fontSize: 13, color: 'var(--ink)', outline: 'none', resize: 'vertical', lineHeight: 1.55 }} />
            </div>

            {sendResult && (
              <div style={{ padding: '10px 14px', borderRadius: 6, marginBottom: 12, fontSize: 13, fontWeight: 600, background: sendResult.ok ? '#dcfce7' : '#fee2e2', color: sendResult.ok ? '#166534' : '#991b1b' }}>
                {sendResult.ok ? '✅ ' : '❌ '}{sendResult.message}
              </div>
            )}

            <button onClick={handleSend} disabled={sendDisabled}
              style={{ width: '100%', padding: '12px 0', borderRadius: 7, border: 'none', background: sendDisabled ? 'var(--grey-200)' : 'var(--orange)', color: sendDisabled ? 'var(--grey-400)' : '#fff', fontSize: 13, fontWeight: 800, letterSpacing: '0.07em', textTransform: 'uppercase', cursor: sendDisabled ? 'not-allowed' : 'pointer', transition: 'background 0.14s' }}>
              {sending ? 'Sending…' : recipientPhones.length > 0 ? 'Send to ' + recipientPhones.length + ' recipient' + (recipientPhones.length !== 1 ? 's' : '') : 'Send SMS'}
            </button>
          </div>
        </div>

        {/* History */}
        <div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
            <div style={{ fontSize: 13.5, fontWeight: 700, color: 'var(--ink)' }}>📨 Recent Messages</div>
            <button onClick={loadData} style={{ background: 'none', border: '1px solid var(--grey-200)', borderRadius: 5, padding: '5px 12px', fontSize: 11.5, fontWeight: 600, color: 'var(--grey-600)', cursor: 'pointer' }}>
              {loading ? '…' : '↻ Refresh'}
            </button>
          </div>
          {loading && (
            <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 8, padding: 24, textAlign: 'center', color: 'var(--grey-400)', fontSize: 13 }}>Loading…</div>
          )}
          {!loading && messages.length === 0 && (
            <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 8, padding: '32px 24px', textAlign: 'center' }}>
              <div style={{ fontSize: 28, marginBottom: 8 }}>📭</div>
              <div style={{ fontSize: 13, color: 'var(--grey-500)', fontWeight: 600 }}>No messages yet</div>
            </div>
          )}
          {!loading && messages.length > 0 && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, maxHeight: 560, overflowY: 'auto' }}>
              {messages.slice(0, 30).map(function(m) {
                var dateStr = new Date(m.created_at).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: true });
                return (
                  <div key={m.id} style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 8, padding: '12px 14px' }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 5 }}>
                      <span style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--ink)' }}>{m.sms_header || '—'}</span>
                      <SmsStatusDot status={m.status} />
                    </div>
                    {m.body && (
                      <div style={{ fontSize: 12.5, color: 'var(--grey-600)', marginBottom: 6, lineHeight: 1.45 }}>
                        {m.body.length > 100 ? m.body.slice(0, 100) + '…' : m.body}
                      </div>
                    )}
                    <div style={{ fontSize: 11, color: 'var(--grey-400)', display: 'flex', gap: 10 }}>
                      <span>{dateStr}</span>
                      <span>ID #{m.id}</span>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>

      </div>

      <style>{`
        @media (max-width: 820px) {
          .sms-stats-grid { grid-template-columns: repeat(2, 1fr) !important; }
          .sms-main-grid  { grid-template-columns: 1fr !important; }
          .sms-tpl-grid   { grid-template-columns: 1fr !important; }
        }
        @media (max-width: 480px) {
          .sms-stats-grid { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { AdminSMS });
