/* global window, document, sessionStorage, IntersectionObserver */
window.Niwa = window.Niwa || {};

window.Niwa.AdminChatView = (function () {
  'use strict';

  var bodyEl = null;
  var store = null;
  var welcomeNode = null;
  var sentinelEl = null;
  var observer = null;
  var onLoadOlder = null;
  var lastRenderedDate = '';

  function init(el, chatStore, opts) {
    bodyEl = el;
    store = chatStore;
    opts = opts || {};
    onLoadOlder = typeof opts.onLoadOlder === 'function' ? opts.onLoadOlder : null;

    if (!bodyEl || !store) return;

    var existingWelcome = bodyEl.querySelector('.niwa-welcome');
    if (existingWelcome) {
      welcomeNode = existingWelcome.cloneNode(true);
    }

    store.on('messages:replaced', function (payload) {
      renderInitial(payload.messages || []);
    });
    store.on('messages:prepended', function (payload) {
      prependMessages(payload.messages || []);
    });
    store.on('messages:appended', function (payload) {
      appendMessage(payload.message);
    });
    store.on('pending:set', showTyping);
    store.on('pending:cleared', hideTyping);
    store.on('chat:open', scrollToBottomOnNextFrame);

    bodyEl.addEventListener('scroll', function () {
      if (sentinelEl || !onLoadOlder) return;
      if (bodyEl.scrollTop <= 80) {
        onLoadOlder();
      }
    });
  }

  function renderInitial(messages) {
    messages = Array.isArray(messages) ? messages : [];
    disconnectObserver();
    bodyEl.innerHTML = '';
    lastRenderedDate = '';

    if (!messages.length) {
      restoreWelcome();
      renderPendingIfNeeded();
      return;
    }

    ensureSentinel();
    for (var i = 0; i < messages.length; i++) {
      appendMessageNode(messages[i]);
    }

    syncSentinelVisibility();
    renderPendingIfNeeded();
    scrollToBottom();
  }

  function prependMessages(messages) {
    if (!messages.length || !bodyEl) return;
    removeWelcome();
    ensureSentinel();

    var previousScrollHeight = bodyEl.scrollHeight || 0;
    var previousScrollTop = bodyEl.scrollTop || 0;
    var fragment = document.createDocumentFragment();
    var firstVisible = sentinelEl ? sentinelEl.nextSibling : bodyEl.firstChild;

    var previousDate = firstRenderedDate();
    var lastPrependedDate = '';
    for (var i = 0; i < messages.length; i++) {
      var currentDate = dateLabel(messages[i].ts);
      var includeDate = currentDate && currentDate !== lastPrependedDate && currentDate !== previousDate;
      var nodes = buildMessageNodes(messages[i], includeDate ? currentDate : '');
      for (var j = 0; j < nodes.length; j++) {
        fragment.appendChild(nodes[j]);
      }
      lastPrependedDate = currentDate;
    }

    bodyEl.insertBefore(fragment, firstVisible || null);
    var delta = (bodyEl.scrollHeight || 0) - previousScrollHeight;
    bodyEl.scrollTop = Math.max(0, previousScrollTop + delta);
    syncSentinelVisibility();
  }

  function appendMessage(message) {
    if (!message || !bodyEl) return;
    var wasAtBottom = isNearBottom();
    hideTyping();
    removeWelcome();
    ensureSentinel();
    appendMessageNode(message);
    syncSentinelVisibility();
    renderPendingIfNeeded();
    if (wasAtBottom) scrollToBottom();
  }

  function appendMessageNode(message) {
    if (!message) return null;
    var label = dateLabel(message.ts);
    if (label && label !== lastRenderedDate) {
      bodyEl.appendChild(createDateSeparator(label));
      lastRenderedDate = label;
    }

    var node = createMessageNode(message);
    bodyEl.appendChild(node);
    return node;
  }

  function buildMessageNodes(message, forcedDateLabel) {
    var nodes = [];
    var label = forcedDateLabel || '';
    if (label) {
      nodes.push(createDateSeparator(label));
    }
    nodes.push(createMessageNode(message));
    return nodes;
  }

  function createMessageNode(message) {
    var role = message.role === 'user' ? 'user' : 'bot';
    var row = document.createElement('div');
    row.className = 'niwa-message niwa-message--' + role;
    row.setAttribute('data-admin-message-id', message.id || '');
    row.setAttribute('data-admin-message-ts', String(message.ts || ''));

    var avatar = document.createElement('div');
    avatar.className = 'niwa-message__avatar';
    if (role === 'bot') {
      var avatarUrl = window.NiwaAI && window.NiwaAI.avatar_url;
      if (avatarUrl) {
        var img = document.createElement('img');
        img.src = avatarUrl;
        img.alt = 'Niwa';
        img.width = 28;
        img.height = 28;
        avatar.appendChild(img);
      }
    }
    row.appendChild(avatar);

    var content = document.createElement('div');
    content.className = 'niwa-message__content';
    var bubble = document.createElement('div');
    bubble.className = 'niwa-message__bubble';
    var text = document.createElement('p');
    text.className = 'niwa-message__text';

    if (role === 'bot' && window.Niwa && window.Niwa.Utils) {
      text.innerHTML = window.Niwa.Utils.sanitizeHtml(window.Niwa.Utils.formatBotRichText(message.text));
    } else {
      text.textContent = message.text;
    }

    bubble.appendChild(text);
    content.appendChild(bubble);

    var time = document.createElement('div');
    time.className = 'niwa-message__time';
    time.textContent = timeLabel(message.ts);
    content.appendChild(time);
    row.appendChild(content);
    return row;
  }

  function createDateSeparator(label) {
    var sep = document.createElement('div');
    sep.className = 'niwa-messages__date-sep niwa-admin-chat__date-sep';
    sep.textContent = label;
    return sep;
  }

  function showTyping() {
    if (!bodyEl || bodyEl.querySelector('#niwaAdminTyping')) return;
    removeWelcome();
    ensureSentinel();

    var typing = document.createElement('div');
    typing.className = 'niwa-typing niwa-admin-chat__typing';
    typing.id = 'niwaAdminTyping';

    var avatar = document.createElement('div');
    avatar.className = 'niwa-typing__avatar';
    var avatarUrl = window.NiwaAI && window.NiwaAI.avatar_url;
    if (avatarUrl) {
      var img = document.createElement('img');
      img.src = avatarUrl;
      img.alt = 'Niwa';
      img.width = 28;
      img.height = 28;
      avatar.appendChild(img);
    }

    var text = document.createElement('span');
    text.className = 'niwa-typing__text';
    text.textContent = 'Thinking...';
    typing.appendChild(avatar);
    typing.appendChild(text);
    bodyEl.appendChild(typing);
    scrollToBottom();
  }

  function hideTyping() {
    if (!bodyEl) return;
    var typing = bodyEl.querySelector('#niwaAdminTyping');
    if (typing && typing.parentNode) {
      typing.parentNode.removeChild(typing);
    }
  }

  function ensureSentinel() {
    if (sentinelEl && sentinelEl.parentNode === bodyEl) return sentinelEl;
    sentinelEl = document.createElement('div');
    sentinelEl.className = 'niwa-admin-chat__sentinel';
    sentinelEl.setAttribute('aria-hidden', 'true');
    bodyEl.insertBefore(sentinelEl, bodyEl.firstChild);
    observeSentinel();
    return sentinelEl;
  }

  function observeSentinel() {
    disconnectObserver();
    if (!sentinelEl || !onLoadOlder || typeof IntersectionObserver === 'undefined') return;

    observer = new IntersectionObserver(function (entries) {
      if (!entries || !entries.length || !entries[0].isIntersecting) return;
      onLoadOlder();
    }, {
      root: bodyEl,
      threshold: 0.1
    });
    observer.observe(sentinelEl);
  }

  function syncSentinelVisibility() {
    if (!sentinelEl || !store) return;
    var hasMore = !!store.getState().hasMore;
    sentinelEl.hidden = !hasMore;
  }

  function renderPendingIfNeeded() {
    if (!store) return;
    if (store.getState().pending) {
      showTyping();
    }
  }

  function firstRenderedDate() {
    if (!bodyEl) return '';
    var firstMessage = bodyEl.querySelector('.niwa-message[data-admin-message-ts]');
    if (!firstMessage) return '';
    return dateLabel(firstMessage.getAttribute('data-admin-message-ts'));
  }

  function disconnectObserver() {
    if (observer) {
      observer.disconnect();
      observer = null;
    }
  }

  function restoreWelcome() {
    bodyEl.innerHTML = '';
    sentinelEl = null;
    if (welcomeNode) {
      bodyEl.appendChild(welcomeNode.cloneNode(true));
    }
  }

  function removeWelcome() {
    var welcome = bodyEl.querySelector('.niwa-welcome');
    if (welcome && welcome.parentNode) {
      welcome.parentNode.removeChild(welcome);
    }
  }

  function dateLabel(ts) {
    var date = new Date((parseInt(ts, 10) || 0) * 1000);
    if (window.Niwa && window.Niwa.Utils && window.Niwa.Utils.formatDate) {
      return window.Niwa.Utils.formatDate(date);
    }
    return date.toLocaleDateString();
  }

  function timeLabel(ts) {
    var date = new Date((parseInt(ts, 10) || 0) * 1000);
    if (window.Niwa && window.Niwa.Utils && window.Niwa.Utils.formatTime) {
      return window.Niwa.Utils.formatTime(date);
    }
    return date.toLocaleTimeString();
  }

  function isNearBottom() {
    if (!bodyEl) return true;
    return (bodyEl.scrollHeight - bodyEl.scrollTop - bodyEl.clientHeight) < 24;
  }

  function scrollToBottom() {
    if (!bodyEl) return;
    bodyEl.scrollTop = bodyEl.scrollHeight;
  }

  function scrollToBottomOnNextFrame() {
    if (!bodyEl) return;
    window.requestAnimationFrame(scrollToBottom);
  }

  return {
    init: init,
    showTyping: showTyping,
    hideTyping: hideTyping,
    renderPendingIfNeeded: renderPendingIfNeeded,
    scrollToBottom: scrollToBottom
  };
})();
