import { useRef, useCallback, MouseEvent } from 'react';

const DRAG_THRESHOLD = 5;

export default function useDragScroll<T extends HTMLElement = HTMLElement>() {
	const ref = useRef<T>(null);
	const isDragging = useRef(false);
	const hasMoved = useRef(false);
	const startX = useRef(0);
	const scrollLeft = useRef(0);

	const onMouseDown = useCallback((e: MouseEvent) => {
		const el = ref.current;
		if (!el) return;

		e.preventDefault();
		isDragging.current = true;
		hasMoved.current = false;
		startX.current = e.pageX - el.offsetLeft;
		scrollLeft.current = el.scrollLeft;
		el.style.cursor = 'grabbing';
	}, []);

	const onMouseMove = useCallback((e: MouseEvent) => {
		if (!isDragging.current) return;
		const el = ref.current;
		if (!el) return;

		const x = e.pageX - el.offsetLeft;
		const walk = x - startX.current;

		if (!hasMoved.current && Math.abs(walk) > DRAG_THRESHOLD) {
			hasMoved.current = true;
			el.style.pointerEvents = 'auto';
			for (const child of el.children) {
				(child as HTMLElement).style.pointerEvents = 'none';
			}
		}

		e.preventDefault();
		el.scrollLeft = scrollLeft.current - walk;
	}, []);

	const resetState = useCallback(() => {
		isDragging.current = false;
		const el = ref.current;
		if (!el) return;
		el.style.cursor = 'grab';
		if (hasMoved.current) {
			for (const child of el.children) {
				(child as HTMLElement).style.pointerEvents = '';
			}
		}
		hasMoved.current = false;
	}, []);

	const onMouseUp = useCallback(() => resetState(), [resetState]);
	const onMouseLeave = useCallback(() => resetState(), [resetState]);

	return {
		ref,
		onMouseDown,
		onMouseMove,
		onMouseUp,
		onMouseLeave,
	};
}