import { describe, it, expect } from 'vitest';
import { SCHOOL_LEVELS, SCHOOL_LEVEL_OPTIONS } from '$lib/constants/schoolLevels';
import type { SchoolLevel } from '$lib/constants/schoolLevels';

/**
 * Unit tests for the school levels constants (schoolLevels.ts).
 *
 * Verifies the complete list of levels matches the Education Nationale
 * reference, the correct ordering from CP to Terminale, and the
 * SCHOOL_LEVEL_OPTIONS formatting for select/dropdown components.
 */

describe('schoolLevels constants', () => {
	// ==========================================================================
	// SCHOOL_LEVELS
	// ==========================================================================
	describe('SCHOOL_LEVELS', () => {
		it('should contain exactly 12 levels', () => {
			expect(SCHOOL_LEVELS).toHaveLength(12);
		});

		it('should contain all primary school levels (CP to CM2)', () => {
			expect(SCHOOL_LEVELS).toContain('CP');
			expect(SCHOOL_LEVELS).toContain('CE1');
			expect(SCHOOL_LEVELS).toContain('CE2');
			expect(SCHOOL_LEVELS).toContain('CM1');
			expect(SCHOOL_LEVELS).toContain('CM2');
		});

		it('should contain all college levels (6eme to 3eme)', () => {
			expect(SCHOOL_LEVELS).toContain('6ème');
			expect(SCHOOL_LEVELS).toContain('5ème');
			expect(SCHOOL_LEVELS).toContain('4ème');
			expect(SCHOOL_LEVELS).toContain('3ème');
		});

		it('should contain all lycee levels (2nde, 1ere, Terminale)', () => {
			expect(SCHOOL_LEVELS).toContain('2nde');
			expect(SCHOOL_LEVELS).toContain('1ère');
			expect(SCHOOL_LEVELS).toContain('Terminale');
		});

		it('should be ordered from CP to Terminale', () => {
			const expectedOrder = [
				'CP',
				'CE1',
				'CE2',
				'CM1',
				'CM2',
				'6ème',
				'5ème',
				'4ème',
				'3ème',
				'2nde',
				'1ère',
				'Terminale'
			];
			expect([...SCHOOL_LEVELS]).toEqual(expectedOrder);
		});

		it('should be a readonly array (as const)', () => {
			// TypeScript ensures this at compile time, but we verify the runtime
			// values are stable by checking identity
			const firstRead = SCHOOL_LEVELS[0];
			const secondRead = SCHOOL_LEVELS[0];
			expect(firstRead).toBe(secondRead);
			expect(firstRead).toBe('CP');
		});
	});

	// ==========================================================================
	// SchoolLevel type (compile-time check via runtime usage)
	// ==========================================================================
	describe('SchoolLevel type', () => {
		it('should accept valid school level values', () => {
			// This is a compile-time check expressed as a runtime test
			const level: SchoolLevel = 'CP';
			expect(level).toBe('CP');

			const another: SchoolLevel = 'Terminale';
			expect(another).toBe('Terminale');
		});
	});

	// ==========================================================================
	// SCHOOL_LEVEL_OPTIONS
	// ==========================================================================
	describe('SCHOOL_LEVEL_OPTIONS', () => {
		it('should have the same number of options as SCHOOL_LEVELS', () => {
			expect(SCHOOL_LEVEL_OPTIONS).toHaveLength(SCHOOL_LEVELS.length);
		});

		it('should have value and label properties for each option', () => {
			for (const option of SCHOOL_LEVEL_OPTIONS) {
				expect(option).toHaveProperty('value');
				expect(option).toHaveProperty('label');
			}
		});

		it('should use the level as both value and label', () => {
			for (let i = 0; i < SCHOOL_LEVELS.length; i++) {
				expect(SCHOOL_LEVEL_OPTIONS[i]!.value).toBe(SCHOOL_LEVELS[i]);
				expect(SCHOOL_LEVEL_OPTIONS[i]!.label).toBe(SCHOOL_LEVELS[i]);
			}
		});

		it('should format first option correctly (CP)', () => {
			expect(SCHOOL_LEVEL_OPTIONS[0]).toEqual({ value: 'CP', label: 'CP' });
		});

		it('should format last option correctly (Terminale)', () => {
			const last = SCHOOL_LEVEL_OPTIONS[SCHOOL_LEVEL_OPTIONS.length - 1];
			expect(last).toEqual({ value: 'Terminale', label: 'Terminale' });
		});

		it('should format accented levels correctly', () => {
			const sixieme = SCHOOL_LEVEL_OPTIONS.find((opt) => opt.value === '6ème');
			expect(sixieme).toEqual({ value: '6ème', label: '6ème' });

			const premiere = SCHOOL_LEVEL_OPTIONS.find((opt) => opt.value === '1ère');
			expect(premiere).toEqual({ value: '1ère', label: '1ère' });
		});

		it('should preserve the order from SCHOOL_LEVELS', () => {
			const optionValues = SCHOOL_LEVEL_OPTIONS.map((opt) => opt.value);
			expect(optionValues).toEqual([...SCHOOL_LEVELS]);
		});
	});
});
