import type { PointerEvent as ReactPointerEvent } from 'react';

type PointerLikeEvent = MouseEvent & { pageX?: number; pageY?: number };
type PreventableEvent = Event | ReactPointerEvent | { preventDefault?: () => void; stopPropagation?: () => void };

export const preventAll = (event?: PreventableEvent | null): void => {
  if (!event) {
    return;
  }
  try {
    event.preventDefault();
  } catch (error) {
    console.warn('[events] preventDefault failed', error);
  }
  try {
    event.stopPropagation();
  } catch (error) {
    console.warn('[events] stopPropagation failed', error);
  }
};

type AnyFn = (...args: unknown[]) => unknown;

export const safeInvoke = <Fn extends AnyFn>(
  fn: Fn | null | undefined,
  ...args: Parameters<Fn>
): ReturnType<Fn> | undefined =>
  (fn ? (fn(...args) as ReturnType<Fn>) : undefined);

export const getPointerPosition = (
  event?: PointerLikeEvent | null,
  { fallbackToPage = true }: { fallbackToPage?: boolean } = {},
): { x: number; y: number } => {
  if (!event) {
    return { x: 0, y: 0 };
  }
  const clientX = Number.isFinite(event.clientX) ? event.clientX : null;
  const clientY = Number.isFinite(event.clientY) ? event.clientY : null;
  const pageX = fallbackToPage && Number.isFinite(event.pageX) ? event.pageX : null;
  const pageY = fallbackToPage && Number.isFinite(event.pageY) ? event.pageY : null;
  return {
    x: clientX ?? pageX ?? 0,
    y: clientY ?? pageY ?? 0,
  };
};
