/**
 * Unit tests for suppressionParser.
 * Covers buildSuppressionMap and isSuppressed.
 */

import { buildSuppressionMap, isSuppressed } from "../../core/src/suppressionParser.js";
import { makeDocument } from "./validators/helpers.js";

describe('suppressionParser', () => {
    describe('buildSuppressionMap', () => {
        test('returns empty map for document with no suppression comments', () => {
            const doc = makeDocument(['VAR x : STRING', 'SET x = "hello"']);
            expect(buildSuppressionMap(doc).size).toBe(0);
        });

        test('maps suppression to the line immediately below', () => {
            const doc = makeDocument([
                '// @rule-ignore ACU-VAR-001',
                'SET x = undeclared'
            ]);
            const map = buildSuppressionMap(doc);
            expect(map.has(1)).toBe(true);
            expect(map.get(1).has('ACU-VAR-001')).toBe(true);
        });

        test('multiple rule IDs on one line are all captured', () => {
            const doc = makeDocument([
                '// @rule-ignore ACU-VAR-001 ACU-FNC-001',
                'some line'
            ]);
            const map = buildSuppressionMap(doc);
            expect(map.get(1)).toEqual(new Set(['ACU-VAR-001', 'ACU-FNC-001']));
        });

        test('normalises rule IDs to uppercase', () => {
            const doc = makeDocument([
                '// @rule-ignore acu-var-001',
                'some line'
            ]);
            const map = buildSuppressionMap(doc);
            expect(map.get(1).has('ACU-VAR-001')).toBe(true);
        });

        test('REASON: clause and trailing text do not produce spurious IDs', () => {
            const doc = makeDocument([
                '// @rule-ignore ACU-VAR-001 REASON: intentional legacy code',
                'some line'
            ]);
            const map = buildSuppressionMap(doc);
            expect(map.get(1).has('ACU-VAR-001')).toBe(true);
            expect(map.get(1).size).toBe(1); // REASON: is not a valid ACU-XXX-NNN token
        });

        test('suppression on the last line is ignored (no target line exists)', () => {
            const doc = makeDocument(['// @rule-ignore ACU-VAR-001']);
            expect(buildSuppressionMap(doc).size).toBe(0);
        });

        test('unrelated comment lines produce no entries', () => {
            const doc = makeDocument(['// This is a comment', 'SET x = 1']);
            expect(buildSuppressionMap(doc).size).toBe(0);
        });

        test('consecutive suppression comments each target their own following line', () => {
            const doc = makeDocument([
                '// @rule-ignore ACU-VAR-001',
                '// @rule-ignore ACU-FNC-001',
                'actual code'
            ]);
            const map = buildSuppressionMap(doc);
            // Line 0's suppression targets line 1
            expect(map.get(1).has('ACU-VAR-001')).toBe(true);
            // Line 1's suppression targets line 2
            expect(map.get(2).has('ACU-FNC-001')).toBe(true);
        });
    });

    describe('isSuppressed', () => {
        function singleEntryMap(line, ids) {
            return new Map([[line, new Set(ids)]]);
        }

        test('returns true when messageId is suppressed on the given line', () => {
            const map = singleEntryMap(5, ['ACU-VAR-001']);
            expect(isSuppressed('ACU-VAR-001', 5, map)).toBe(true);
        });

        test('returns false when lineIndex has no suppression entry', () => {
            const map = singleEntryMap(5, ['ACU-VAR-001']);
            expect(isSuppressed('ACU-VAR-001', 6, map)).toBe(false);
        });

        test('returns false when messageId is not in the suppression set for that line', () => {
            const map = singleEntryMap(5, ['ACU-FNC-001']);
            expect(isSuppressed('ACU-VAR-001', 5, map)).toBe(false);
        });

        test('is case-insensitive for the messageId argument', () => {
            const map = singleEntryMap(5, ['ACU-VAR-001']);
            expect(isSuppressed('acu-var-001', 5, map)).toBe(true);
        });

        test('returns false for an empty suppression map', () => {
            expect(isSuppressed('ACU-VAR-001', 0, new Map())).toBe(false);
        });
    });
});
