import { Dimensions } from 'hooks/useDimensions';
import { LegendPosition } from 'types/api/dashboard/getAll';

import {
	applyEnhancedLegendStyling,
	calculateEnhancedLegendConfig,
	EnhancedLegendConfig,
} from '../enhancedLegend';

describe('Enhanced Legend Functionality', () => {
	const mockDimensions: Dimensions = {
		width: 800,
		height: 400,
	};

	const mockConfig: EnhancedLegendConfig = {
		minHeight: 46,
		maxHeight: 80,
		calculatedHeight: 60,
		showScrollbar: false,
		requiredRows: 2,
		minWidth: 150,
		maxWidth: 300,
		calculatedWidth: 200,
	};

	describe('calculateEnhancedLegendConfig', () => {
		describe('Bottom Legend Configuration', () => {
			it('should calculate correct configuration for bottom legend with few series', () => {
				const config = calculateEnhancedLegendConfig(
					mockDimensions,
					3,
					['Series A', 'Series B', 'Series C'],
					LegendPosition.BOTTOM,
				);

				expect(config.calculatedHeight).toBeGreaterThan(0);
				expect(config.minHeight).toBe(46); // lineHeight (34) + padding (12)
				expect(config.showScrollbar).toBe(false);
				expect(config.requiredRows).toBeGreaterThanOrEqual(1); // Actual behavior may vary
			});

			it('should calculate correct configuration for bottom legend with many series', () => {
				const longSeriesLabels = Array.from(
					{ length: 10 },
					(_, i) => `Very Long Series Name ${i + 1}`,
				);

				const config = calculateEnhancedLegendConfig(
					mockDimensions,
					10,
					longSeriesLabels,
					LegendPosition.BOTTOM,
				);

				expect(config.calculatedHeight).toBeGreaterThan(0);
				expect(config.showScrollbar).toBe(true);
				expect(config.requiredRows).toBeGreaterThan(2);
				expect(config.maxHeight).toBeLessThanOrEqual(80); // absoluteMaxHeight constraint
			});

			it('should handle responsive width adjustments for bottom legend', () => {
				const narrowDimensions: Dimensions = { width: 300, height: 400 };
				const wideDimensions: Dimensions = { width: 1200, height: 400 };

				const narrowConfig = calculateEnhancedLegendConfig(
					narrowDimensions,
					5,
					['Series A', 'Series B', 'Series C', 'Series D', 'Series E'],
					LegendPosition.BOTTOM,
				);

				const wideConfig = calculateEnhancedLegendConfig(
					wideDimensions,
					5,
					['Series A', 'Series B', 'Series C', 'Series D', 'Series E'],
					LegendPosition.BOTTOM,
				);

				// Narrow panels should have more rows due to less items per row
				expect(narrowConfig.requiredRows).toBeGreaterThanOrEqual(
					wideConfig.requiredRows,
				);
			});

			it('should respect maximum legend height ratio for bottom legend', () => {
				const config = calculateEnhancedLegendConfig(
					mockDimensions,
					20,
					Array.from({ length: 20 }, (_, i) => `Series ${i + 1}`),
					LegendPosition.BOTTOM,
				);

				// The implementation uses absoluteMaxHeight of 80
				expect(config.calculatedHeight).toBeLessThanOrEqual(80);
			});
		});

		describe('Right Legend Configuration', () => {
			it('should calculate correct configuration for right legend', () => {
				const config = calculateEnhancedLegendConfig(
					mockDimensions,
					5,
					['Series A', 'Series B', 'Series C', 'Series D', 'Series E'],
					LegendPosition.RIGHT,
				);

				expect(config.calculatedWidth).toBeGreaterThan(0);
				expect(config.minWidth).toBe(150);
				expect(config.maxWidth).toBeLessThanOrEqual(400);
				expect(config.calculatedWidth).toBeLessThanOrEqual(
					mockDimensions.width * 0.3,
				); // maxLegendWidthRatio
				expect(config.requiredRows).toBe(5); // Each series on its own row for right-side
			});

			it('should calculate width based on series label length for right legend', () => {
				const shortLabels = ['A', 'B', 'C'];
				const longLabels = [
					'Very Long Series Name A',
					'Very Long Series Name B',
					'Very Long Series Name C',
				];

				const shortConfig = calculateEnhancedLegendConfig(
					mockDimensions,
					3,
					shortLabels,
					LegendPosition.RIGHT,
				);

				const longConfig = calculateEnhancedLegendConfig(
					mockDimensions,
					3,
					longLabels,
					LegendPosition.RIGHT,
				);

				expect(longConfig.calculatedWidth).toBeGreaterThan(
					shortConfig.calculatedWidth ?? 0,
				);
			});

			it('should handle scrollbar for right legend with many series', () => {
				const tallDimensions: Dimensions = { width: 800, height: 200 };
				const manySeriesLabels = Array.from(
					{ length: 15 },
					(_, i) => `Series ${i + 1}`,
				);

				const config = calculateEnhancedLegendConfig(
					tallDimensions,
					15,
					manySeriesLabels,
					LegendPosition.RIGHT,
				);

				expect(config.showScrollbar).toBe(true);
				expect(config.calculatedHeight).toBeLessThanOrEqual(config.maxHeight);
			});

			it('should respect maximum width constraints for right legend', () => {
				const narrowDimensions: Dimensions = { width: 400, height: 400 };

				const config = calculateEnhancedLegendConfig(
					narrowDimensions,
					5,
					Array.from({ length: 5 }, (_, i) => `Very Long Series Name ${i + 1}`),
					LegendPosition.RIGHT,
				);

				expect(config.calculatedWidth).toBeLessThanOrEqual(
					narrowDimensions.width * 0.3,
				);
				expect(config.calculatedWidth).toBeLessThanOrEqual(400); // absoluteMaxWidth
			});
		});

		describe('Edge Cases', () => {
			it('should handle empty series labels', () => {
				const config = calculateEnhancedLegendConfig(
					mockDimensions,
					0,
					[],
					LegendPosition.BOTTOM,
				);

				expect(config.calculatedHeight).toBeGreaterThan(0);
				expect(config.requiredRows).toBe(0);
			});

			it('should handle undefined series labels', () => {
				const config = calculateEnhancedLegendConfig(
					mockDimensions,
					3,
					undefined,
					LegendPosition.BOTTOM,
				);

				expect(config.calculatedHeight).toBeGreaterThan(0);
				expect(config.requiredRows).toBe(1); // For 3 series, should be 1 row (logic only forces 2 rows when seriesCount > 3)
			});

			it('should handle very small dimensions', () => {
				const smallDimensions: Dimensions = { width: 100, height: 100 };

				const config = calculateEnhancedLegendConfig(
					smallDimensions,
					3,
					['A', 'B', 'C'],
					LegendPosition.BOTTOM,
				);

				expect(config.calculatedHeight).toBeGreaterThan(0);
				expect(config.calculatedHeight).toBeLessThanOrEqual(
					smallDimensions.height * 0.15,
				);
			});
		});
	});

	describe('applyEnhancedLegendStyling', () => {
		let mockLegendElement: HTMLElement;

		beforeEach(() => {
			mockLegendElement = document.createElement('div');
			mockLegendElement.className = 'u-legend';
		});

		describe('Bottom Legend Styling', () => {
			it('should apply correct classes for bottom legend', () => {
				applyEnhancedLegendStyling(
					mockLegendElement,
					mockConfig,
					2,
					LegendPosition.BOTTOM,
				);

				expect(mockLegendElement.classList.contains('u-legend-enhanced')).toBe(
					true,
				);
				expect(mockLegendElement.classList.contains('u-legend-bottom')).toBe(true);
				expect(mockLegendElement.classList.contains('u-legend-right')).toBe(false);
				expect(mockLegendElement.classList.contains('u-legend-multi-line')).toBe(
					true,
				);
			});

			it('should apply single-line class for single row bottom legend', () => {
				applyEnhancedLegendStyling(
					mockLegendElement,
					mockConfig,
					1,
					LegendPosition.BOTTOM,
				);

				expect(mockLegendElement.classList.contains('u-legend-single-line')).toBe(
					true,
				);
				expect(mockLegendElement.classList.contains('u-legend-multi-line')).toBe(
					false,
				);
			});

			it('should set correct height styles for bottom legend', () => {
				applyEnhancedLegendStyling(
					mockLegendElement,
					mockConfig,
					2,
					LegendPosition.BOTTOM,
				);

				expect(mockLegendElement.style.height).toBe('60px');
				expect(mockLegendElement.style.minHeight).toBe('46px');
				expect(mockLegendElement.style.maxHeight).toBe('80px');
				expect(mockLegendElement.style.width).toBe('');
			});
		});

		describe('Right Legend Styling', () => {
			it('should apply correct classes for right legend', () => {
				applyEnhancedLegendStyling(
					mockLegendElement,
					mockConfig,
					5,
					LegendPosition.RIGHT,
				);

				expect(mockLegendElement.classList.contains('u-legend-enhanced')).toBe(
					true,
				);
				expect(mockLegendElement.classList.contains('u-legend-right')).toBe(true);
				expect(mockLegendElement.classList.contains('u-legend-bottom')).toBe(false);
				expect(mockLegendElement.classList.contains('u-legend-right-aligned')).toBe(
					true,
				);
			});

			it('should set correct width and height styles for right legend', () => {
				applyEnhancedLegendStyling(
					mockLegendElement,
					mockConfig,
					5,
					LegendPosition.RIGHT,
				);

				expect(mockLegendElement.style.width).toBe('200px');
				expect(mockLegendElement.style.minWidth).toBe('150px');
				expect(mockLegendElement.style.maxWidth).toBe('300px');
				expect(mockLegendElement.style.height).toBe('60px');
				expect(mockLegendElement.style.minHeight).toBe('46px');
				expect(mockLegendElement.style.maxHeight).toBe('80px');
			});
		});

		describe('Scrollbar Styling', () => {
			it('should add scrollable class when scrollbar is needed', () => {
				const scrollableConfig = { ...mockConfig, showScrollbar: true };

				applyEnhancedLegendStyling(
					mockLegendElement,
					scrollableConfig,
					5,
					LegendPosition.BOTTOM,
				);

				expect(mockLegendElement.classList.contains('u-legend-scrollable')).toBe(
					true,
				);
			});

			it('should remove scrollable class when scrollbar is not needed', () => {
				mockLegendElement.classList.add('u-legend-scrollable');

				applyEnhancedLegendStyling(
					mockLegendElement,
					mockConfig,
					2,
					LegendPosition.BOTTOM,
				);

				expect(mockLegendElement.classList.contains('u-legend-scrollable')).toBe(
					false,
				);
			});
		});
	});

	describe('Legend Responsive Distribution', () => {
		describe('Items per row calculation', () => {
			it('should calculate correct items per row for different panel widths', () => {
				const testCases = [
					{ width: 300, expectedMaxItemsPerRow: 2 },
					{ width: 600, expectedMaxItemsPerRow: 4 },
					{ width: 1200, expectedMaxItemsPerRow: 8 },
				];

				testCases.forEach(({ width, expectedMaxItemsPerRow }) => {
					const dimensions: Dimensions = { width, height: 400 };
					const config = calculateEnhancedLegendConfig(
						dimensions,
						expectedMaxItemsPerRow + 2, // More series than can fit in one row
						Array.from(
							{ length: expectedMaxItemsPerRow + 2 },
							(_, i) => `Series ${i + 1}`,
						),
						LegendPosition.BOTTOM,
					);

					expect(config.requiredRows).toBeGreaterThan(1);
				});
			});

			it('should handle very long series names by adjusting layout', () => {
				const longSeriesNames = [
					'Very Long Series Name That Might Not Fit',
					'Another Extremely Long Series Name',
					'Yet Another Very Long Series Name',
				];

				const config = calculateEnhancedLegendConfig(
					{ width: 400, height: 300 },
					3,
					longSeriesNames,
					LegendPosition.BOTTOM,
				);

				// Should require more rows due to long names
				expect(config.requiredRows).toBeGreaterThanOrEqual(2);
			});
		});

		describe('Dynamic height adjustment', () => {
			it('should adjust height based on number of required rows', () => {
				const fewSeries = calculateEnhancedLegendConfig(
					mockDimensions,
					2,
					['A', 'B'],
					LegendPosition.BOTTOM,
				);

				const manySeries = calculateEnhancedLegendConfig(
					mockDimensions,
					10,
					Array.from({ length: 10 }, (_, i) => `Series ${i + 1}`),
					LegendPosition.BOTTOM,
				);

				expect(manySeries.calculatedHeight).toBeGreaterThan(
					fewSeries.calculatedHeight,
				);
			});
		});
	});

	describe('Legend Position Integration', () => {
		it('should handle legend position changes correctly', () => {
			const seriesLabels = [
				'Series A',
				'Series B',
				'Series C',
				'Series D',
				'Series E',
			];

			const bottomConfig = calculateEnhancedLegendConfig(
				mockDimensions,
				5,
				seriesLabels,
				LegendPosition.BOTTOM,
			);

			const rightConfig = calculateEnhancedLegendConfig(
				mockDimensions,
				5,
				seriesLabels,
				LegendPosition.RIGHT,
			);

			// Bottom legend should have width constraints, right legend should have height constraints
			expect(bottomConfig.calculatedWidth).toBeUndefined();
			expect(rightConfig.calculatedWidth).toBeDefined();
			expect(rightConfig.calculatedWidth).toBeGreaterThan(0);
		});

		it('should apply different styling based on legend position', () => {
			const mockElement = document.createElement('div');

			// Test bottom positioning
			applyEnhancedLegendStyling(
				mockElement,
				mockConfig,
				3,
				LegendPosition.BOTTOM,
			);

			const hasBottomClasses = mockElement.classList.contains('u-legend-bottom');

			// Reset element
			mockElement.className = 'u-legend';

			// Test right positioning
			applyEnhancedLegendStyling(mockElement, mockConfig, 3, LegendPosition.RIGHT);

			const hasRightClasses = mockElement.classList.contains('u-legend-right');

			expect(hasBottomClasses).toBe(true);
			expect(hasRightClasses).toBe(true);
		});
	});

	describe('Performance and Edge Cases', () => {
		it('should handle large number of series efficiently', () => {
			const startTime = Date.now();

			const largeSeries = Array.from({ length: 100 }, (_, i) => `Series ${i + 1}`);
			const config = calculateEnhancedLegendConfig(
				mockDimensions,
				100,
				largeSeries,
				LegendPosition.BOTTOM,
			);

			const endTime = Date.now();
			const executionTime = endTime - startTime;

			expect(executionTime).toBeLessThan(100); // Should complete within 100ms
			expect(config.calculatedHeight).toBeGreaterThan(0);
			expect(config.showScrollbar).toBe(true);
		});

		it('should handle zero dimensions gracefully', () => {
			const zeroDimensions: Dimensions = { width: 0, height: 0 };

			const config = calculateEnhancedLegendConfig(
				zeroDimensions,
				3,
				['A', 'B', 'C'],
				LegendPosition.BOTTOM,
			);

			expect(config.calculatedHeight).toBeGreaterThan(0);
			expect(config.minHeight).toBeGreaterThan(0);
		});

		it('should handle negative dimensions gracefully', () => {
			const negativeDimensions: Dimensions = { width: -100, height: -100 };

			const config = calculateEnhancedLegendConfig(
				negativeDimensions,
				3,
				['A', 'B', 'C'],
				LegendPosition.BOTTOM,
			);

			expect(config.calculatedHeight).toBeGreaterThan(0);
			expect(config.minHeight).toBeGreaterThan(0);
		});
	});
});
