import { Table } from '@backend/domain'
import { TableGraph, TableGraphBuilder } from './table-graph'
describe('TableGraph', () => {
	let tableA: Table
	let tableB: Table
	let tableC: Table
	let tableD: Table
	let graph: TableGraph
	beforeAll(() => {
		tableA = new Table({ id: 'A' })
		tableB = new Table({ id: 'B' })
		tableC = new Table({ id: 'C' })
		tableD = new Table({ id: 'D' })
	})
	beforeEach(() => {
		graph = new TableGraph([tableA, tableB, tableC])
	})
	describe('getTableCombinations', () => {
		it('should return combinations for a simple graph subset [A, B]', () => {
			graph.addEdge(tableA, tableB)
			const subset = [tableA, tableB]
			const combinations = graph.getTableCombinations(subset)
			expect(combinations).toEqual([[tableA, tableB]])
		})
		it('should return all valid combinations for subset [A, B, C]', () => {
			graph.addEdge(tableA, tableB)
			graph.addEdge(tableB, tableC)
			const subset = [tableA, tableB, tableC]
			const combinations = graph.getTableCombinations(subset)
			const expectedCombinations = [
				[tableA, tableB],
				[tableA, tableB, tableC],
				[tableB, tableC],
			]
			expect(combinations).toEqual(expect.arrayContaining(expectedCombinations))
			expect(combinations.length).toBe(3)
		})
		it('should handle a subset with a single node [A]', () => {
			const subset = [tableA]
			const combinations = graph.getTableCombinations(subset)
			expect(combinations).toEqual([])
		})
		it('should return combinations for fully connected graph subset [A, B, C, D]', () => {
			graph.addEdge(tableA, tableB)
			graph.addEdge(tableB, tableC)
			graph.addEdge(tableC, tableD)
			graph.addEdge(tableD, tableA)
			const subset = [tableA, tableB, tableC, tableD]
			const combinations = graph.getTableCombinations(subset)
			const expectedCombinations = [
				[tableA, tableB],
				[tableA, tableB, tableC],
				[tableA, tableB, tableC, tableD],
				[tableA, tableD],
				[tableA, tableC, tableD],
				[tableB, tableC],
				[tableB, tableC, tableD],
				[tableC, tableD],
			]
			expect(combinations).toEqual(expect.arrayContaining(expectedCombinations))
			expect(combinations.length).toBe(expectedCombinations.length)
		})
		it('should return empty combinations when there are no neighbors', () => {
			const subset = [tableA, tableB]
			const combinations = graph.getTableCombinations(subset)
			expect(combinations).toEqual([])
		})
	})
})
describe('TableGraphBuilder', () => {
	let tableA: Table
	let tableB: Table
	let tableC: Table
	beforeEach(() => {
		tableA = new Table({ width: 2, height: 2, rowStart: 0, columnStart: 0 })
		tableB = new Table({ width: 1, height: 1, rowStart: 2, columnStart: 0 })
		tableC = new Table({ width: 1, height: 1, rowStart: 2, columnStart: 2 })
	})
	describe('createSpatialIndex method', () => {
		it('should create a spatial index for the given tables', () => {
			const spatialIndex = TableGraphBuilder.prototype['createSpatialIndex'].call(new TableGraphBuilder(), [
				tableA,
				tableB,
				tableC,
			])
			expect(spatialIndex.get('0,0')).toEqual([tableA])
			expect(spatialIndex.get('0,1')).toEqual([tableA])
			expect(spatialIndex.get('0,2')).toEqual([tableA, tableB])
			expect(spatialIndex.get('1,0')).toEqual([tableA])
			expect(spatialIndex.get('1,1')).toEqual([tableA])
			expect(spatialIndex.get('1,2')).toEqual([tableA, tableB])
			expect(spatialIndex.get('2,0')).toEqual([tableA])
			expect(spatialIndex.get('2,1')).toEqual([tableA])
			expect(spatialIndex.get('2,2')).toEqual([tableA, tableC])
			expect(spatialIndex.get('0,3')).toEqual([tableB])
			expect(spatialIndex.get('1,3')).toEqual([tableB])
			expect(spatialIndex.get('2,3')).toEqual([tableC])
			expect(spatialIndex.get('3,2')).toEqual([tableC])
			expect(spatialIndex.get('3,3')).toEqual([tableC])
		})
	})
})
