/* entry.jsx — Full-screen entry gate for iternative.com.
 *
 * WHAT:  Fires on every fresh page load BEFORE the user sees the minimalist
 *        site. Shows a full-viewport background video loop (entry-loop.mp4 —
 *        same loop as the Tribe-Sales-App landing) with a centered glowing
 *        ITernative logo + "Enter" CTA styled like the existing minimalist→
 *        maximalist portal-peek treatment (accent halo, breathing animation,
 *        ring pulse on hover).
 *
 * WHY:   (a) Gives every visitor a deliberate "moment" before the content —
 *        same vibe the Tribe-Sales-App and TribeCalc surfaces have when
 *        Pavel sends them. (b) Hooks an analytics POST so Pavel sees a
 *        timestamped record of "someone walked through the door" in the
 *        same n8n Sales_App_Activity flow that aggregates the rest of the
 *        funnel signals.
 *
 * HOW:   Mounts to its own root div appended to <body>. Independent of the
 *        main React App tree — no shared state. On click of the Enter
 *        button: POST to n8n webhook (fire-and-forget, no-cors,
 *        keepalive=true), fade overlay out, remove from DOM. Once
 *        dismissed, the page underneath is untouched.
 *
 * STYLING REFERENCE:
 *   - Video loop frame:        landing/styles.css from D:\APPS\PROD\Tribe_Sales_App\
 *   - Glowing logo + halo:     .it-portal + .portal-peek-* in styles.css
 *   - Eyebrow/title typography: .portal-peek-eyebrow / .portal-peek-title
 *
 * Does NOT use session-storage skip — every fresh visit shows the gate +
 * fires the webhook. Pavel can add a skip-once-per-session check later if
 * he wants quieter analytics; the current intent is "every visit logged."
 */
(function () {
  'use strict';

  // ── Config ──────────────────────────────────────────────────────────
  var WEBHOOK_URL = 'https://n8n.jane.iternative.com/webhook/f4514cec-8b82-44dc-946c-Sales_App_Activity';
  var FADE_OUT_MS = 520;   // matches a graceful exit duration
  var ROOT_ID = 'entry-gate-root';

  // ── Webhook payload ─────────────────────────────────────────────────
  // Matches the Sales_App_Activity payload shape used elsewhere
  // (src/analytics.js in the Tribe-Sales-App), so the same n8n flow can
  // consume both streams. `target` carries the human-readable label
  // Pavel asked for: "New ITernative.com Visit".
  function uuidV4() {
    try {
      if (window.crypto && typeof window.crypto.randomUUID === 'function') {
        return window.crypto.randomUUID();
      }
    } catch (e) { /* fall through */ }
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      var r = (Math.random() * 16) | 0;
      var v = c === 'x' ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }

  function sessionId() {
    var KEY = 'iternative-entry-session';
    try {
      var existing = sessionStorage.getItem(KEY);
      if (existing) return existing;
      var fresh = uuidV4();
      sessionStorage.setItem(KEY, fresh);
      return fresh;
    } catch (e) { return uuidV4(); }
  }

  function fireWebhook() {
    try {
      var payload = {
        slug:       'iternative-com',
        event_type: 'visit',
        target:     'New ITernative.com Visit',
        session_id: sessionId(),
        timestamp:  new Date().toISOString(),
        user_agent: (navigator && navigator.userAgent) || '',
        url:        window.location.href || ''
      };
      fetch(WEBHOOK_URL, {
        method:    'POST',
        mode:      'no-cors',
        keepalive: true,
        headers:   { 'Content-Type': 'application/json' },
        body:      JSON.stringify(payload)
      }).catch(function () { /* swallow — analytics must not block UX */ });
    } catch (e) { /* swallow */ }
  }

  // ── Mount + render ──────────────────────────────────────────────────
  function mountGate() {
    // Avoid double-mount if the script gets re-executed somehow.
    if (document.getElementById(ROOT_ID)) return;

    var root = document.createElement('div');
    root.id = ROOT_ID;
    root.setAttribute('aria-modal', 'true');
    root.setAttribute('role', 'dialog');
    root.setAttribute('aria-label', 'Welcome to ITernative');
    root.innerHTML = [
      // Background video loop
      '<video class="entry-bg-video" autoplay muted loop playsinline preload="auto" aria-hidden="true">',
        '<source src="entry-loop.mp4" type="video/mp4">',
      '</video>',

      // Veil for legibility
      '<div class="entry-bg-veil" aria-hidden="true"></div>',

      // Centered stage with the glowing-logo + Enter CTA
      '<button class="entry-cta" type="button" aria-label="Enter ITernative.com">',
        '<span class="entry-cta-glow" aria-hidden="true"></span>',
        '<span class="entry-cta-ring" aria-hidden="true"></span>',
        '<span class="entry-cta-logo">',
          '<img src="public/iternative-logo.png" alt="" aria-hidden="true">',
        '</span>',
        '<span class="entry-cta-text">',
          '<span class="entry-cta-eyebrow">— Click to enter —</span>',
          '<span class="entry-cta-title">Enter</span>',
        '</span>',
      '</button>'
    ].join('');

    document.body.appendChild(root);

    // Lock background scroll while gate is up.
    document.body.classList.add('entry-gate-active');

    // Defensive autoplay nudge (mobile Safari edge cases).
    var vid = root.querySelector('video.entry-bg-video');
    if (vid) {
      var tryPlay = function () { vid.play().catch(function () { /* blocked — page still works */ }); };
      if (document.readyState === 'complete') tryPlay();
      else window.addEventListener('load', tryPlay, { once: true });
    }

    // Click ANYWHERE on the gate dismisses — the button itself is just
    // a visual focal point. Pavel 2026-05-13: "make the click anywhere
    // making the entry." Root handles the event; CTA click bubbles up
    // naturally so a click directly on the button also works.
    var cta = root.querySelector('.entry-cta');
    var dismissing = false;
    function dismiss() {
      if (dismissing) return;
      dismissing = true;
      fireWebhook();
      root.classList.add('is-leaving');
      setTimeout(function () {
        try { root.parentNode && root.parentNode.removeChild(root); } catch (e) {}
        document.body.classList.remove('entry-gate-active');
      }, FADE_OUT_MS);
    }
    root.addEventListener('click', dismiss);

    // Keyboard: Enter or Space anywhere on the gate dismisses.
    function onKey(e) {
      if (e.key === 'Enter' || e.key === ' ' || e.key === 'Spacebar') {
        e.preventDefault();
        dismiss();
        document.removeEventListener('keydown', onKey);
      }
    }
    document.addEventListener('keydown', onKey);

    // ── Proximity glow ────────────────────────────────────────────────
    // As the cursor approaches the CTA box, lift the `--proximity` CSS
    // variable from 0 (far) → 1 (over). styles.css uses --proximity to
    // scale the .entry-cta-glow opacity + the .entry-cta-ring opacity,
    // so the visual reaction starts before :hover formally fires and
    // settles smoothly into the hover state.
    //
    // PROXIMITY_RADIUS_PX is the distance at which `--proximity` first
    // rises above 0 (cursor that far away or further sees the resting
    // state). Beyond that, distance is linearly mapped to [0, 1].
    var PROXIMITY_RADIUS_PX = 360;
    var pendingFrame = null;
    var lastMouseX = -1, lastMouseY = -1;
    function updateProximityNow() {
      pendingFrame = null;
      if (!cta || dismissing) return;
      var rect = cta.getBoundingClientRect();
      // Distance to the nearest edge of the CTA rect (so the cursor
      // sitting INSIDE the box reads as distance 0, not the
      // center-to-center distance which would still show "far").
      var dx = Math.max(rect.left - lastMouseX, 0, lastMouseX - rect.right);
      var dy = Math.max(rect.top  - lastMouseY, 0, lastMouseY - rect.bottom);
      var dist = Math.sqrt(dx * dx + dy * dy);
      var proximity;
      if (dist <= 0) {
        proximity = 1;
      } else if (dist >= PROXIMITY_RADIUS_PX) {
        proximity = 0;
      } else {
        proximity = 1 - (dist / PROXIMITY_RADIUS_PX);
      }
      root.style.setProperty('--proximity', proximity.toFixed(3));
    }
    function onMouseMove(e) {
      lastMouseX = e.clientX;
      lastMouseY = e.clientY;
      if (pendingFrame == null) {
        pendingFrame = window.requestAnimationFrame(updateProximityNow);
      }
    }
    root.addEventListener('mousemove', onMouseMove, { passive: true });
    // Cursor leaves the gate entirely → snap back to 0.
    root.addEventListener('mouseleave', function () {
      if (pendingFrame != null) {
        window.cancelAnimationFrame(pendingFrame);
        pendingFrame = null;
      }
      root.style.setProperty('--proximity', '0');
    });
  }

  // Mount as early as possible. document.body must exist; if not yet,
  // defer to DOMContentLoaded.
  if (document.body) {
    mountGate();
  } else {
    document.addEventListener('DOMContentLoaded', mountGate, { once: true });
  }
})();
