/**
 * Grid Layout Hook
 *
 * Arranges nodes in a uniform grid. Sorts by existing position
 * (top-left to bottom-right) to preserve rough spatial order.
 */

import { useAtomValue } from 'jotai';
import { useRef } from 'react';
import { graphAtom } from '../core/graph-store';
import { uiNodesAtom } from '../core/graph-derived';
import { useAnimatedLayout, type UseAnimatedLayoutOptions } from './useAnimatedLayout';
import type { NodePosition, GraphNodeAttributes } from '../core/types';

export interface UseGridLayoutOptions extends UseAnimatedLayoutOptions {
	/** Number of columns. Default: auto (sqrt of node count) */
	columns?: number;
	/** Gap between cells. Default: 80 */
	gap?: number;
}

export function useGridLayout(options: UseGridLayoutOptions = {}) {
	const { columns, gap = 80, ...animateOptions } = options;

	const graph = useAtomValue(graphAtom);
	const nodes = useAtomValue(uiNodesAtom);
	const { animate, isAnimating } = useAnimatedLayout(animateOptions);
	const isRunningRef = useRef(false);

	const applyLayout = async (): Promise<void> => {
		if (isRunningRef.current || isAnimating) return;
		if (nodes.length === 0) return;

		isRunningRef.current = true;

		// Sort nodes by position: top-to-bottom, then left-to-right
		const sorted = [...nodes].sort((a, b) => {
			const ay = a.position?.y ?? 0;
			const by = b.position?.y ?? 0;
			if (Math.abs(ay - by) > 50) return ay - by;
			return (a.position?.x ?? 0) - (b.position?.x ?? 0);
		});

		const cols = columns ?? Math.ceil(Math.sqrt(sorted.length));

		// Compute cell size from max node dimensions
		let maxW = 200;
		let maxH = 100;
		for (const node of sorted) {
			if (graph.hasNode(node.id)) {
				const attrs = graph.getNodeAttributes(node.id) as GraphNodeAttributes;
				maxW = Math.max(maxW, attrs.width || 200);
				maxH = Math.max(maxH, attrs.height || 100);
			}
		}

		const cellW = maxW + gap;
		const cellH = maxH + gap;
		const rows = Math.ceil(sorted.length / cols);

		// Center grid around (0,0)
		const totalW = (cols - 1) * cellW;
		const totalH = (rows - 1) * cellH;
		const offsetX = -totalW / 2;
		const offsetY = -totalH / 2;

		const targets = new Map<string, NodePosition>();
		for (let i = 0; i < sorted.length; i++) {
			const col = i % cols;
			const row = Math.floor(i / cols);
			targets.set(sorted[i].id, {
				x: Math.round(offsetX + col * cellW),
				y: Math.round(offsetY + row * cellH),
			});
		}

		await animate(targets, 'Grid layout');
		isRunningRef.current = false;
	};

	return {
		applyLayout,
		isRunning: isRunningRef.current || isAnimating,
	};
}
