/**
 * Hook for detecting two-finger split gesture on a node.
 *
 * Tracks 2 finger pointers on the node element. When they diverge
 * past SPLIT_THRESHOLD (80px screen distance increase), the node is
 * split into two copies with all edges duplicated.
 *
 * Uses raw PointerEvents (not @use-gesture pinch) so it doesn't
 * conflict with the Viewport's pinch-to-zoom.
 */

import { useRef } from 'react';
import { useAtomValue, useSetAtom } from 'jotai';
import type { NodeId } from '../core/types';
import { splitNodeAtom } from '../core/graph-mutations';
import { screenToWorldAtom } from '../core/viewport-store';

const SPLIT_THRESHOLD = 80; // px screen distance increase to trigger split

interface PointerInfo {
	pointerId: number;
	x: number;
	y: number;
}

export interface UseSplitGestureReturn {
	onPointerDown: (e: React.PointerEvent) => void;
	onPointerMove: (e: React.PointerEvent) => void;
	onPointerUp: (e: React.PointerEvent) => void;
}

export function useSplitGesture(nodeId: NodeId): UseSplitGestureReturn {
	const splitNode = useSetAtom(splitNodeAtom);
	const screenToWorld = useAtomValue(screenToWorldAtom);

	const pointersRef = useRef<Map<number, PointerInfo>>(new Map());
	const initialDistanceRef = useRef<number | null>(null);
	const splitFiredRef = useRef(false);

	const getDistance = (a: PointerInfo, b: PointerInfo) =>
		Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);

	const onPointerDown = (e: React.PointerEvent) => {
		if (e.pointerType !== 'touch') return;

		pointersRef.current.set(e.pointerId, {
			pointerId: e.pointerId,
			x: e.clientX,
			y: e.clientY,
		});

		if (pointersRef.current.size === 2) {
			const [p1, p2] = Array.from(pointersRef.current.values());
			initialDistanceRef.current = getDistance(p1, p2);
			splitFiredRef.current = false;
		}
	};

	const onPointerMove = (e: React.PointerEvent) => {
		if (e.pointerType !== 'touch') return;
		if (!pointersRef.current.has(e.pointerId)) return;

		pointersRef.current.set(e.pointerId, {
			pointerId: e.pointerId,
			x: e.clientX,
			y: e.clientY,
		});

		if (pointersRef.current.size === 2 && initialDistanceRef.current !== null && !splitFiredRef.current) {
			const [p1, p2] = Array.from(pointersRef.current.values());
			const currentDistance = getDistance(p1, p2);
			const delta = currentDistance - initialDistanceRef.current;

			if (delta > SPLIT_THRESHOLD) {
				splitFiredRef.current = true;
				e.stopPropagation();

				// Convert finger positions to world coordinates
				const world1 = screenToWorld(p1.x, p1.y);
				const world2 = screenToWorld(p2.x, p2.y);

				splitNode({
					nodeId,
					position1: world1,
					position2: world2,
				});
			}
		}
	};

	const onPointerUp = (e: React.PointerEvent) => {
		pointersRef.current.delete(e.pointerId);
		if (pointersRef.current.size < 2) {
			initialDistanceRef.current = null;
			splitFiredRef.current = false;
		}
	};

	return { onPointerDown, onPointerMove, onPointerUp };
}
