/**
 * Unit tests for diagnosticCatalog.
 * Covers lookup functions, profile severities, surface filtering, and catalog integrity.
 */

import {
    DIAGNOSTIC_CATALOG,
    getCatalogEntry,
    isValidMessageId,
    getMessageIdsForRule,
    getProfileRuleSeverities,
    isSuppressable,
    isOnSurface
} from "../../core/src/diagnostics/diagnosticCatalog.js";

describe('diagnosticCatalog', () => {
    describe('getCatalogEntry', () => {
        test('returns the entry for a known message ID', () => {
            const entry = getCatalogEntry('ACU-VAR-001');
            expect(entry).not.toBeNull();
            expect(entry.ruleId).toBe('undefinedVariable');
        });

        test('returns null for an unknown message ID', () => {
            expect(getCatalogEntry('ACU-ZZZ-999')).toBeNull();
        });
    });

    describe('isValidMessageId', () => {
        test('returns true for a registered ID', () => {
            expect(isValidMessageId('ACU-FNC-001')).toBe(true);
        });

        test('returns false for an unregistered ID', () => {
            expect(isValidMessageId('ACU-ZZZ-001')).toBe(false);
        });
    });

    describe('getMessageIdsForRule', () => {
        test('returns all IDs that share a ruleId', () => {
            // blockStructure is used by ACU-BLK-001, -002, -003
            const ids = getMessageIdsForRule('blockStructure');
            expect(ids).toContain('ACU-BLK-001');
            expect(ids).toContain('ACU-BLK-002');
            expect(ids).toContain('ACU-BLK-003');
        });

        test('returns empty array for an unknown ruleId', () => {
            expect(getMessageIdsForRule('nonExistentRule')).toEqual([]);
        });

        test('single-ID rule returns array of length 1', () => {
            const ids = getMessageIdsForRule('undefinedVariable');
            expect(ids).toEqual(['ACU-VAR-001']);
        });
    });

    describe('getProfileRuleSeverities', () => {
        test('returns the default profile for "default"', () => {
            const profile = getProfileRuleSeverities('default');
            expect(profile.blockStructure).toBe('error');
        });

        test('falls back to default profile for an unknown name', () => {
            const unknown = getProfileRuleSeverities('nonexistent');
            expect(unknown).toEqual(getProfileRuleSeverities('default'));
        });

        test('legacy profile differs from default (unsetVariable is off)', () => {
            expect(getProfileRuleSeverities('default').unsetVariable).toBe('warning');
            expect(getProfileRuleSeverities('legacy').unsetVariable).toBe('off');
        });

        test('strict profile applies stricter severity to naming rules', () => {
            expect(getProfileRuleSeverities('strict').namingPrefixScope).toBe('error');
        });
    });

    describe('isSuppressable', () => {
        test('returns true for a standard suppressable entry', () => {
            expect(isSuppressable('ACU-VAR-001')).toBe(true);
        });

        test('returns false for an unknown message ID', () => {
            expect(isSuppressable('ACU-ZZZ-999')).toBe(false);
        });
    });

    describe('isOnSurface', () => {
        test('ACU-VAR-001 is on both ide and cicd surfaces', () => {
            expect(isOnSurface('ACU-VAR-001', 'ide')).toBe(true);
            expect(isOnSurface('ACU-VAR-001', 'cicd')).toBe(true);
        });

        test('ACU-KWD-001 is on ide surface only', () => {
            expect(isOnSurface('ACU-KWD-001', 'ide')).toBe(true);
            expect(isOnSurface('ACU-KWD-001', 'cicd')).toBe(false);
        });

        test('returns true for an unknown message ID (fail-open)', () => {
            expect(isOnSurface('ACU-ZZZ-999', 'ide')).toBe(true);
        });
    });

    describe('catalog integrity', () => {
        test('every entry has the required fields: ruleId, message, paramKeys, surfaces, category', () => {
            for (const entry of Object.values(DIAGNOSTIC_CATALOG)) {
                expect(entry).toHaveProperty('ruleId');
                expect(entry).toHaveProperty('message');
                expect(entry).toHaveProperty('paramKeys');
                expect(entry).toHaveProperty('surfaces');
                expect(entry).toHaveProperty('category');
            }
        });

        test('every message template contains a {placeholder} for each declared paramKey', () => {
            for (const entry of Object.values(DIAGNOSTIC_CATALOG)) {
                for (const key of entry.paramKeys) {
                    expect(entry.message).toContain(`{${key}}`);
                }
            }
        });

        test('all message IDs match the ACU-DOMAIN-NNN format', () => {
            const idPattern = /^ACU-[A-Z]+-\d{3}$/;
            for (const id of Object.keys(DIAGNOSTIC_CATALOG)) {
                expect(id).toMatch(idPattern);
            }
        });

        test('category field is one of the three defined values', () => {
            const validCategories = new Set(['validity', 'standards', 'advisory']);
            for (const entry of Object.values(DIAGNOSTIC_CATALOG)) {
                expect(validCategories.has(entry.category)).toBe(true);
            }
        });

        test('surfaces array only contains "ide" and/or "cicd"', () => {
            const validSurfaces = new Set(['ide', 'cicd']);
            for (const entry of Object.values(DIAGNOSTIC_CATALOG)) {
                for (const surface of entry.surfaces) {
                    expect(validSurfaces.has(surface)).toBe(true);
                }
            }
        });
    });
});
