/* Viamar — customer-facing in-app chat panel ("Message your agent")
 *
 * A branded, backend-wired chat drawer the customer apps open to talk to a
 * real Viamar agent. The ops console (separate surface) sends replies; this
 * panel sends the customer's messages and polls for the agent's answers.
 *
 * Published as window.ViamarChat = { open(opts), close() }. Self-mounting:
 * open() appends its own host div to document.body and ReactDOM-renders the
 * drawer into a dedicated root; close() unmounts. Mirrors the mount/unmount
 * pattern in app/sign-in-dialog.jsx so it works from every shell (desktop,
 * mobile) with no container div in the page.
 *
 * Layout: slide-up sheet on mobile (≤760px), right-side panel on desktop.
 * Entrance animation: transform translateY / translateX only (CLAUDE.md hard
 * rule — never opacity-from-0). Auto-scroll sets scrollTop = scrollHeight
 * (never scrollIntoView — another hard rule).
 *
 * Backend contract (live worker — do not change):
 *   Send  POST  ${VIAMAR_API_BASE}/app/chat/messages
 *         body  { session_token, body }
 *         -> { success, message_id, direction:'inbound', body, created_at }
 *   Load  GET   ${VIAMAR_API_BASE}/app/chat/messages?session_token=<t>&limit=50
 *         opt   &since=<ISO created_at>
 *         -> { success, messages:[{ id, created_at, direction, channel, body, author_name }] }
 *   direction:'inbound'  = the customer's own messages (right, navy)
 *   direction:'outbound' = the Viamar agent's replies   (left, paper)
 *
 * No-session case: if ViamarAPI.session() has no session_token, we don't try
 * to chat — we render a friendly "sign in or call us" panel instead.
 */
(function () {
  var chatHost = null;
  var chatRoot = null;
  var isOpen = false;

  var PHONE_DISPLAY = '1-800-277-7570';
  var PHONE_HREF = 'tel:+18002777570';
  var POLL_MS = 5000;

  function apiBase() {
    if (window.ViamarAPI && window.ViamarAPI.apiBase) {
      return (window.ViamarAPI.apiBase() || '').replace(/\/+$/, '');
    }
    return (window.VIAMAR_API_BASE || (window.localStorage && localStorage.getItem('viamar.api.base')) || '').replace(/\/+$/, '');
  }

  function sessionToken() {
    try {
      var s = window.ViamarAPI && window.ViamarAPI.session ? window.ViamarAPI.session() : null;
      return (s && s.session_token) || '';
    } catch (e) {
      return '';
    }
  }

  function ensureKeyframes() {
    if (document.getElementById('viamar-chat-panel-style')) return;
    var st = document.createElement('style');
    st.id = 'viamar-chat-panel-style';
    st.textContent =
      '@keyframes viamarChatSheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }\n' +
      '@keyframes viamarChatPanelIn { from { transform: translateX(100%); } to { transform: translateX(0); } }\n' +
      '.viamar-chat-sheet { animation: viamarChatSheetUp .34s cubic-bezier(.22,.61,.36,1) both; }\n' +
      '.viamar-chat-panel { animation: viamarChatPanelIn .34s cubic-bezier(.22,.61,.36,1) both; }\n';
    document.head.appendChild(st);
  }

  function ensureRoot() {
    if (!chatRoot) {
      chatHost = document.createElement('div');
      chatHost.id = 'viamar-chat-panel-host';
      document.body.appendChild(chatHost);
      chatRoot = ReactDOM.createRoot(chatHost);
    }
    return chatRoot;
  }

  function isMobile() {
    try { return window.matchMedia && window.matchMedia('(max-width: 760px)').matches; }
    catch (e) { return (window.innerWidth || 1024) <= 760; }
  }

  function fmtTime(iso) {
    if (!iso) return '';
    try {
      var d = new Date(iso);
      if (isNaN(d.getTime())) return '';
      return d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
    } catch (e) { return ''; }
  }

  // ── Message bubble ────────────────────────────────────────────────
  function MessageBubble(props) {
    var T = window.T || {};
    var FB = window.FB || "'Archivo', sans-serif";
    var FM = window.FM || "'Space Mono', monospace";
    var navy = T.navy || '#0A1B2E';
    var ink = T.ink || '#0A1B2E';
    var faint = T.faint || '#9AA7B4';
    var muted = T.muted || '#6B7B8B';
    var line2 = T.line2 || '#EEF1F4';

    var m = props.m || {};
    var mine = m.direction === 'inbound'; // customer's own message → right, navy
    var author = (!mine && m.author_name) ? m.author_name : '';
    var time = fmtTime(m.created_at);

    return React.createElement('div', {
      style: { display: 'flex', justifyContent: mine ? 'flex-end' : 'flex-start', marginBottom: 10 },
    }, React.createElement('div', { style: { maxWidth: '82%' } }, [
      author ? React.createElement('div', {
        key: 'author',
        style: { fontFamily: FM, fontSize: 9.5, color: faint, letterSpacing: 0.3, margin: '0 4px 3px', textTransform: 'uppercase' },
      }, author) : null,
      React.createElement('div', {
        key: 'body',
        style: {
          background: mine ? navy : '#fff',
          color: mine ? '#fff' : ink,
          borderRadius: mine ? '18px 18px 5px 18px' : '18px 18px 18px 5px',
          padding: '11px 14px', fontFamily: FB, fontSize: 14.5, lineHeight: 1.45,
          whiteSpace: 'pre-wrap', wordBreak: 'break-word',
          boxShadow: mine ? '0 4px 14px rgba(10,27,46,0.22)' : '0 1px 2px rgba(10,27,46,0.06)',
          border: mine ? 'none' : '1px solid ' + line2,
        },
      }, m.body || ''),
      time ? React.createElement('div', {
        key: 'time',
        style: { fontFamily: FM, fontSize: 9.5, color: faint, marginTop: 4, textAlign: mine ? 'right' : 'left', padding: '0 4px' },
      }, time) : null,
    ].filter(Boolean)));
  }

  // ── No-session panel ──────────────────────────────────────────────
  function NoSessionBody(props) {
    var T = window.T || {};
    var FD = window.FD || "'Archivo Expanded', Archivo, sans-serif";
    var FB = window.FB || "'Archivo', sans-serif";
    var ink = T.ink || '#0A1B2E';
    var navy = T.navy || '#0A1B2E';
    var red = T.red || '#DD1C24';
    var muted = T.muted || '#6B7B8B';

    function signIn() {
      if (window.ViamarSignInDialog && window.ViamarSignInDialog.open) {
        if (props.onClose) props.onClose();
        window.ViamarSignInDialog.open();
      } else {
        window.location.href = '/login/';
      }
    }

    return React.createElement('div', {
      style: { flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', textAlign: 'center', gap: 16, padding: '28px 26px 36px' },
    }, [
      React.createElement('div', {
        key: 'h',
        style: { fontFamily: FD, fontWeight: 900, fontSize: 20, color: ink, letterSpacing: '-.015em', lineHeight: 1.18 },
      }, 'Sign in to message your agent'),
      React.createElement('div', {
        key: 's',
        style: { fontFamily: FB, fontSize: 13.5, color: muted, lineHeight: 1.55, maxWidth: 320 },
      }, "Sign in with the email on your quote or shipment and your dedicated Viamar agent will pick up the thread — or call us, we're happy to help."),
      React.createElement('a', {
        key: 'call',
        href: PHONE_HREF,
        style: {
          width: '100%', maxWidth: 320, boxSizing: 'border-box', textAlign: 'center',
          background: red, color: '#fff', textDecoration: 'none',
          padding: '15px 22px', borderRadius: 12, fontFamily: FB, fontWeight: 800,
          fontSize: 14.5, letterSpacing: '.01em', marginTop: 4,
        },
      }, 'Call ' + PHONE_DISPLAY),
      React.createElement('button', {
        key: 'signin',
        onClick: signIn,
        style: {
          width: '100%', maxWidth: 320, boxSizing: 'border-box',
          background: '#fff', color: navy, border: '1.5px solid ' + (T.line || '#E5E8EC'),
          padding: '14px 22px', borderRadius: 12, fontFamily: FB, fontWeight: 800,
          fontSize: 14, cursor: 'pointer',
        },
      }, 'Sign in'),
    ]);
  }

  // ── Active chat body (has a session_token) ────────────────────────
  function ChatBody(props) {
    var T = window.T || {};
    var FB = window.FB || "'Archivo', sans-serif";
    var FM = window.FM || "'Space Mono', monospace";
    var ink = T.ink || '#0A1B2E';
    var navy = T.navy || '#0A1B2E';
    var red = T.red || '#DD1C24';
    var muted = T.muted || '#6B7B8B';
    var faint = T.faint || '#9AA7B4';
    var line = T.line || '#E5E8EC';
    var paper = T.paper || '#F4F5F7';

    var token = props.token;
    var base = props.base;

    var messagesState = React.useState([]);
    var messages = messagesState[0], setMessages = messagesState[1];
    var inputState = React.useState('');
    var input = inputState[0], setInput = inputState[1];
    var sendingState = React.useState(false);
    var sending = sendingState[0], setSending = sendingState[1];
    var loadedState = React.useState(false);
    var loaded = loadedState[0], setLoaded = loadedState[1];

    var scrollRef = React.useRef(null);
    var latestRef = React.useRef(null);   // newest server created_at seen
    var seenRef = React.useRef({});        // id -> true (dedup)
    var pollRef = React.useRef(null);
    var aliveRef = React.useRef(true);

    // Merge a batch of server messages in, de-duplicated, advancing latestRef.
    var mergeMessages = React.useCallback(function (incoming) {
      if (!incoming || !incoming.length) return;
      setMessages(function (prev) {
        var next = prev.slice();
        for (var i = 0; i < incoming.length; i++) {
          var msg = incoming[i];
          if (!msg) continue;
          var id = msg.id != null ? String(msg.id) : null;
          if (id && seenRef.current[id]) continue;
          if (id) seenRef.current[id] = true;
          // Drop any optimistic placeholder this confirms (same body, inbound).
          if (msg.direction === 'inbound' && msg.body) {
            for (var j = next.length - 1; j >= 0; j--) {
              if (next[j] && next[j]._optimistic && next[j].body === msg.body) {
                next.splice(j, 1);
                break;
              }
            }
          }
          next.push(msg);
          if (msg.created_at && (!latestRef.current || msg.created_at > latestRef.current)) {
            latestRef.current = msg.created_at;
          }
        }
        return next;
      });
    }, []);

    function fetchThread(since) {
      if (!base || !token) return Promise.resolve(null);
      var url = base + '/app/chat/messages?session_token=' + encodeURIComponent(token) + '&limit=50';
      if (since) url += '&since=' + encodeURIComponent(since);
      return fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json' } })
        .then(function (res) { return res.json().catch(function () { return {}; }); })
        .then(function (json) { return json && json.messages ? json.messages : []; })
        .catch(function () { return []; });
    }

    // Initial load + 5s polling with ?since=<latest>. Stop on unmount.
    React.useEffect(function () {
      aliveRef.current = true;
      fetchThread(null).then(function (msgs) {
        if (!aliveRef.current) return;
        mergeMessages(msgs);
        setLoaded(true);
      });
      pollRef.current = setInterval(function () {
        fetchThread(latestRef.current).then(function (msgs) {
          if (!aliveRef.current) return;
          mergeMessages(msgs);
        });
      }, POLL_MS);
      return function () {
        aliveRef.current = false;
        if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; }
      };
      // eslint-disable-next-line
    }, []);

    // Auto-scroll to newest — scrollTop = scrollHeight (never scrollIntoView).
    React.useEffect(function () {
      var el = scrollRef.current;
      if (el) el.scrollTop = el.scrollHeight;
    }, [messages, loaded, sending]);

    function send() {
      var text = (input || '').trim();
      if (!text || sending) return;
      setInput('');
      setSending(true);
      // Optimistic append (no server id yet).
      var optimistic = {
        id: null, _optimistic: true, direction: 'inbound', channel: 'app',
        body: text, author_name: '', created_at: new Date().toISOString(),
      };
      setMessages(function (prev) { return prev.concat([optimistic]); });

      fetch(base + '/app/chat/messages', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ session_token: token, body: text }),
      }).then(function (res) {
        return res.json().catch(function () { return {}; });
      }).then(function () {
        // Refresh from server — confirmed message replaces the optimistic one
        // (mergeMessages drops the matching placeholder by body).
        return fetchThread(latestRef.current);
      }).then(function (msgs) {
        if (aliveRef.current) mergeMessages(msgs);
      }).catch(function () {
        // Leave the optimistic bubble in place; the next poll reconciles.
      }).then(function () {
        if (aliveRef.current) setSending(false);
      });
    }

    var rows = (messages || []).map(function (m, i) {
      return React.createElement(MessageBubble, { key: (m && m.id != null ? 'm' + m.id : 'o' + i), m: m });
    });

    var emptyState = (loaded && rows.length === 0)
      ? React.createElement('div', {
          key: 'empty',
          style: { textAlign: 'center', color: muted, fontFamily: FB, fontSize: 13.5, lineHeight: 1.55, padding: '36px 20px', maxWidth: 320, margin: '0 auto' },
        }, "Send your agent a message — we'll get back to you, usually within about one business hour.")
      : null;

    var canSend = !!input.trim() && !sending;

    return React.createElement(React.Fragment, null, [
      // message list
      React.createElement('div', {
        key: 'list',
        ref: scrollRef,
        style: { flex: 1, overflowY: 'auto', padding: '16px 16px 10px', background: paper },
      }, emptyState || rows),

      // composer
      React.createElement('div', {
        key: 'composer',
        style: { flexShrink: 0, padding: '10px 14px', background: '#fff', borderTop: '1px solid ' + line, display: 'flex', alignItems: 'center', gap: 10 },
      }, [
        React.createElement('input', {
          key: 'input',
          value: input,
          disabled: sending,
          placeholder: 'Message your agent…',
          'aria-label': 'Message your agent',
          onChange: function (e) { setInput(e.target.value); },
          onKeyDown: function (e) { if (e.key === 'Enter') send(); },
          style: {
            flex: 1, border: '1.5px solid ' + line, borderRadius: 999,
            padding: '12px 16px', fontSize: 16, color: ink, outline: 'none',
            background: sending ? paper : '#fff', fontFamily: FB, boxSizing: 'border-box',
          },
        }),
        React.createElement('button', {
          key: 'send',
          onClick: send,
          disabled: !canSend,
          'aria-label': 'Send message',
          style: {
            width: 44, height: 44, borderRadius: '50%', border: 0, flexShrink: 0,
            background: canSend ? red : line, cursor: canSend ? 'pointer' : 'default',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: canSend ? '0 4px 12px rgba(221,28,36,0.3)' : 'none',
            transition: 'background .15s',
          },
        }, React.createElement('svg', { width: 19, height: 19, viewBox: '0 0 24 24', fill: 'none' },
          React.createElement('path', { d: 'M5 12h13M12 5l7 7-7 7', stroke: '#fff', strokeWidth: 2.4, strokeLinecap: 'round', strokeLinejoin: 'round' })
        )),
      ]),
    ]);
  }

  // ── Drawer shell (header + body) ──────────────────────────────────
  function ChatDrawer(props) {
    var T = window.T || {};
    var FD = window.FD || "'Archivo Expanded', Archivo, sans-serif";
    var FM = window.FM || "'Space Mono', monospace";
    var navy = T.navy || '#0A1B2E';
    var green = T.green || '#2E8B6F';

    var mobileState = React.useState(isMobile());
    var mobile = mobileState[0], setMobile = mobileState[1];
    React.useEffect(function () {
      function onResize() { setMobile(isMobile()); }
      window.addEventListener('resize', onResize);
      return function () { window.removeEventListener('resize', onResize); };
    }, []);

    // Escape closes.
    React.useEffect(function () {
      function onKey(e) { if (e.key === 'Escape' && props.onClose) props.onClose(); }
      window.addEventListener('keydown', onKey);
      return function () { window.removeEventListener('keydown', onKey); };
    }, [props]);

    var token = props.token;
    var base = props.base;
    var hasChat = !!(token && base);

    var sheetStyle = mobile
      ? {
          position: 'absolute', left: 0, right: 0, bottom: 0,
          width: '100%', maxHeight: '88vh', height: '88vh',
          borderRadius: '22px 22px 0 0',
        }
      : {
          position: 'absolute', top: 0, right: 0, bottom: 0,
          width: 420, maxWidth: '100%', height: '100%',
        };

    var headerEl = React.createElement('div', {
      key: 'header',
      style: {
        flexShrink: 0, background: navy, padding: mobile ? '16px 18px 14px' : '20px 20px 16px',
        display: 'flex', alignItems: 'center', gap: 12,
      },
    }, [
      React.createElement('div', { key: 'avatar', style: { position: 'relative', flexShrink: 0 } }, [
        React.createElement('div', {
          key: 'a',
          style: { width: 42, height: 42, borderRadius: '50%', background: 'linear-gradient(135deg,#2C5172,#112A44)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: FD, fontWeight: 800, fontSize: 16, color: '#fff', boxShadow: 'inset 0 0 0 1.5px rgba(255,255,255,0.14)' },
        }, 'V'),
        React.createElement('span', {
          key: 'dot',
          style: { position: 'absolute', bottom: 0, right: 0, width: 11, height: 11, borderRadius: '50%', background: green, border: '2px solid ' + navy },
        }),
      ]),
      React.createElement('div', { key: 'title', style: { flex: 1, minWidth: 0 } }, [
        React.createElement('div', {
          key: 't',
          style: { fontFamily: FD, fontWeight: 800, fontSize: 16, color: '#fff', fontStretch: '110%', letterSpacing: '-.005em' },
        }, 'Message your agent'),
        React.createElement('div', {
          key: 's',
          style: { fontFamily: FM, fontSize: 10.5, color: 'rgba(255,255,255,0.6)', marginTop: 2 },
        }, 'Viamar · replies within one business day'),
      ]),
      React.createElement('button', {
        key: 'close',
        onClick: props.onClose,
        'aria-label': 'Close chat',
        style: {
          width: 38, height: 38, borderRadius: 11, border: 0, flexShrink: 0,
          background: 'rgba(255,255,255,0.08)', color: '#fff', cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        },
      }, React.createElement('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'none' },
        React.createElement('path', { d: 'M6 6l12 12M18 6L6 18', stroke: '#fff', strokeWidth: 2.2, strokeLinecap: 'round' })
      )),
    ]);

    var bodyEl = hasChat
      ? React.createElement(ChatBody, { key: 'body', token: token, base: base })
      : React.createElement(NoSessionBody, { key: 'body', onClose: props.onClose });

    var sheet = React.createElement('div', {
      className: mobile ? 'viamar-chat-sheet' : 'viamar-chat-panel',
      role: 'dialog',
      'aria-modal': true,
      'aria-label': 'Message your Viamar agent',
      onMouseDown: function (e) { e.stopPropagation(); },
      style: Object.assign({
        background: (T.paper || '#F4F5F7'),
        display: 'flex', flexDirection: 'column', overflow: 'hidden',
        boxShadow: '0 -10px 60px rgba(0,0,0,0.4)', boxSizing: 'border-box',
      }, sheetStyle),
    }, [headerEl, bodyEl]);

    // Backdrop — click outside closes.
    return React.createElement('div', {
      onMouseDown: function (e) { if (e.target === e.currentTarget && props.onClose) props.onClose(); },
      style: {
        position: 'fixed', inset: 0, zIndex: 9970,
        background: 'rgba(6,16,28,0.5)',
        display: 'flex',
        alignItems: mobile ? 'flex-end' : 'stretch',
        justifyContent: mobile ? 'center' : 'flex-end',
      },
    }, sheet);
  }

  function close() {
    if (!isOpen) return;
    isOpen = false;
    if (chatRoot) chatRoot.render(null);
  }

  function open(opts) {
    opts = opts || {};
    ensureKeyframes();
    var root = ensureRoot();
    isOpen = true;
    var token = sessionToken();
    var base = apiBase();
    if (window.ViamarAnalytics) {
      var reasonEvidence = window.ViamarSupportReason && window.ViamarSupportReason.evidence
        ? window.ViamarSupportReason.evidence(opts)
        : { support_reason: 'general', support_reason_group: 'general_help' };
      window.ViamarAnalytics.track('support_chat_opened', Object.assign({
        source: opts.source || 'chat-panel',
      }, reasonEvidence));
    }
    root.render(React.createElement(ChatDrawer, {
      token: token,
      base: base,
      onClose: close,
    }));
  }

  window.ViamarChat = { open: open, close: close };
})();
