/**
 * Zoom Transition Hook
 *
 * Drives the requestAnimationFrame loop for smooth zoom/pan animations.
 * Reads the animation target from zoomAnimationTargetAtom and interpolates
 * zoom/pan values with cubic ease-in-out.
 */

'use client';

import { useEffect, useRef } from 'react';
import { useAtomValue, useSetAtom } from 'jotai';
import {
	zoomAtom,
	panAtom,
	zoomAnimationTargetAtom,
	zoomTransitionProgressAtom,
	zoomFocusNodeIdAtom,
} from '../core/viewport-store';

export interface UseZoomTransitionReturn {
	/** Whether an animation is currently running */
	isAnimating: boolean;
	/** Current transition progress (0-1) */
	progress: number;
	/** Cancel any running animation */
	cancel: () => void;
}

/** Cubic ease-in-out */
function easeInOutCubic(t: number): number {
	return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}

/**
 * Hook that drives zoom/pan animations via requestAnimationFrame.
 *
 * @example
 * ```tsx
 * function Canvas() {
 *   const { isAnimating, progress } = useZoomTransition();
 *   return <div style={{ opacity: isAnimating ? 1 - progress * 0.3 : 1 }}>...</div>;
 * }
 * ```
 */
export function useZoomTransition(): UseZoomTransitionReturn {
	const target = useAtomValue(zoomAnimationTargetAtom);
	const setZoom = useSetAtom(zoomAtom);
	const setPan = useSetAtom(panAtom);
	const setTarget = useSetAtom(zoomAnimationTargetAtom);
	const setProgress = useSetAtom(zoomTransitionProgressAtom);
	const setFocusNode = useSetAtom(zoomFocusNodeIdAtom);
	const progress = useAtomValue(zoomTransitionProgressAtom);
	const rafRef = useRef<number | null>(null);

	const cancel = () => {
		if (rafRef.current !== null) {
			cancelAnimationFrame(rafRef.current);
			rafRef.current = null;
		}
		setTarget(null);
		setProgress(0);
		setFocusNode(null);
	};

	useEffect(() => {
		if (!target) return;

		const animate = () => {
			const elapsed = performance.now() - target.startTime;
			const rawT = Math.min(1, elapsed / target.duration);
			const t = easeInOutCubic(rawT);

			const currentZoom = target.startZoom + (target.targetZoom - target.startZoom) * t;
			const currentPanX = target.startPan.x + (target.targetPan.x - target.startPan.x) * t;
			const currentPanY = target.startPan.y + (target.targetPan.y - target.startPan.y) * t;

			setZoom(currentZoom);
			setPan({ x: currentPanX, y: currentPanY });
			setProgress(t);

			if (rawT < 1) {
				rafRef.current = requestAnimationFrame(animate);
			} else {
				// Animation complete
				rafRef.current = null;
				setTarget(null);
			}
		};

		rafRef.current = requestAnimationFrame(animate);

		return () => {
			if (rafRef.current !== null) {
				cancelAnimationFrame(rafRef.current);
				rafRef.current = null;
			}
		};
	}, [target, setZoom, setPan, setTarget, setProgress]);

	return {
		isAnimating: target !== null,
		progress,
		cancel,
	};
}
