// Screen wake-lock for active calls. WebKit + WebView2 both ship the
// Screen Wake Lock API (tauri 2.x). Browsers release the sentinel when
// the page becomes hidden, so we re-acquire on visibilitychange while a
// call is active.

interface WakeLockSentinelLike {
  release: () => Promise<void>;
  addEventListener: (event: string, fn: () => void) => void;
}

interface WakeLockNavigator {
  wakeLock?: {
    request: (type: 'screen') => Promise<WakeLockSentinelLike>;
  };
}

let sentinel: WakeLockSentinelLike | null = null;
let active = false;
let visibilityBound = false;

function hasWakeLock(): boolean {
  return typeof navigator !== 'undefined' && !!(navigator as unknown as WakeLockNavigator).wakeLock;
}

async function acquire(): Promise<void> {
  if (sentinel || !hasWakeLock()) return;
  try {
    const s = await (navigator as unknown as WakeLockNavigator).wakeLock!.request('screen');
    sentinel = s;
    s.addEventListener('release', () => {
      sentinel = null;
      // If still active (released by the browser because we went hidden),
      // wait for visibility and re-request.
    });
  } catch (err: unknown) {
    // Permission denied, document not visible, etc. Harmless — the call
    // still works, the user's screen may dim. Log once.
    console.warn('wakeLock request failed', err);
  }
}

async function release(): Promise<void> {
  if (!sentinel) return;
  try {
    await sentinel.release();
  } catch {
    /* already released */
  }
  sentinel = null;
}

function onVisibility(): void {
  if (!active) return;
  if (document.visibilityState === 'visible') {
    void acquire();
  }
}

// Called from CallContext when the call enters a state that should keep
// the screen awake (connected / connecting). Toggle off again when the
// call ends.
export async function setCallWakeLock(on: boolean): Promise<void> {
  active = on;
  if (on) {
    if (!visibilityBound) {
      document.addEventListener('visibilitychange', onVisibility);
      visibilityBound = true;
    }
    await acquire();
  } else {
    if (visibilityBound) {
      document.removeEventListener('visibilitychange', onVisibility);
      visibilityBound = false;
    }
    await release();
  }
}
