/* global React, findTeam, TFApi */
const { useState: useStateF, useEffect: useEffectF, useRef: useRefF } = React;

// =================== Syncing screen ===================
// Calls real /api/time 10 times, computes median offset, then transitions.
function ScreenSyncing({ team, onReady, onFail }) {
  const [tick, setTick] = useStateF(0);
  const [progress, setProgress] = useStateF(0);

  useEffectF(() => {
    const t = setInterval(() => setTick((x) => x + 1), 80);
    let cancelled = false;

    // Run real clock sync
    (async () => {
      try {
        // Visual progress bar — fakes early progress while syncClock runs
        const tickProgress = setInterval(() => {
          setProgress((p) => Math.min(p + 0.04, 0.85));
        }, 60);

        const result = await window.TFApi.syncClock(10);

        clearInterval(tickProgress);
        setProgress(1);

        if (!cancelled) {
          // Tiny visual delay so progress completion is visible
          setTimeout(() => onReady(result), 150);
        }
      } catch (e) {
        if (!cancelled) onFail(e.message || 'Sync failed');
      }
    })();

    return () => { cancelled = true; clearInterval(t); };
  }, []);

  return (
    <div className="phone-inner" style={{
      background: '#000',
      display: 'grid', placeItems: 'center',
    }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{
          position: 'relative', width: 120, height: 120, margin: '0 auto 24px',
        }}>
          {[0, 1, 2].map((i) => (
            <div key={i} style={{
              position: 'absolute', inset: i * 14,
              borderRadius: '50%',
              border: `2px solid ${i === 0 ? team.primary : team.secondary}`,
              opacity: ((tick + i * 3) % 9) / 9,
              transform: `scale(${0.7 + ((tick + i * 3) % 9) / 9 * 0.5})`,
              transition: 'all .12s linear',
            }} />
          ))}
          <div style={{
            position: 'absolute', inset: '40%',
            background: team.primary, borderRadius: '50%',
            boxShadow: `0 0 24px ${team.primary}`,
          }} />
        </div>
        <div className="display" style={{
          fontSize: 24, letterSpacing: '0.04em', color: '#fff',
        }}>
          SYNCING…
        </div>
        <div className="mono" style={{
          fontSize: 11, letterSpacing: '0.3em', color: 'rgba(255,255,255,.55)',
          marginTop: 10,
        }}>
          NTP · {Math.floor(progress * 100)}% · {Math.floor((tick * 80) % 1000).toString().padStart(3, '0')}MS
        </div>
        {/* Progress bar */}
        <div style={{
          marginTop: 18, width: 180, height: 3, borderRadius: 2,
          background: 'rgba(255,255,255,.1)', overflow: 'hidden',
          marginLeft: 'auto', marginRight: 'auto',
        }}>
          <div style={{
            width: `${progress * 100}%`, height: '100%',
            background: team.primary,
            transition: 'width .25s ease',
          }} />
        </div>
      </div>
    </div>
  );
}

// =================== Flash screen ===================
// Globally synchronized via server time + team pattern formula.
function ScreenFlash({ team, initialOffset, onExit }) {
  const [bg, setBg] = useStateF(team.pattern.colors[0]);
  const [hintVisible, setHintVisible] = useStateF(true);
  const [pressProgress, setPressProgress] = useStateF(0);
  const [debugInfo, setDebugInfo] = useStateF(null);

  const offsetRef = useRefF(initialOffset || 0);
  const lastColorRef = useRefF('');
  const pressStart = useRefF(null);
  const rafRef = useRefF(null);
  const wakeLockRef = useRefF(null);
  const resyncIntervalRef = useRefF(null);

  // --- Render loop ---
  useEffectF(() => {
    let alive = true;
    const tick = () => {
      if (!alive) return;
      const color = window.TFApi.getCurrentColor(team.pattern, offsetRef.current);
      if (color !== lastColorRef.current) {
        setBg(color);
        lastColorRef.current = color;
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => { alive = false; cancelAnimationFrame(rafRef.current); };
  }, [team.id]);

  // --- Hide hint after 3s ---
  useEffectF(() => {
    const t = setTimeout(() => setHintVisible(false), 3000);
    return () => clearTimeout(t);
  }, []);

  // --- Wake lock + fullscreen + periodic resync ---
  useEffectF(() => {
    let cancelled = false;

    async function acquire() {
      if ('wakeLock' in navigator) {
        try { wakeLockRef.current = await navigator.wakeLock.request('screen'); } catch {}
      }
      try {
        const el = document.documentElement;
        if (el.requestFullscreen) await el.requestFullscreen();
        else if (el.webkitRequestFullscreen) await el.webkitRequestFullscreen();
      } catch {}
    }
    acquire();

    // Re-sync every 10s, smooth interpolation toward new offset
    resyncIntervalRef.current = setInterval(async () => {
      try {
        const r = await window.TFApi.syncClock(3);
        if (cancelled) return;
        // Smooth toward new offset to avoid visible jumps
        offsetRef.current = offsetRef.current * 0.7 + r.offset * 0.3;
        if (window.location.hash === '#debug') {
          setDebugInfo({ offset: offsetRef.current, rtt: r.rtt });
        }
      } catch {}
    }, 10000);

    // Initial debug
    if (window.location.hash === '#debug') {
      setDebugInfo({ offset: offsetRef.current, rtt: 0 });
    }

    // Re-acquire wake lock on visibility change
    const onVis = async () => {
      if (document.visibilityState === 'visible') {
        if ('wakeLock' in navigator && !wakeLockRef.current) {
          try { wakeLockRef.current = await navigator.wakeLock.request('screen'); } catch {}
        }
        // Refresh offset — app was in background, drift accumulated
        try {
          const r = await window.TFApi.syncClock(5);
          if (!cancelled) offsetRef.current = r.offset;
        } catch {}
      }
    };
    document.addEventListener('visibilitychange', onVis);

    return () => {
      cancelled = true;
      document.removeEventListener('visibilitychange', onVis);
      clearInterval(resyncIntervalRef.current);
      if (wakeLockRef.current) { try { wakeLockRef.current.release(); } catch {} }
      if (document.fullscreenElement) { try { document.exitFullscreen(); } catch {} }
    };
  }, []);

  // --- Long-press exit ---
  const pressDown = (e) => {
    e.preventDefault();
    pressStart.current = Date.now();
    const update = () => {
      if (pressStart.current == null) return;
      const dt = (Date.now() - pressStart.current) / 2000;
      setPressProgress(Math.min(dt, 1));
      if (dt >= 1) {
        pressStart.current = null;
        setPressProgress(0);
        onExit();
        return;
      }
      requestAnimationFrame(update);
    };
    requestAnimationFrame(update);
  };
  const pressUp = () => {
    pressStart.current = null;
    setPressProgress(0);
  };

  // Determine readable text color: pick the OTHER color in the pattern as contrast
  const idx = team.pattern.colors.indexOf(bg);
  const contrastColor = team.pattern.colors[(idx + 1) % team.pattern.colors.length] || '#fff';

  return (
    <div
      className="phone-inner"
      style={{
        background: bg,
        transition: 'background-color 60ms linear',
        cursor: 'pointer',
      }}
      onPointerDown={pressDown}
      onPointerUp={pressUp}
      onPointerLeave={pressUp}
      onPointerCancel={pressUp}
    >
      {/* Subtle vignette so colors don't burn flat */}
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: 'radial-gradient(circle at 50% 50%, transparent 50%, rgba(0,0,0,.18) 100%)',
      }} />

      {/* Hint */}
      <div style={{
        position: 'absolute', top: 60, left: 24, right: 24,
        display: 'flex', justifyContent: 'center',
        opacity: hintVisible ? 1 : 0,
        transition: 'opacity 600ms ease',
        pointerEvents: 'none',
      }}>
        <div style={{
          padding: '10px 16px',
          background: 'rgba(0,0,0,.45)',
          borderRadius: 12,
          backdropFilter: 'blur(8px)',
          WebkitBackdropFilter: 'blur(8px)',
        }}>
          <div style={{
            color: '#fff', fontSize: 12, fontWeight: 600,
            letterSpacing: '0.04em', textAlign: 'center',
            lineHeight: 1.35,
          }}>
            Hold the screen for<br />
            <span style={{ fontFamily: 'var(--display)', fontSize: 16, letterSpacing: '0.06em' }}>2 SECONDS TO EXIT</span>
          </div>
        </div>
      </div>

      {/* Press progress ring */}
      {pressProgress > 0 && (
        <div style={{
          position: 'absolute', left: '50%', top: '50%',
          transform: 'translate(-50%, -50%)',
          pointerEvents: 'none',
        }}>
          <svg width="120" height="120" viewBox="0 0 120 120">
            <circle cx="60" cy="60" r="50" stroke="rgba(0,0,0,.2)" strokeWidth="6" fill="none" />
            <circle
              cx="60" cy="60" r="50"
              stroke={contrastColor}
              strokeWidth="6"
              fill="none"
              strokeLinecap="round"
              strokeDasharray={`${2 * Math.PI * 50}`}
              strokeDashoffset={`${2 * Math.PI * 50 * (1 - pressProgress)}`}
              transform="rotate(-90 60 60)"
              style={{ transition: 'stroke-dashoffset .08s linear' }}
            />
          </svg>
        </div>
      )}

      {/* Debug info if #debug in URL */}
      {debugInfo && (
        <div style={{
          position: 'absolute', bottom: 24, left: 0, right: 0,
          display: 'flex', justifyContent: 'center',
          pointerEvents: 'none',
        }}>
          <div className="mono" style={{
            fontSize: 10, color: contrastColor, letterSpacing: '0.2em',
            fontWeight: 600,
            background: 'rgba(0,0,0,.35)', padding: '4px 10px', borderRadius: 999,
          }}>
            offset {debugInfo.offset.toFixed(0)}ms · rtt {debugInfo.rtt.toFixed(0)}ms
          </div>
        </div>
      )}
    </div>
  );
}

window.ScreenSyncing = ScreenSyncing;
window.ScreenFlash = ScreenFlash;
