import {
  type MouseEvent as ReactMouseEvent,
  useCallback,
  useEffect,
  useRef,
  useState,
} from 'react';

import { CursorType } from 'src/pages/dashboard/Conversations/types';

type UseZoomPanReturn = {
  transform: string;
  cursor: CursorType;
  isDragging: boolean;
  handlers: {
    onMouseDown: (e: ReactMouseEvent) => void;
    onMouseMove: (e: ReactMouseEvent) => void;
    onMouseUp: () => void;
    onMouseLeave: () => void;
  };
};

const useZoomPan = (zoom: number): UseZoomPanReturn => {
  const [offset, setOffset] = useState({ x: 0, y: 0 });
  const [isDragging, setIsDragging] = useState(false);
  const dragStart = useRef({ x: 0, y: 0 });
  const offsetAtDragStart = useRef({ x: 0, y: 0 });

  useEffect(() => {
    setOffset({ x: 0, y: 0 });
  }, [zoom]);

  const onMouseDown = useCallback(
    (e: ReactMouseEvent) => {
      if (zoom <= 1) return;
      e.preventDefault();
      setIsDragging(true);
      dragStart.current = { x: e.clientX, y: e.clientY };
      offsetAtDragStart.current = { x: offset.x, y: offset.y };
    },
    [zoom, offset],
  );

  const onMouseMove = useCallback(
    (e: ReactMouseEvent) => {
      if (!isDragging) return;
      setOffset({
        x: offsetAtDragStart.current.x + (e.clientX - dragStart.current.x),
        y: offsetAtDragStart.current.y + (e.clientY - dragStart.current.y),
      });
    },
    [isDragging],
  );

  const onMouseUp = useCallback(() => setIsDragging(false), []);

  let cursor: CursorType = CursorType.DEFAULT;
  if (zoom > 1) cursor = isDragging ? CursorType.GRABBING : CursorType.GRAB;

  return {
    transform: `translate(${offset.x}px, ${offset.y}px) scale(${zoom})`,
    cursor,
    isDragging,
    handlers: { onMouseDown, onMouseMove, onMouseUp, onMouseLeave: onMouseUp },
  };
};

export default useZoomPan;
