// OM Group Premium Loading Screen
// Self-contained — driven by requestAnimationFrame, no external timeline engine.
// Reusable for: login, company-switch, logout, refresh, large report loading.
//
// Usage:
//   <window.AppLoadingScreen onComplete={() => setShowLoading(false)} />
//
// Props:
//   onComplete  — called once when the animation finishes and overlay is at opacity 0.

const { useEffect: _lsEff, useState: _lsSt, useRef: _lsRf } = React;

// ── Constants ─────────────────────────────────────────────────────────────────
const _LS_ORANGE        = '#F15A24';
const _LS_DURATION      = 4.0;   // total animation seconds
const _LS_BREATH_PERIOD = 2.75;  // breathing cycle period

// ── Math helpers ──────────────────────────────────────────────────────────────
function _lsEaseInOut(t) {
  return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}
function _lsBreath(t) {
  return (1 - Math.cos((t / _LS_BREATH_PERIOD) * 2 * Math.PI)) / 2;
}

// ── Component ─────────────────────────────────────────────────────────────────
function AppLoadingScreen({ onComplete, onReveal }) {
  const [time, setTime] = _lsSt(0);
  const startRef      = _lsRf(null);
  const rafRef        = _lsRf(null);
  const calledRef     = _lsRf(false);
  const revealedRef   = _lsRf(false);

  _lsEff(function() {
    startRef.current = performance.now();

    function tick(now) {
      var elapsed = (now - startRef.current) / 1000;

      // Fire onReveal at the START of the fade-out (t=3.6 s).
      // At this point the overlay is still fully opaque, so the dashboard
      // can safely mount behind it and be ready before it turns transparent.
      if (elapsed >= 3.6 && !revealedRef.current) {
        revealedRef.current = true;
        onReveal && onReveal();
      }

      if (elapsed >= _LS_DURATION) {
        setTime(_LS_DURATION);
        if (!calledRef.current) {
          calledRef.current = true;
          // Tiny pause so the last opacity-0 frame paints before unmount
          setTimeout(function() { onComplete && onComplete(); }, 80);
        }
        return;
      }

      setTime(elapsed);
      rafRef.current = requestAnimationFrame(tick);
    }

    rafRef.current = requestAnimationFrame(tick);

    return function() {
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
    };
  }, []); // intentionally empty — runs once on mount

  // ── Animation math ─────────────────────────────────────────────────────────

  // Screen opacity: fully opaque from frame 0, fades out at 3.6–4.0 s.
  // No fade-in — the overlay must be a solid mask from the very first paint.
  var screenOpacity =
    time > 3.6 ? Math.max(0, 1 - (time - 3.6) / 0.4) :
    1;

  // Entry: logo fades + scales in over 0–0.45 s
  var entryT      = Math.min(1, time / 0.45);
  var entryEased  = _lsEaseInOut(entryT);
  var entryScale  = 0.94 + 0.06 * entryEased;
  var entryOpacity= entryEased;
  var entryBlur   = (1 - entryEased) * 5;

  // Breathing: ramps in after 0.45 s, period = BREATH_PERIOD
  var breathActive= Math.max(0, Math.min(1, (time - 0.45) / 0.3));
  var breathVal   = _lsBreath(Math.max(0, time - 0.45));
  var breathScale = 1.0 + breathVal * 0.06 * breathActive;

  // Combined logo transform
  var logoScale   = time < 0.45 ? entryScale   : breathScale;
  var logoOpacity = entryOpacity;
  var logoBlur    = time < 0.45 ? entryBlur    : 0;

  // Glow synced to breath
  var glowBase    = time < 0.6 ? 0 : Math.min(1, (time - 0.6) / 0.4);
  var glowBreath  = 0.22 + breathVal * 0.18 * breathActive;
  var glowOpacity = glowBase * glowBreath;
  var glowSize    = 1.0 + breathVal * 0.25 * breathActive;

  // Drop-shadow synced to breath
  var shadowSpread  = 8  + breathVal * 14   * breathActive;
  var shadowOpacity = 0.10 + breathVal * 0.13 * breathActive;

  // Progress bar: 0→88 % over 0.5–3.0 s, then 88→100 % at 3.0–3.5 s
  var progress =
    time < 0.5 ? 0 :
    time < 3.0 ? ((time - 0.5) / 2.5) * 0.88 :
    Math.min(1.0, 0.88 + ((time - 3.0) / 0.5) * 0.12);

  var barOpacity =
    time < 0.4 ? 0 :
    time < 0.7 ? (time - 0.4) / 0.3 :
    time > 3.5 ? Math.max(0, 1 - (time - 3.5) / 0.15) :
    1;

  // ── Render ──────────────────────────────────────────────────────────────────
  var filterParts = [];
  if (logoBlur > 0.1) filterParts.push('blur(' + logoBlur.toFixed(2) + 'px)');
  filterParts.push(
    'drop-shadow(0 4px ' + shadowSpread.toFixed(1) + 'px rgba(241,90,36,' + shadowOpacity.toFixed(3) + '))'
  );

  return React.createElement('div', {
    style: {
      position:       'fixed',
      inset:          0,
      zIndex:         9999,
      background:     'radial-gradient(ellipse 80% 60% at 50% 42%, #fffaf7 0%, #ffffff 65%)',
      display:        'flex',
      flexDirection:  'column',
      alignItems:     'center',
      justifyContent: 'center',
      opacity:        screenOpacity,
      overflow:       'hidden',
      // Block interaction while visible; allow clicks through once faded
      pointerEvents:  screenOpacity > 0.01 ? 'all' : 'none',
      willChange:     'opacity',
    }
  },

    React.createElement('div', {
      style: {
        display:        'flex',
        flexDirection:  'column',
        alignItems:     'center',
        padding:        '20px',
        maxWidth:       '100vw',
        maxHeight:      '100vh',
        boxSizing:      'border-box',
      }
    },

      // ── Logo + glow container ───────────────────────────────────────────
      React.createElement('div', {
        style: {
          position:       'relative',
          display:        'flex',
          alignItems:     'center',
          justifyContent: 'center',
          // Responsive: scales between 120 px (mobile) and 160 px (desktop)
          width:  'clamp(120px, 20vw, 160px)',
          height: 'clamp(120px, 20vw, 160px)',
          flexShrink: 0,
        }
      },

        // Background glow disc
        React.createElement('div', {
          style: {
            position:     'absolute',
            inset:        0,
            borderRadius: '50%',
            background:   'radial-gradient(circle, ' + _LS_ORANGE + '66 0%, transparent 68%)',
            opacity:      glowOpacity,
            transform:    'scale(' + glowSize.toFixed(4) + ')',
            filter:       'blur(28px)',
            pointerEvents:'none',
          }
        }),

        // Logo image
        React.createElement('img', {
          src:       'uploads/OM GROUP ONLY LOGO.png',
          alt:       'OM Group',
          draggable: 'false',
          style: {
            width:        'clamp(80px, 13vw, 96px)',
            height:       'clamp(80px, 13vw, 96px)',
            objectFit:    'contain',
            opacity:      logoOpacity,
            transform:    'scale(' + logoScale.toFixed(4) + ')',
            filter:       filterParts.join(' '),
            position:     'relative',
            zIndex:       1,
            userSelect:   'none',
            pointerEvents:'none',
            willChange:   'transform, filter',
            display:      'block',
          }
        })
      ),

      // Spacer
      React.createElement('div', { style: { height: 'clamp(24px, 4vh, 36px)' } }),

      // ── Progress bar ───────────────────────────────────────────────────
      React.createElement('div', {
        style: {
          width:        'clamp(120px, 20vw, 160px)',
          height:       2,
          borderRadius: 2,
          background:   'rgba(0,0,0,0.08)',
          overflow:     'hidden',
          opacity:      barOpacity,
          flexShrink:   0,
        }
      },
        React.createElement('div', {
          style: {
            height:     '100%',
            width:      (progress * 100).toFixed(2) + '%',
            background: 'linear-gradient(90deg, ' + _LS_ORANGE + 'aa, ' + _LS_ORANGE + ')',
            borderRadius: 2,
          }
        })
      )
    )
  );
}

window.AppLoadingScreen = AppLoadingScreen;
