/* global window */
window.Niwa = window.Niwa || {};

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

  function create(opts) {
    opts = opts || {};
    var store = opts.store || null;
    var transport = opts.transport || null;
    var setInputValue = typeof opts.setInputValue === 'function' ? opts.setInputValue : function () {};
    var syncSendDisabled = typeof opts.syncSendDisabled === 'function' ? opts.syncSendDisabled : function () {};
    var onTailNeeded = typeof opts.onTailNeeded === 'function' ? opts.onTailNeeded : function () {};
    var onIdleNeeded = typeof opts.onIdleNeeded === 'function' ? opts.onIdleNeeded : function () {};
    var onAjaxError = typeof opts.onAjaxError === 'function' ? opts.onAjaxError : defaultAjaxError;
	var persistence = window.Niwa.AdminChatPersistence || null;
    var sending = false;
    var activeSend = null;
	var sendQueue = persistence && typeof persistence.loadSendQueue === 'function' ? persistence.loadSendQueue() : [];
    var sendRetryTimer = null;
	if (sendQueue.length) scheduleSendRetry(0);

    function sendMessage(rawText) {
      var text = String(rawText || '').trim();
      if (!text || !store || !transport) return;

      var nowSec = Math.floor(Date.now() / 1000);
	  var sentAt = Date.now();
	  var requestId = buildRequestId(sentAt);
      store.append({ id: requestId, role: 'user', text: text, ts: nowSec, source: 'admin_ui', local: true });
      setInputValue('');
	  enqueueSend(text, sentAt, requestId);
      syncSendDisabled();
      processSendQueue();
    }

    function enqueueSend(text, sentAt, requestId) {
      sentAt = sentAt || Date.now();
      sendQueue.push({
        text: String(text || ''),
        sentAt: sentAt,
        requestId: requestId || buildRequestId(sentAt),
        attempts: 0
      });
	  persistSendQueue();
    }

    function processSendQueue() {
      if (sending || activeSend || !sendQueue.length || !store || !transport) return;

      activeSend = sendQueue.shift();
	  persistSendQueue();
      sending = true;
      store.setPending(activeSend.text, activeSend.sentAt, {
        requestId: activeSend.requestId || ''
      });
      syncSendDisabled();

      var fd = transport.baseFormData((window.NiwaAI && window.NiwaAI.action) || 'niwa_ai_admin_autonomy_chat');
      fd.append('_ajax_nonce', transport.getNonce());
      fd.append('message', activeSend.text);
      fd.append('request_id', activeSend.requestId || buildRequestId(activeSend.sentAt));

      transport.fetchAjax(fd, false).then(function (response) {
        if (!response || !response.success) {
		  var errorCode = response && response.data ? String(response.data.code || response.data.error || '') : '';
		  if (errorCode === 'admin_ui_request_message_conflict' || errorCode === 'admin_ui_chat_queue_full' || errorCode === 'empty_message') {
            onAjaxError(response, 'Admin chat request failed.');
			store.clearPending(activeSend.requestId || '');
            finishActiveSend();
		  } else retryActiveSend();
          return;
        }

        var data = response.data || {};
        var jobId = data.job_id ? String(data.job_id) : '';
        if (jobId) {
          store.setPending(activeSend.text, activeSend.sentAt, {
            jobId: jobId,
            requestId: activeSend.requestId || '',
			session: data.session || '',
			generation: parseInt(data.generation || 0, 10) || 0,
			sequence: parseInt(data.sequence || 0, 10) || 0,
			phase: 'pending'
          });
          onTailNeeded(0);
		} else {
          onTailNeeded(0);
        }
		finishActiveSend();
      }).catch(function () {
		retryActiveSend();
      }).then(function () {
        syncSendDisabled();
        onIdleNeeded();
      });
    }

    function retryActiveSend() {
      if (!activeSend) return;
      activeSend.attempts = (activeSend.attempts || 0) + 1;
	  if (activeSend.attempts > 5) {
		store.clearPending(activeSend.requestId || '');
		store.append({ id: 'admin_error_' + activeSend.requestId, role: 'bot', text: 'Network/CDN connection error. Reload the page and send the message again.', ts: Math.floor(Date.now() / 1000), source: 'admin_error', requestId: activeSend.requestId, local: true });
		finishActiveSend();
		return;
	  }
      var retryDelay = Math.min(30000, 1200 * activeSend.attempts);
      var item = activeSend;
      activeSend = null;
      sending = false;
      sendQueue.unshift(item);
	  persistSendQueue();
      syncSendDisabled();
      scheduleSendRetry(retryDelay);
    }

    function finishActiveSend() {
      activeSend = null;
      sending = false;
	  persistSendQueue();
      syncSendDisabled();
      if (sendQueue.length) {
        scheduleSendRetry(0);
      }
    }

    function scheduleSendRetry(delay) {
      if (sendRetryTimer) {
        window.clearTimeout(sendRetryTimer);
      }
      sendRetryTimer = window.setTimeout(function () {
        sendRetryTimer = null;
        processSendQueue();
      }, Math.max(0, delay || 0));
    }

	function persistSendQueue() {
	  if (persistence && typeof persistence.writeSendQueue === 'function') {
		persistence.writeSendQueue((activeSend ? [activeSend] : []).concat(sendQueue));
	  }
	}

    return {
      sendMessage: sendMessage,
      finishActiveSend: finishActiveSend,
      processSendQueue: processSendQueue
    };
  }

  function buildRequestId(seed) {
    var random = Math.random().toString(36).slice(2, 10);
    return 'admin_ui_' + String(seed || Date.now()) + '_' + random;
  }

  function defaultAjaxError(response, fallback) {
    if (window.console && window.console.warn) {
      window.console.warn(fallback, response);
    }
  }

  return {
    create: create
  };
})();
