/**
 * Connected Node Renderer Component
 *
 * Renders all nodes with automatic Supabase persistence.
 * Apps only need to provide renderNode - persistence is handled automatically.
 */

import React from 'react';
import { useAtomValue } from 'jotai';
import { nodePositionAtomFamily } from '../core/graph-position';
import { nodeFamilyAtom } from '../core/graph-derived';
import { visibleNodeKeysAtom } from '../core/virtualization-store';
import type { NodeId, UINodeState } from '../core/types';
import { ConnectedNode, type NodeRenderProps } from './ConnectedNode';

export interface ConnectedNodeRendererProps {
	/** Render function for custom node content */
	renderNode: (props: NodeRenderProps) => React.ReactNode;
	/** Callback when persist fails (optional - for custom error handling) */
	onNodePersistError?: (nodeId: NodeId, error: Error) => void;
	/** Optional wrapper component around nodes */
	nodeWrapper?: React.ComponentType<{ children: React.ReactNode; nodeData: UINodeState }>;
}

/**
 * Renders all nodes from the graph with automatic DB persistence.
 *
 * This is the batteries-included version of NodeRenderer.
 * No need to pass persistence callbacks - changes are automatically
 * synced to Supabase.
 */
export function ConnectedNodeRenderer({
	renderNode,
	onNodePersistError,
	nodeWrapper,
}: ConnectedNodeRendererProps) {
	const nodeKeys = useAtomValue(visibleNodeKeysAtom);

	return (
		<>
			{nodeKeys.map((key) => (
				<ConnectedNodeItem
					key={key}
					nodeKey={key}
					renderNode={renderNode}
					onNodePersistError={onNodePersistError}
					nodeWrapper={nodeWrapper}
				/>
			))}
		</>
	);
}

interface ConnectedNodeItemProps {
	nodeKey: string;
	renderNode: (props: NodeRenderProps) => React.ReactNode;
	onNodePersistError?: (nodeId: NodeId, error: Error) => void;
	nodeWrapper?: React.ComponentType<{ children: React.ReactNode; nodeData: UINodeState }>;
}

function ConnectedNodeItem({
	nodeKey,
	renderNode,
	onNodePersistError,
	nodeWrapper,
}: ConnectedNodeItemProps) {
	const nodeData = useAtomValue(nodeFamilyAtom(nodeKey));
	const position = useAtomValue(nodePositionAtomFamily(nodeKey));

	if (!nodeData) return null;

	return (
		<div
			style={{
				position: 'absolute',
				left: position.x,
				top: position.y,
				transform: 'translate(0, 0)',
			}}
		>
			<ConnectedNode
				nodeData={nodeData}
				renderContent={renderNode}
				onPersistError={onNodePersistError}
				wrapper={nodeWrapper}
			/>
		</div>
	);
}
