export function detectPlayerPlatform({ userAgent = '', platform = '', maxTouchPoints = 0 } = {}) {
  const isIOS = /iPad|iPhone|iPod/.test(userAgent)
    || (platform === 'MacIntel' && maxTouchPoints > 1);
  const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)
    || maxTouchPoints > 1;
  return { isIOS, isMobile };
}

export function isLandscapeOrientation(orientationType, width, height) {
  if (orientationType) return orientationType.includes('landscape');
  return width > height;
}

export function requiresMobileAudioGesture({ isIOS, isMobile, isEmbedded, hasAudio }) {
  return Boolean((isIOS || isMobile) && isEmbedded && hasAudio);
}

export function sendPlayerActions(targetWindow, origin, actions) {
  if (!targetWindow) return 0;
  for (const action of actions) {
    targetWindow.postMessage({ action }, origin);
  }
  return actions.length;
}

export function bindTouchAndClick(element, handler, {
  setTimer = setTimeout,
  dedupeMs = 300,
} = {}) {
  if (!element) return () => {};
  let touchHandled = false;

  const onTouchEnd = event => {
    event.preventDefault();
    touchHandled = true;
    handler(event);
    setTimer(() => { touchHandled = false; }, dedupeMs);
  };
  const onClick = event => {
    if (!touchHandled) handler(event);
  };

  element.addEventListener('touchend', onTouchEnd, { passive: false });
  element.addEventListener('click', onClick);
  return () => {
    element.removeEventListener('touchend', onTouchEnd);
    element.removeEventListener('click', onClick);
  };
}

export function createMobileFullscreenController({
  documentTarget = globalThis.document,
  windowTarget = globalThis.window,
  screenTarget = globalThis.screen,
  body = documentTarget?.body,
  button = null,
  preferFallback = false,
  nativeTimeoutMs = 700,
  setTimer = setTimeout,
  clearTimer = clearTimeout,
} = {}) {
  let fallbackActive = false;
  const root = documentTarget?.documentElement;

  function nativeElement() {
    return documentTarget?.fullscreenElement
      || documentTarget?.webkitFullscreenElement
      || null;
  }

  function updateFallbackOrientation() {
    const portrait = Number(windowTarget?.innerHeight || 0)
      > Number(windowTarget?.innerWidth || 0);
    body?.classList?.toggle(
      'landscape-fallback-rotated',
      fallbackActive && portrait,
    );
  }

  function updateButton() {
    const active = fallbackActive || Boolean(nativeElement());
    if (!button) return;
    button.setAttribute?.('aria-label', active ? 'Exit fullscreen' : 'Enter fullscreen');
    button.setAttribute?.('title', active ? 'Exit fullscreen (F)' : 'Fullscreen (F)');
    button.setAttribute?.('aria-pressed', String(active));
    button.textContent = active ? '×' : '⛶';
  }

  function setFallback(active) {
    fallbackActive = Boolean(active);
    body?.classList?.toggle('landscape-fallback', fallbackActive);
    updateFallbackOrientation();
    updateButton();
    if (fallbackActive) windowTarget?.scrollTo?.(0, 1);
  }

  async function lockLandscape() {
    try {
      await screenTarget?.orientation?.lock?.('landscape');
    } catch {
      // Safari commonly exposes fullscreen without orientation locking.
    }
  }

  async function exit() {
    if (fallbackActive) {
      setFallback(false);
      screenTarget?.orientation?.unlock?.();
      return true;
    }
    const exitFullscreen = documentTarget?.exitFullscreen
      || documentTarget?.webkitExitFullscreen;
    if (!nativeElement() || !exitFullscreen) return false;
    await exitFullscreen.call(documentTarget);
    screenTarget?.orientation?.unlock?.();
    updateButton();
    return true;
  }

  async function enter() {
    const requestFullscreen = root?.requestFullscreen
      || root?.webkitRequestFullscreen;
    if (!preferFallback && requestFullscreen) {
      try {
        let timeoutId;
        let entered;
        try {
          entered = await Promise.race([
            Promise.resolve(requestFullscreen.call(root)).then(
              () => true,
              () => false,
            ),
            new Promise(resolve => {
              timeoutId = setTimer(() => resolve(false), nativeTimeoutMs);
            }),
          ]);
        } finally {
          if (timeoutId !== undefined) clearTimer(timeoutId);
        }
        if (!entered || !nativeElement()) throw new Error('Native fullscreen unavailable');
        await lockLandscape();
        updateButton();
        return 'native';
      } catch {
        // iPhone Safari rejects document fullscreen; use the landscape stage.
      }
    }
    setFallback(true);
    return 'fallback';
  }

  async function toggle() {
    if (fallbackActive || nativeElement()) {
      await exit();
      return 'exit';
    }
    return enter();
  }

  const onResize = () => updateFallbackOrientation();
  const onFullscreenChange = () => updateButton();
  windowTarget?.addEventListener?.('resize', onResize);
  windowTarget?.addEventListener?.('orientationchange', onResize);
  documentTarget?.addEventListener?.('fullscreenchange', onFullscreenChange);
  documentTarget?.addEventListener?.('webkitfullscreenchange', onFullscreenChange);
  updateButton();

  return {
    toggle,
    enter,
    exit,
    isFallbackActive: () => fallbackActive,
    destroy() {
      setFallback(false);
      windowTarget?.removeEventListener?.('resize', onResize);
      windowTarget?.removeEventListener?.('orientationchange', onResize);
      documentTarget?.removeEventListener?.('fullscreenchange', onFullscreenChange);
      documentTarget?.removeEventListener?.('webkitfullscreenchange', onFullscreenChange);
    },
  };
}
