import { useCallback, useEffect, useRef } from "react";

import * as S from "./style";

const MIN_WIDTH = 368;
const MAX_WIDTH = 1280;

const ResizeHandle = (props: IResizeHandleProps): JSX.Element => {
	const { onMouseMove, currentWidth = 500 } = props;

	const isDragging = useRef(false);
	const handlerRef = useRef<HTMLDivElement>(null);

	const handleResize = useCallback(
		(e: MouseEvent) => {
			if (!isDragging.current) return;
			e.preventDefault();

			const newWidth = document.body.offsetWidth - e.clientX;
			const validatedWidth = Math.max(MIN_WIDTH, Math.min(newWidth, MAX_WIDTH));
			onMouseMove(validatedWidth);
		},
		[onMouseMove],
	);

	const handleMouseUp = useCallback(() => {
		isDragging.current = false;
		document.body.classList.remove("no-select");
	}, []);

	const handleMouseDown = useCallback(() => {
		isDragging.current = true;
		document.body.classList.add("no-select");
	}, []);

	const handleKeyDown = useCallback(
		(e: React.KeyboardEvent<HTMLDivElement>) => {
			const step = 20;
			let newWidth: number | null = null;

			if (e.key === "ArrowRight") {
				newWidth = Math.max(MIN_WIDTH, currentWidth - step);
				e.preventDefault();
			} else if (e.key === "ArrowLeft") {
				newWidth = Math.min(MAX_WIDTH, currentWidth + step);
				e.preventDefault();
			}

			if (newWidth !== null) {
				onMouseMove(newWidth);
			}
		},
		[onMouseMove, currentWidth],
	);

	useEffect(() => {
		window.addEventListener("mousemove", handleResize);
		window.addEventListener("mouseup", handleMouseUp);

		return () => {
			window.removeEventListener("mousemove", handleResize);
			window.removeEventListener("mouseup", handleMouseUp);
		};
	}, [handleResize, handleMouseUp]);

	useEffect(() => {
		const handleIframeMove = (event: MessageEvent) => {
			if (!isDragging.current) return;
			if (event.data?.type !== "iframe-mousemove") return;

			handleResize({
				clientX: event.data.clientX,
				preventDefault: () => {},
			} as MouseEvent);
		};

		window.addEventListener("message", handleIframeMove);

		return () => {
			window.removeEventListener("message", handleIframeMove);
		};
	}, [handleResize]);

	return (
		<S.Handler
			ref={handlerRef}
			onMouseDown={handleMouseDown}
			onKeyDown={handleKeyDown}
			tabIndex={0}
			role="slider"
			aria-label="Panel resize handle"
			aria-valuemin={MIN_WIDTH}
			aria-valuemax={MAX_WIDTH}
			data-testid="handler"
		/>
	);
};

export interface IResizeHandleProps {
	onMouseMove: (value: number) => void;
	currentWidth?: number;
}

export default ResizeHandle;
