/* =========================================================
   Tappt — Tips (LinkMe-style "collect tips")
   - TipConfigSheet: icon, display type, colour, amounts, copy
   - TipSheet: visitor picks an amount + sends
   - TipButton: profile entry point (button / link / pill / corner icon)
   Loaded after app-dash.jsx.
   ========================================================= */
const { useState: tipUse } = React;

const TIP_ICONS = ['heart', 'coffee', 'dollarsign', 'gift', 'star', 'flame', 'music', 'trophy', 'ticket', 'spark'];
const TIP_COLORS = ['#E8FF59', '#FF6BC8', '#6B8299', '#5CC8FF', '#FF8A3D', '#2ED573', '#FFD93D', '#FF5A7A'];
const TIP_DEFAULT = { headline: 'Buy me a coffee', subtext: 'If my work helps you, a tip keeps it coming.', amounts: [3, 5, 10], icon: 'coffee', display: 'button', color: '#E8FF59', cta: 'Send a tip' };
function tipConf(u) {
  return {
    headline: u.tipHeadline || TIP_DEFAULT.headline,
    subtext: u.tipSubtext || TIP_DEFAULT.subtext,
    amounts: (u.tipAmounts && u.tipAmounts.length) ? u.tipAmounts : TIP_DEFAULT.amounts,
    icon: u.tipIcon || TIP_DEFAULT.icon,
    display: u.tipDisplay || TIP_DEFAULT.display,
    color: u.tipColor || TIP_DEFAULT.color,
  };
}
window.tipConf = tipConf;
/* readable ink on a coloured fill */
function tipInk(hex) {
  const h = (hex || '#E8FF59').replace('#', '');
  const r = parseInt(h.slice(0, 2), 16), g = parseInt(h.slice(2, 4), 16), b = parseInt(h.slice(4, 6), 16);
  return (r * 299 + g * 587 + b * 114) / 1000 > 150 ? '#0B0B0C' : '#fff';
}
window.tipInk = tipInk;

/* ---- creator config ---- */
function TipConfigSheet({ draft, onChange, onClose }) {
  const MI2 = window.I;
  const t = tipConf({ tipHeadline: draft.tipHeadline, tipSubtext: draft.tipSubtext, tipAmounts: draft.tipAmounts, tipIcon: draft.tipIcon, tipDisplay: draft.tipDisplay, tipColor: draft.tipColor });
  const ink = tipInk(t.color);
  const setAmt = (i, v) => { const a = t.amounts.slice(); a[i] = Math.max(1, parseInt(v.replace(/[^0-9]/g, '') || '0', 10)); onChange({ tipAmounts: a }); };
  const addAmt = () => { if (t.amounts.length >= 4) return; onChange({ tipAmounts: t.amounts.concat([Math.max(...t.amounts) + 5]) }); };
  const rmAmt = (i) => { if (t.amounts.length <= 2) return; onChange({ tipAmounts: t.amounts.filter((_, j) => j !== i) }); };
  const ic = (id, sz) => (MI2[id] ? MI2[id]({ width: sz, height: sz }) : null);

  return (
    <div className="sheet-bg" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="sheet">
        <div className="sheet-grab" />
        <div className="sheet-head"><span style={{ width: 56 }} /><h3>Tips</h3><button className="glass-pill" style={{ background: 'var(--accent)', color: 'var(--accent-ink)', border: 'none' }} onClick={onClose}>Done</button></div>
        <div className="sheet-scroll">
          {/* live preview */}
          <div className="tip-cfg-preview">
            {t.display === 'corner'
              ? <span className="tip-prev-corner" style={{ background: t.color, color: ink }}>{ic(t.icon, 20)}</span>
              : t.display === 'link'
              ? <span className="tip-prev-link"><span className="tpl-ic" style={{ background: t.color, color: ink }}>{ic(t.icon, 17)}</span><span>{t.headline}</span>{MI2.arrow ? MI2.arrow({ width: 15, height: 15 }) : '→'}</span>
              : t.display === 'pill'
              ? <span className="tip-prev-pill" style={{ background: t.color, color: ink }}>{ic(t.icon, 16)} {t.headline}</span>
              : <span className="tip-prev-btn" style={{ background: t.color, color: ink }}>{ic(t.icon, 18)} {t.headline}</span>}
          </div>

          {/* display type */}
          <div className="ex-grouplabel">Display</div>
          <div className="tip-disp-grid">
            {[['button', 'Button'], ['pill', 'Pill'], ['link', 'Link row'], ['corner', 'Corner icon']].map(([id, lb]) => (
              <button key={id} className={'tip-disp' + (t.display === id ? ' sel' : '')} onClick={() => onChange({ tipDisplay: id })}>
                <span className={'tip-disp-prev tdp-' + id}><span className="tdp-dot" /></span>
                <span className="tip-disp-lb">{lb}</span>
              </button>
            ))}
          </div>

          {/* icon */}
          <div className="ex-grouplabel">Icon</div>
          <div className="tip-icon-row">{TIP_ICONS.map((id) => <button key={id} className={'tip-icon' + (t.icon === id ? ' on' : '')} onClick={() => onChange({ tipIcon: id })}>{ic(id, 21)}</button>)}</div>

          {/* colour */}
          <div className="ex-grouplabel">Colour</div>
          <div className="tip-color-row">{TIP_COLORS.map((c) => <button key={c} className={'tip-color' + (t.color === c ? ' on' : '')} style={{ background: c }} onClick={() => onChange({ tipColor: c })}>{t.color === c ? (MI2.check ? MI2.check({ width: 14, height: 14 }) : '✓') : ''}</button>)}</div>

          <div className="field" style={{ marginTop: 18 }}><label>Headline</label><input className="input" value={t.headline} onChange={(e) => onChange({ tipHeadline: e.target.value })} placeholder="Buy me a coffee" /></div>
          <div className="field"><label>Subtext</label><input className="input" value={t.subtext} onChange={(e) => onChange({ tipSubtext: e.target.value })} placeholder="If my work helps you…" /></div>
          <div className="ex-grouplabel">Preset amounts (£)</div>
          <div className="tip-amts">
            {t.amounts.map((a, i) => (
              <div className="tip-amt-edit" key={i}>
                <span className="tip-amt-cur">£</span>
                <input className="tip-amt-in" inputMode="numeric" value={a} onChange={(e) => setAmt(i, e.target.value)} />
                {t.amounts.length > 2 && <button className="tip-amt-x" onClick={() => rmAmt(i)}>{MI2.close ? MI2.close({ width: 12, height: 12 }) : '✕'}</button>}
              </div>
            ))}
            {t.amounts.length < 4 && <button className="tip-amt-add" onClick={addAmt}>{MI2.plus ? MI2.plus({ width: 16, height: 16 }) : '+'}</button>}
          </div>
          <div className="ex-hint" style={{ marginTop: 10 }}>Tips settle to the same Stripe payouts as sales. Platform fee applies (Pro 4% / free 10%).</div>
          <div style={{ height: 18 }} />
        </div>
      </div>
    </div>
  );
}
window.TipConfigSheet = TipConfigSheet;

/* ---- profile entry point ---- */
function TipButton({ user, onOpen }) {
  const t = tipConf(user);
  const MI2 = window.MI;
  const ink = tipInk(t.color);
  const ic = (sz) => (MI2[t.icon] ? MI2[t.icon]({ width: sz, height: sz }) : (MI2.heart ? MI2.heart({ width: sz, height: sz }) : '♥'));
  if (t.display === 'corner') {
    return <button className="tip-corner" style={{ background: t.color, color: ink }} onClick={onOpen} aria-label="Send a tip">{ic(20)}</button>;
  }
  if (t.display === 'link') {
    return <div className="pf-section"><button className="tip-link-row" onClick={onOpen}><span className="tlr-ic" style={{ background: t.color, color: ink }}>{ic(18)}</span><span className="tlr-t">{t.headline}</span>{MI2.arrow ? MI2.arrow({ width: 16, height: 16 }) : '→'}</button></div>;
  }
  if (t.display === 'pill') {
    return <div className="pf-section" style={{ textAlign: 'center' }}><button className="tip-pill" style={{ background: t.color, color: ink }} onClick={onOpen}>{ic(16)} {t.headline}</button></div>;
  }
  return <div className="pf-section"><button className="tip-btn-full" style={{ background: t.color, color: ink }} onClick={onOpen}>{ic(18)} {t.headline}</button></div>;
}
window.TipButton = TipButton;

/* ---- visitor tip flow ---- */
function TipSheet({ user, onClose, onTip }) {
  const t = tipConf(user);
  const MI2 = window.MI;
  const ink = tipInk(t.color);
  const [amt, setAmt] = tipUse(t.amounts[1] || t.amounts[0]);
  const [custom, setCustom] = tipUse('');
  const [note, setNote] = tipUse('');
  const [done, setDone] = tipUse(false);
  const first = (user.name || 'them').split(' ')[0];
  const finalAmt = custom ? parseInt(custom, 10) : amt;
  const ic = (sz) => (MI2[t.icon] ? MI2[t.icon]({ width: sz, height: sz }) : (MI2.heart ? MI2.heart({ width: sz, height: sz }) : '♥'));
  const send = async () => {
    if (!finalAmt || finalAmt < 1) return;
    // try a REAL Stripe Connect checkout when the creator can take tips; the webhook
    // records the tip server-side on success. Falls back to recorded-only otherwise.
    try {
      if (window.TapptDB && window.TapptDB.available() && window.TapptDB.startTipCheckout && user.handle) {
        const r = await window.TapptDB.startTipCheckout({ handle: user.handle, amount: finalAmt, note: note.trim() });
        if (r && r.url) { location.href = r.url; return; }
      }
    } catch (e) {}
    // fallback: record the tip locally / to the owner's table (no live charge configured yet)
    onTip && onTip({ amount: finalAmt, note: note.trim(), ts: Date.now() });
    setDone(true);
  };
  return (
    <div className="sheet-bg exchange-bg" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="exchange-sheet">
        {done ? (
          <div className="ex-done">
            <div className="ex-done-check" style={{ background: t.color, color: ink }}>{ic(28)}</div>
            <h2>£{finalAmt} sent to {first}</h2>
            <p>Thank you — {first} just got your tip{note ? ' and your note' : ''}. You're a legend.</p>
            <button className="ex-submit" style={{ background: t.color, color: ink }} onClick={onClose}>Done</button>
          </div>
        ) : (
          <React.Fragment>
            <div className="ex-form-head">
              <div className="tip-big-ic" style={{ background: t.color, color: ink }}>{ic(30)}</div>
              <h2 className="ex-h">{t.headline}</h2>
              <p className="ex-sub">{t.subtext}</p>
            </div>
            <div className="ex-form-body">
              <div className="tip-grid">
                {t.amounts.map((a) => <button key={a} className={'tip-opt' + (!custom && amt === a ? ' on' : '')} style={!custom && amt === a ? { borderColor: t.color, background: 'color-mix(in srgb, ' + t.color + ' 14%, var(--bg-2))' } : null} onClick={() => { setAmt(a); setCustom(''); }}>£{a}</button>)}
              </div>
              <div className="tip-custom">
                <span>£</span>
                <input className="tip-custom-in" inputMode="numeric" placeholder="Other amount" value={custom} onChange={(e) => setCustom(e.target.value.replace(/[^0-9]/g, ''))} />
              </div>
              <textarea className="ex-input" rows={2} placeholder={'Say something nice to ' + first + ' (optional)'} value={note} onChange={(e) => setNote(e.target.value)} />
              <button className={'ex-submit' + (finalAmt >= 1 ? '' : ' off')} style={{ background: t.color, color: ink }} onClick={send}>{ic(17)} Send £{finalAmt || 0}</button>
              <div className="ex-legal">{MI2.lock ? MI2.lock({ width: 12, height: 12 }) : ''} Secured by Stripe · tips are non-refundable</div>
              <button className="ex-notnow" onClick={onClose}>Maybe later</button>
            </div>
          </React.Fragment>
        )}
      </div>
    </div>
  );
}
window.TipSheet = TipSheet;

/* shared moment composer — used on the profile + as a FAB sheet on Moments */
function MomentComposer({ user, onPost, toast, autoFocus }) {
  const [text, setText] = tipUse('');
  const [img, setImg] = tipUse(null);
  const [imgKind, setImgKind] = tipUse('image');
  const fileRef = React.useRef(null);
  const camRef = React.useRef(null);
  const MI2 = window.MI;
  const pickMedia = (e) => {
    const f = e.target.files && e.target.files[0]; if (!f) return;
    const kind = f.type.startsWith('video') ? 'video' : 'image';
    if (window.readMedia) window.readMedia(f, (src, k) => { setImg(src); setImgKind(k); });
    else { const r = new FileReader(); r.onload = () => { setImg(r.result); setImgKind(kind); }; r.readAsDataURL(f); }
    e.target.value = '';
  };
  const post = () => {
    if (!text.trim() && !img) return;
    onPost && onPost({ id: (window.newMomentId ? window.newMomentId() : 'm' + Date.now()), cap: text.trim(), img: img, imgKind: imgKind, ts: Date.now(), taps: 0 });
    setText(''); setImg(null); setImgKind('image');
    toast && toast('Moment posted');
  };
  return (
    <div className="mc-card">
      <div className="mc-top">
        <window.Avatar user={user} size={46} coverFallback />
        <textarea className="mc-input" rows={1} autoFocus={autoFocus} value={text} placeholder="What's happening?" onChange={(e) => { setText(e.target.value); e.target.style.height = 'auto'; e.target.style.height = e.target.scrollHeight + 'px'; }} />
        <button className={'mc-post' + (text.trim() || img ? ' ready' : '')} onClick={post} aria-label="Post moment">{MI2.plus({ width: 26, height: 26 })}</button>
      </div>
      {img && (
        <div className="mc-preview">
          {imgKind === 'video' ? <video ref={window.playMuted} src={img} muted autoPlay loop playsInline /> : <img src={img} alt="" />}
          <button className="mc-preview-x" onClick={() => setImg(null)}>{MI2.close ? MI2.close({ width: 14, height: 14 }) : '✕'}</button>
        </div>
      )}
      <div className="mc-foot">
        <span className="mc-keep">{MI2.clock ? MI2.clock({ width: 16, height: 16 }) : ''} Moments are kept forever</span>
        <div className="mc-tools">
          <button onClick={() => camRef.current && camRef.current.click()} aria-label="Camera">{MI2.camera({ width: 20, height: 20 })}</button>
          <button onClick={() => fileRef.current && fileRef.current.click()} aria-label="Photo">{MI2.image({ width: 20, height: 20 })}</button>
        </div>
      </div>
      <input ref={fileRef} type="file" accept="image/*,video/*" style={{ display: 'none' }} onChange={pickMedia} />
      <input ref={camRef} type="file" accept="image/*" capture="environment" style={{ display: 'none' }} onChange={pickMedia} />
    </div>
  );
}
window.MomentComposer = MomentComposer;
