import { describe, it, expect, beforeEach } from 'vitest';
import { InMemoryStorageAdapter } from '../db/adapter';

describe('InMemoryStorageAdapter', () => {
	let adapter: InMemoryStorageAdapter;

	beforeEach(() => {
		adapter = new InMemoryStorageAdapter();
	});

	it('createNode returns a full node with generated ID', async () => {
		const node = await adapter.createNode('g1', { label: 'Test' });
		expect(node.id).toBeTruthy();
		expect(node.graph_id).toBe('g1');
		expect(node.label).toBe('Test');
	});

	it('fetchNodes returns only nodes for given graph', async () => {
		await adapter.createNode('g1', { id: 'n1' });
		await adapter.createNode('g2', { id: 'n2' });
		const nodes = await adapter.fetchNodes('g1');
		expect(nodes).toHaveLength(1);
		expect(nodes[0].id).toBe('n1');
	});

	it('updateNode updates and returns node', async () => {
		await adapter.createNode('g1', { id: 'n1', label: 'Old' });
		const updated = await adapter.updateNode('n1', { label: 'New' });
		expect(updated.label).toBe('New');
	});

	it('updateNode throws for non-existent node', async () => {
		await expect(adapter.updateNode('nope', {})).rejects.toThrow('not found');
	});

	it('deleteNode removes node and connected edges', async () => {
		await adapter.createNode('g1', { id: 'n1' });
		await adapter.createNode('g1', { id: 'n2' });
		await adapter.createEdge('g1', { id: 'e1', source_node_id: 'n1', target_node_id: 'n2' });

		await adapter.deleteNode('n1');

		const nodes = await adapter.fetchNodes('g1');
		expect(nodes).toHaveLength(1);
		const edges = await adapter.fetchEdges('g1');
		expect(edges).toHaveLength(0);
	});

	it('createEdge returns full edge', async () => {
		const edge = await adapter.createEdge('g1', { source_node_id: 'a', target_node_id: 'b' });
		expect(edge.id).toBeTruthy();
		expect(edge.graph_id).toBe('g1');
		expect(edge.source_node_id).toBe('a');
	});

	it('updateEdge throws for non-existent edge', async () => {
		await expect(adapter.updateEdge('nope', {})).rejects.toThrow('not found');
	});

	it('deleteEdge removes edge', async () => {
		await adapter.createEdge('g1', { id: 'e1', source_node_id: 'a', target_node_id: 'b' });
		await adapter.deleteEdge('e1');
		const edges = await adapter.fetchEdges('g1');
		expect(edges).toHaveLength(0);
	});

	it('createNodes batch creates multiple nodes', async () => {
		const nodes = await adapter.createNodes!('g1', [{ id: 'n1' }, { id: 'n2' }]);
		expect(nodes).toHaveLength(2);
		const fetched = await adapter.fetchNodes('g1');
		expect(fetched).toHaveLength(2);
	});

	it('deleteNodes batch removes multiple', async () => {
		await adapter.createNode('g1', { id: 'n1' });
		await adapter.createNode('g1', { id: 'n2' });
		await adapter.deleteNodes!(['n1', 'n2']);
		const nodes = await adapter.fetchNodes('g1');
		expect(nodes).toHaveLength(0);
	});
});
