/*!
 * pp-visit.js — PPPHP visitor-analytics beacon (console installs only).
 *
 * Sends the signals only the browser can measure — timezone, screen, viewport,
 * connection, engagement time, page-load speed — to /pp/visit, where the server
 * attaches them to the current session's visit row. Accurate device + real
 * location (timezone) detail without any third-party tracker.
 *
 * Vanilla, dependency-free, deferred, and defensive: any failure is swallowed so
 * it can never affect the page.
 */
(function () {
  'use strict';
  if (window.__ppVisitLoaded) return;      // once per page
  window.__ppVisitLoaded = true;

  var endpoint = window.__PP_VISIT || deriveEndpoint();
  if (!endpoint) return;

  function deriveEndpoint() {
    try {
      var s = document.currentScript;
      if (!s) { var all = document.getElementsByTagName('script'); s = all[all.length - 1]; }
      var src = (s && s.src) || '';
      return src.replace(/\/js\/pp-visit\.js.*$/, '').replace(/\/assets$/, '') + '/pp/visit';
    } catch (e) { return ''; }
  }

  var n = navigator || {};
  var conn = n.connection || n.mozConnection || n.webkitConnection || {};

  function loadMs() {
    try {
      var nav = performance.getEntriesByType && performance.getEntriesByType('navigation')[0];
      if (nav) return Math.max(0, Math.round(nav.duration || (nav.loadEventEnd - nav.startTime)));
      var t = performance.timing;
      if (t && t.loadEventEnd && t.navigationStart) return Math.max(0, t.loadEventEnd - t.navigationStart);
    } catch (e) {}
    return 0;
  }

  function base() {
    var d = {
      tz:    tz(),
      langs: (n.languages || []).slice(0, 6).join(',') || n.language || '',
      sw:    numeric(screen.width),
      sh:    numeric(screen.height),
      vw:    numeric(window.innerWidth),
      vh:    numeric(window.innerHeight),
      dpr:   window.devicePixelRatio || 1,
      cd:    numeric(screen.colorDepth),
      touch: ('ontouchstart' in window) || (n.maxTouchPoints > 0) ? 1 : 0,
      cores: numeric(n.hardwareConcurrency),
      mem:   n.deviceMemory || 0,
      conn:  (conn.effectiveType || '').substring(0, 12),
      dark:  matchDark() ? 1 : 0,
      wd:    n.webdriver ? 1 : 0,
      path:  location.pathname
    };
    return d;
  }

  function tz() { try { return Intl.DateTimeFormat().resolvedOptions().timeZone || ''; } catch (e) { return ''; } }
  function matchDark() { try { return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; } catch (e) { return false; } }
  function numeric(v) { v = parseInt(v, 10); return isFinite(v) && v > 0 ? v : 0; }

  function send(data, useBeacon) {
    try {
      var body = JSON.stringify(data);
      if (useBeacon && n.sendBeacon) {
        n.sendBeacon(endpoint, new Blob([body], { type: 'application/json' }));
      } else {
        fetch(endpoint, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: body,
          keepalive: true,
          credentials: 'same-origin'
        }).catch(function () {});
      }
    } catch (e) {}
  }

  // ── Engagement: count seconds the page is visible AND the user is active ──
  var active = 0, engaged = true, idleTimer = null, pageStart = Date.now();

  var ticker = setInterval(function () {
    if (document.visibilityState === 'visible' && engaged) active++;
  }, 1000);

  function onActivity() {
    engaged = true;
    if (idleTimer) clearTimeout(idleTimer);
    idleTimer = setTimeout(function () { engaged = false; }, 30000);   // idle after 30s
  }
  ['mousemove', 'keydown', 'scroll', 'click', 'touchstart'].forEach(function (ev) {
    window.addEventListener(ev, onActivity, { passive: true });
  });
  onActivity();

  function sessionActive() {
    var prev = 0;
    try { prev = parseInt(sessionStorage.getItem('ppActive') || '0', 10) || 0; } catch (e) {}
    return prev + active;
  }

  var flushed = false;
  function flush() {
    var total = sessionActive();
    try { sessionStorage.setItem('ppActive', String(total)); } catch (e) {}
    send({ active: total, dwell: Date.now() - pageStart, path: location.pathname }, true);
    active = 0;   // its share is now banked in sessionStorage
  }
  document.addEventListener('visibilitychange', function () {
    if (document.visibilityState === 'hidden') flush();
  });
  window.addEventListener('pagehide', function () { if (!flushed) { flushed = true; flush(); } });

  // ── Initial payload, once the page has settled ──
  function init() {
    var d = base();
    d.load = loadMs();
    d.active = sessionActive();
    send(d, false);
  }
  if (document.readyState === 'complete') setTimeout(init, 300);
  else window.addEventListener('load', function () { setTimeout(init, 300); });
})();
