/**
 * Unit tests for keywordCapsValidator.
 */

import { validateKeywordCapitalization } from "../../../core/src/validators/keywordCapsValidator.js";
import { makeDocument, alwaysWarn, alwaysOff, messageIds } from "./helpers.js";

describe('validateKeywordCapitalization', () => {
    describe('happy path — no diagnostics', () => {
        test('returns empty array for properly capitalised keywords', () => {
            const doc = makeDocument(['IF x = 1', '    OUTPUT "hello"', 'ENDIF']);
            expect(validateKeywordCapitalization(doc, alwaysWarn)).toHaveLength(0);
        });

        test('returns empty array for empty document', () => {
            const doc = makeDocument(['']);
            expect(validateKeywordCapitalization(doc, alwaysWarn)).toHaveLength(0);
        });

        test('does not flag keywords inside string literals', () => {
            const doc = makeDocument(['OUTPUT "if you do this"']);
            expect(validateKeywordCapitalization(doc, alwaysWarn)).toHaveLength(0);
        });

        test('does not flag keywords in comments', () => {
            const doc = makeDocument(['// if this is a comment']);
            expect(validateKeywordCapitalization(doc, alwaysWarn)).toHaveLength(0);
        });
    });

    describe('detection — diagnostics produced', () => {
        test('flags lowercase keyword', () => {
            const doc = makeDocument(['#HASH-OFF', 'if x = 1']);
            const diags = validateKeywordCapitalization(doc, alwaysWarn);
            expect(diags.length).toBeGreaterThan(0);
            expect(messageIds(diags)).toContain('ACU-KWD-001');
        });

        test('flags mixed-case keyword', () => {
            const doc = makeDocument(['#HASH-OFF', 'While x > 0']);
            const diags = validateKeywordCapitalization(doc, alwaysWarn);
            expect(messageIds(diags)).toContain('ACU-KWD-001');
        });

        test('diagnostic message contains the offending keyword', () => {
            const doc = makeDocument(['#HASH-OFF', 'endif']);
            const diags = validateKeywordCapitalization(doc, alwaysWarn);
            expect(diags[0].message).toMatch(/endif/i);
            expect(diags[0].message).toMatch(/ENDIF/);
        });

        test('flags multiple keywords on same line', () => {
            const doc = makeDocument(['#HASH-OFF', 'if x = 1 and y = 2']);
            const diags = validateKeywordCapitalization(doc, alwaysWarn);
            const ids = messageIds(diags);
            expect(ids.every((id) => id === 'ACU-KWD-001')).toBe(true);
            expect(ids.length).toBeGreaterThanOrEqual(2);
        });
    });

    describe('severity', () => {
        test('returns null diagnostic when severity is off', () => {
            const doc = makeDocument(['#HASH-OFF', 'if x = 1']);
            const diags = validateKeywordCapitalization(doc, alwaysOff);
            expect(diags).toHaveLength(0);
        });
    });

    describe('executionClassificationMap option', () => {
        test('skips output lines when classification map is provided', () => {
            const doc = makeDocument(['>> if this is output text']);
            const executionClassificationMap = [{ isOutput: true, isExecutable: false }];
            const diags = validateKeywordCapitalization(doc, alwaysWarn, { executionClassificationMap });
            expect(diags).toHaveLength(0);
        });

        test('skips non-executable lines when classification map is provided', () => {
            const doc = makeDocument(['// if this is a comment line']);
            const executionClassificationMap = [{ isOutput: false, isExecutable: false }];
            const diags = validateKeywordCapitalization(doc, alwaysWarn, { executionClassificationMap });
            expect(diags).toHaveLength(0);
        });
    });
});
