// src/features/messages/ui/message-bubble.jsx
//
// One message: sender's bubble aligns right (with their own color), recipient's
// aligns left (neutral). Bubble shows the body + any inline AttachmentPreview
// children + small timestamp + read receipt for sender's own outbound message.
//
// Pinning UX:
//   - Desktop: hover the bubble row → small pin icon fades in (top corner).
//   - Mobile (touch): long-press the bubble (>=400ms) → action sheet with
//     Pin/Unpin appears.
//   The pin call goes through window.MessagePinController.toggle (set by
//   thread-view.jsx) so the thread can do optimistic UI + scroll preservation.

const MSG_fmtTime = (iso) => {
  const d = new Date(iso);
  const now = new Date();
  const same = d.getFullYear() === now.getFullYear()
            && d.getMonth()    === now.getMonth()
            && d.getDate()     === now.getDate();
  if (same) {
    return d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
  }
  return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
       + ' · ' + d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
};

const MB_PinIcon = ({ size = 14, filled = false }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" aria-hidden="true"
       style={{ display:'block' }}>
    <path
      d="M14 2l8 8-4 1-3 3 1 5-2 2-5-5-5 5-1-1 5-5-5-5 2-2 5 1 3-3 1-4z"
      fill={filled ? 'currentColor' : 'none'}
      stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
  </svg>
);

const MessageBubble = ({ message, isMine, anchorRef }) => {
  const m = message;
  const bg     = isMine ? 'oklch(22% 0.06 265)' : 'oklch(96% 0.005 60)';
  const fg     = isMine ? '#fff'                : 'oklch(22% 0.06 265)';
  const align  = isMine ? 'flex-end'            : 'flex-start';
  const border = isMine ? 'transparent'         : 'oklch(92% 0.01 265)';
  const radius = isMine ? '14px 14px 4px 14px'  : '14px 14px 14px 4px';

  const lines = (m.body || '').split('\n');
  const pinned = !!m.pinned_at;
  const [hover, setHover]   = React.useState(false);
  const [sheet, setSheet]   = React.useState(false);
  const [busy,  setBusy]    = React.useState(false);
  const pressTimer = React.useRef(null);

  const callPin = async (next) => {
    const ctl = window.MessagePinController;
    if (!ctl || !ctl.toggle) return;
    setBusy(true);
    try { await ctl.toggle(m.id, next); }
    catch (e) { alert(e.message || 'Could not change pin.'); }
    finally { setBusy(false); setSheet(false); }
  };

  const startPress = () => {
    if (pressTimer.current) clearTimeout(pressTimer.current);
    pressTimer.current = setTimeout(() => setSheet(true), 400);
  };
  const cancelPress = () => {
    if (pressTimer.current) { clearTimeout(pressTimer.current); pressTimer.current = null; }
  };

  return (
    <div ref={anchorRef}
         data-message-id={m.id}
         onMouseEnter={() => setHover(true)}
         onMouseLeave={() => setHover(false)}
         onTouchStart={startPress}
         onTouchEnd={cancelPress}
         onTouchMove={cancelPress}
         onTouchCancel={cancelPress}
         onContextMenu={(e) => { e.preventDefault(); setSheet(true); }}
         style={{ position:'relative', display:'flex', flexDirection:'column',
                  alignItems:align, marginBottom:10,
                  background: pinned ? 'oklch(98% 0.04 90)' : 'transparent',
                  borderRadius: pinned ? 8 : 0,
                  padding: pinned ? '6px 6px' : 0,
                  transition:'background 120ms' }}>
      {pinned && (
        <div style={{ alignSelf:align, fontSize:10, fontWeight:600,
                       color:'oklch(48% 0.12 80)', letterSpacing:'0.06em',
                       textTransform:'uppercase', padding:'0 4px 4px' }}>
          <MB_PinIcon size={10} filled /> <span style={{ marginLeft:4 }}>Pinned</span>
        </div>
      )}
      <div style={{ position:'relative', maxWidth:'78%' }}>
        <div style={{ background:bg, color:fg, padding:'10px 14px',
                      borderRadius:radius, border:`1px solid ${border}`,
                      fontSize:14, lineHeight:1.5, wordBreak:'break-word', whiteSpace:'pre-wrap',
                      fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
          {m.body && lines.map((ln, i) => (
            <React.Fragment key={i}>{ln}{i < lines.length - 1 && <br />}</React.Fragment>
          ))}
          {m.attachments && m.attachments.length > 0 && (
            <div style={{ display:'flex', flexDirection:'column', gap:4, marginTop: m.body ? 8 : 0 }}>
              {m.attachments.map(a => (
                <window.AttachmentPreview key={a.id} attachment={a} />
              ))}
            </div>
          )}
        </div>
        {/* Desktop hover pin icon */}
        <button type="button"
          onClick={(e) => { e.stopPropagation(); callPin(!pinned); }}
          disabled={busy}
          aria-label={pinned ? 'Unpin message' : 'Pin message'}
          title={pinned ? 'Unpin' : 'Pin'}
          style={{
            position:'absolute', top:-6,
            [isMine ? 'left' : 'right']: -8,
            width:26, height:26, borderRadius:'50%',
            border:'1px solid oklch(90% 0.01 265)', background:'#fff',
            color: pinned ? 'oklch(48% 0.15 80)' : 'oklch(40% 0.04 265)',
            cursor: busy ? 'wait' : 'pointer',
            display: (hover || pinned) ? 'flex' : 'none',
            alignItems:'center', justifyContent:'center',
            boxShadow:'0 1px 3px rgba(0,0,0,0.08)',
          }}>
          <MB_PinIcon size={13} filled={pinned} />
        </button>
      </div>
      <div style={{ fontSize:10, color:'oklch(58% 0.03 265)', marginTop:3, padding:'0 4px' }}>
        {MSG_fmtTime(m.created_at)}
        {isMine && m.read_at && <span style={{ marginLeft:8 }}>· read</span>}
      </div>

      {sheet && (
        <div onClick={() => setSheet(false)}
          style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.35)',
                   display:'flex', alignItems:'flex-end', justifyContent:'center',
                   zIndex:9999 }}>
          <div onClick={(e) => e.stopPropagation()}
            style={{ width:'100%', maxWidth:480, background:'#fff',
                     borderTopLeftRadius:14, borderTopRightRadius:14,
                     padding:'12px 0 24px', boxShadow:'0 -2px 16px rgba(0,0,0,0.18)',
                     fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
            <div style={{ width:38, height:4, background:'oklch(85% 0.01 265)',
                          borderRadius:2, margin:'0 auto 8px' }} />
            <button type="button" onClick={() => callPin(!pinned)} disabled={busy}
              style={{ width:'100%', padding:'14px 20px', textAlign:'left',
                       background:'none', border:'none', cursor:'pointer',
                       fontSize:15, color:'oklch(22% 0.06 265)',
                       display:'flex', alignItems:'center', gap:12,
                       fontFamily:'inherit' }}>
              <MB_PinIcon size={16} filled={pinned} />
              {pinned ? 'Unpin message' : 'Pin message'}
            </button>
            <button type="button" onClick={() => setSheet(false)}
              style={{ width:'100%', padding:'12px 20px', textAlign:'center',
                       background:'none', border:'none', borderTop:'1px solid oklch(94% 0.008 265)',
                       cursor:'pointer', fontSize:14, color:'oklch(50% 0.03 265)',
                       fontFamily:'inherit' }}>Cancel</button>
          </div>
        </div>
      )}
    </div>
  );
};

window.Messages.ui.MessageBubble = MessageBubble;
window.MessageBubble             = MessageBubble;
