/* Marketing — push a message to the lock screen of everyone holding one of your passes.
   This used to live at the bottom of the Analytics screen, reachable only after picking a pass
   and scrolling past the KPIs, chart, funnel and member table. Sending a message is a marketing
   job, not a reporting one, so it now sits on the Hub under "Marketing" and carries its own pass
   picker (Analytics had one for its own reasons; this panel no longer inherits it).

   Backend: POST /api/wallet/push (spoonity-passkit-integration) — 10 sends/hour, delivers to both
   Apple and Google holders and reports each platform's delivered/attempted separately. */
const BC_I18N = window.SpoonityI18n;

const BC_ENDPOINT = () => (window.SpoonityAuth && window.SpoonityAuth.getEndpoint
  ? window.SpoonityAuth.getEndpoint()
  : 'https://wallet-api.spoonity.com');

async function broadcastPost(path, body) {
  const r = await fetch(`${BC_ENDPOINT()}${path}`, {
    method: 'POST', credentials: 'include',
    headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),
  });
  const json = await r.json().catch(() => ({}));
  if (!r.ok) throw new Error(json.error || `Request failed (${r.status})`);
  return json;
}

/* BROADCAST-PICK-BEGIN — plain JS (no JSX) so test/broadcast-pick.test.js can slice it out and
   evaluate it directly, the same trick the field-grid tests use on the builder forms. */
// Which pass the composer is aimed at, given the published list and whatever was selected before.
// An empty list means nothing is selectable at all; a selection that has since disappeared (the
// pass was archived from the grid below while this panel sat open) falls back to the first pass
// rather than leaving the composer pointed at a program that is gone.
function resolveBroadcastTarget(programs, current) {
  const list = programs || [];
  if (!list.length) return { programId: '', selected: null, posterOnly: false };
  const selected = list.find((p) => String(p.programId) === String(current)) || list[0];
  return { programId: String(selected.programId), selected, posterOnly: selected.cardLayout === 'poster' };
}
/* BROADCAST-PICK-END */

/* Collapsible broadcast panel — starts closed so it doesn't compete with the rest of the Hub for
   attention on every visit; "Compose"/"Close" toggle plus a chevron make the state legible.

   `programs` is [{ programId, name, cardLayout }] — published, non-archived passes only. An empty
   list is a real state (a vendor who has designed nothing yet), so the panel says so rather than
   offering a composer that could not send anywhere. */
function BroadcastPanel({ programs, accent }) {
  const [open, setOpen] = React.useState(false);
  const [programId, setProgramId] = React.useState('');
  const [header, setHeader] = React.useState('');
  const [body, setBody] = React.useState('');
  const [status, setStatus] = React.useState('idle'); // idle | sending | sent | error
  const [error, setError] = React.useState('');
  const [outcome, setOutcome] = React.useState(null);

  const list = programs || [];
  // Render from the resolved target, not from raw state: the list arrives async, so on the first
  // paint state is still '' while the target is already the first pass. Writing it back keeps
  // them in step for later renders without ever letting the two disagree on screen.
  const target = resolveBroadcastTarget(list, programId);
  React.useEffect(() => {
    if (target.programId !== programId) setProgramId(target.programId);
  }, [target.programId, programId]);
  const posterOnly = target.posterOnly;

  const send = async () => {
    if (!body.trim() || !target.programId || status === 'sending') return;
    setStatus('sending'); setError('');
    try {
      const data = await broadcastPost('/api/wallet/push', { programId: target.programId, header: header.trim() || undefined, body: body.trim() });
      setOutcome(data);
      setStatus('sent');
      setBody('');
    } catch (e) {
      setError(e.message || BC_I18N.T('bc_sendFailed')); setStatus('error');
    }
  };

  // Switching pass invalidates the "sent to 412 members" line above the composer — it reported a
  // send to a different audience.
  const pickProgram = (id) => {
    setProgramId(id);
    if (status === 'sent' || status === 'error') { setStatus('idle'); setOutcome(null); setError(''); }
  };

  const textarea = { width: '100%', padding: '10px 12px', borderRadius: 10, border: '1px solid var(--border-primary)', background: 'var(--surface-secondary, #f8f6f4)', color: 'var(--typography-primary)', fontFamily: 'var(--font-sans)', fontSize: 13, resize: 'vertical', boxSizing: 'border-box' };
  const sendable = body.trim().length > 0 && !!target.programId;

  return (
    <div style={{ background: 'var(--surface-base)', borderRadius: 14, border: '1px solid var(--border-primary)' }}>
      <button type="button" onClick={() => setOpen((o) => !o)}
        style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, padding: '16px 18px', background: 'transparent', border: 'none', cursor: 'pointer', textAlign: 'left', fontFamily: 'var(--font-sans)' }}>
        <span style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          <span style={{ fontSize: 15, fontWeight: 700, color: 'var(--typography-primary)' }}>{BC_I18N.T('bc_sendMessage')}</span>
          <span style={{ fontSize: 11.5, color: 'var(--typography-tertiary)' }}>{BC_I18N.T('bc_pushHint')}</span>
        </span>
        <span style={{ display: 'flex', alignItems: 'center', gap: 10, flexShrink: 0 }}>
          <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--typography-secondary)' }}>{open ? BC_I18N.T('bc_close') : BC_I18N.T('bc_compose')}</span>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--typography-tertiary)" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"
            style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .18s ease' }}><path d="M6 9l6 6 6-6" /></svg>
        </span>
      </button>
      {open && (
        <div style={{ borderTop: '1px solid var(--border-primary)', padding: 18, display: 'flex', flexDirection: 'column', gap: 10, maxWidth: 560 }}>
          {list.length === 0 ? (
            <div style={{ fontSize: 12.5, color: 'var(--typography-tertiary)', lineHeight: 1.5 }}>
              {BC_I18N.T('bc_noPublishedPasses')}
            </div>
          ) : (
            <React.Fragment>
              <label style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
                <span style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--typography-secondary)' }}>{BC_I18N.T('bc_selectPass')}</span>
                <select value={target.programId} onChange={(e) => pickProgram(e.target.value)} disabled={status === 'sending'}
                  style={{ padding: '9px 11px', borderRadius: 9, border: '1px solid var(--border-primary)', background: 'var(--surface-base)', fontFamily: 'var(--font-sans)', fontSize: 13, color: 'var(--typography-primary)', cursor: 'pointer' }}>
                  {list.map((p) => <option key={p.programId} value={p.programId}>{p.name}</option>)}
                </select>
              </label>
              {posterOnly && (
                <div style={{ display: 'flex', gap: 8, alignItems: 'flex-start', padding: '8px 10px', borderRadius: 9, background: 'var(--surface-secondary)', border: '1px solid var(--border-primary)' }}>
                  <span style={{ color: 'var(--warning, #cc6716)', fontWeight: 700, fontSize: 13, lineHeight: '16px' }}>!</span>
                  <span style={{ fontSize: 11, color: 'var(--typography-secondary)', lineHeight: 1.45 }}>
                    {BC_I18N.T('bc_posterOnlyWarning')}
                  </span>
                </div>
              )}
              <input type="text" value={header} onChange={(e) => setHeader(e.target.value)} placeholder={BC_I18N.T('bc_headerPlaceholder')} maxLength={100}
                disabled={status === 'sending'} style={{ ...textarea, resize: 'none' }} />
              <textarea value={body} onChange={(e) => setBody(e.target.value)} placeholder={BC_I18N.T('bc_bodyPlaceholderExample')} maxLength={190} rows={2}
                disabled={status === 'sending'} style={textarea} />
              {error && <div style={{ color: 'var(--critical,#c3223f)', fontSize: 12 }}>{error}</div>}
              {status === 'sent' && outcome && (
                <div style={{ fontSize: 12, color: 'var(--success,#3f7d58)' }}>
                  {BC_I18N.T('bc_sentSummary', { aDelivered: outcome.apple.delivered, aAttempted: outcome.apple.attempted, gDelivered: outcome.google.delivered, gAttempted: outcome.google.attempted })}
                </div>
              )}
              <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                <button type="button" onClick={send} disabled={!sendable || status === 'sending'}
                  style={{ padding: '9px 18px', borderRadius: 9, border: 'none', background: sendable ? accent : 'var(--surface-secondary, #e7e2db)', color: sendable ? '#fff' : 'var(--typography-tertiary)',
                           fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600, cursor: sendable && status !== 'sending' ? 'pointer' : 'default' }}>
                  {status === 'sending' ? BC_I18N.T('bc_sending') : BC_I18N.T('bc_sendToMembers')}
                </button>
                <span style={{ fontSize: 11.5, color: 'var(--typography-tertiary)' }}>{BC_I18N.T('bc_charsLeft', { n: 190 - body.length })}</span>
              </div>
            </React.Fragment>
          )}
        </div>
      )}
    </div>
  );
}

window.SpoonityBroadcast = { Panel: BroadcastPanel };
