/**
 * Unit tests for typeKeywordCapsValidator.
 */

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

describe('validateTypeKeywordCapitalization', () => {
    describe('happy path — no diagnostics', () => {
        test('returns empty array when types are correctly capitalised in VAR declaration', () => {
            const doc = makeDocument(['VAR zName : STRING']);
            expect(validateTypeKeywordCapitalization(doc, alwaysWarn)).toHaveLength(0);
        });

        test('returns empty array for non-declaration lines', () => {
            const doc = makeDocument(['SET zName = "hello"']);
            expect(validateTypeKeywordCapitalization(doc, alwaysWarn)).toHaveLength(0);
        });

        test('returns empty array for correctly typed FUNCTION declaration', () => {
            const doc = makeDocument(['FUNCTION MyFunc(pName : STRING) : LONG']);
            expect(validateTypeKeywordCapitalization(doc, alwaysWarn)).toHaveLength(0);
        });
    });

    describe('detection — diagnostics produced', () => {
        test('flags lowercase type in VAR declaration', () => {
            const doc = makeDocument(['#HASH-OFF', 'VAR zName : string']);
            const diags = validateTypeKeywordCapitalization(doc, alwaysWarn);
            expect(diags.length).toBeGreaterThan(0);
            expect(messageIds(diags)).toContain('ACU-TYPE-001');
        });

        test('flags mixed-case type in VAR declaration', () => {
            const doc = makeDocument(['#HASH-OFF', 'VAR sCount : Short']);
            const diags = validateTypeKeywordCapitalization(doc, alwaysWarn);
            expect(messageIds(diags)).toContain('ACU-TYPE-001');
        });

        test('flags lowercase return type in FUNCTION declaration', () => {
            const doc = makeDocument(['#HASH-OFF', 'FUNCTION GetName() : string']);
            const diags = validateTypeKeywordCapitalization(doc, alwaysWarn);
            expect(messageIds(diags)).toContain('ACU-TYPE-001');
        });

        test('flags lowercase parameter type in FUNCTION declaration', () => {
            const doc = makeDocument(['#HASH-OFF', 'FUNCTION SetAge(pAge : long) : STRING']);
            const diags = validateTypeKeywordCapitalization(doc, alwaysWarn);
            expect(messageIds(diags)).toContain('ACU-TYPE-001');
        });

        test('diagnostic message contains the offending and corrected type', () => {
            const doc = makeDocument(['#HASH-OFF', 'VAR zName : string']);
            const diags = validateTypeKeywordCapitalization(doc, alwaysWarn);
            expect(diags[0].message).toMatch(/string/);
            expect(diags[0].message).toMatch(/STRING/);
        });
    });

    describe('severity', () => {
        test('produces no diagnostic when severity is off', () => {
            const doc = makeDocument(['#HASH-OFF', 'VAR zName : string']);
            const diags = validateTypeKeywordCapitalization(doc, alwaysOff);
            expect(diags).toHaveLength(0);
        });
    });

    describe('column accuracy — regression guard for currentPos bug', () => {
        test('reports correct column for wrongly-cased second param type when first param type is correct', () => {
            // FUNCTION Calc(pName : STRING, pAge : long) : SHORT
            // 0         1         2         3         4
            // 0123456789012345678901234567890123456789012345678901
            //                                      ^37 = 'long'
            // STRING is correct (no diagnostic); long is wrong (ACU-TYPE-001 at col 37).
            // Token stream: the TYPE_KEYWORD token for 'long' has char=37 exactly.
            const doc = makeDocument(['#HASH-OFF', 'FUNCTION Calc(pName : STRING, pAge : long) : SHORT']);
            const diags = validateTypeKeywordCapitalization(doc, alwaysWarn);
            expect(diags).toHaveLength(1);
            expect(diags[0].data.messageId).toBe('ACU-TYPE-001');
            expect(diags[0].range.start.character).toBe(37);
        });
    });
});
