/**
 * Unit tests for interpolationValidator.
 */

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

// Execution classification helpers
function outputLine() { return { isOutput: true, isExecutable: false }; }
function execLine() { return { isOutput: false, isExecutable: true }; }

describe('validateStringInterpolation', () => {
    describe('happy path — no diagnostics', () => {
        test('returns empty array when interpolated variable is declared', () => {
            const doc = makeDocument(['>> Hello ^zName^']);
            const declaredVariables = new Map([['global:zName', { name: 'zName', type: 'STRING' }]]);
            const options = {
                executionClassificationMap: [outputLine()],
                interpolationTargetsByLine: [[{ variableName: 'zName', startPos: 9, endPos: 15, hasClosing: true, isFunctionLike: false }]]
            };
            const diags = validateStringInterpolation(doc, alwaysWarn, { declaredVariables, ...options });
            expect(diags).toHaveLength(0);
        });

        test('skips non-output lines entirely', () => {
            const doc = makeDocument(['SET zName = "^zUndefined^"']);
            const declaredVariables = new Map();
            const options = {
                executionClassificationMap: [execLine()]
            };
            const diags = validateStringInterpolation(doc, alwaysWarn, { declaredVariables, ...options });
            expect(diags).toHaveLength(0);
        });

        test('skips function-like interpolation targets', () => {
            const doc = makeDocument(['>> Result: ^MyFunc()^']);
            const declaredVariables = new Map();
            const options = {
                executionClassificationMap: [outputLine()],
                interpolationTargetsByLine: [[{ variableName: 'MyFunc', startPos: 11, endPos: 18, hasClosing: true, isFunctionLike: true }]]
            };
            const diags = validateStringInterpolation(doc, alwaysWarn, { declaredVariables, ...options });
            expect(diags).toHaveLength(0);
        });
    });

    describe('ACU-INT-001 — undefined variable in interpolation', () => {
        test('flags interpolated variable that is not declared', () => {
            const doc = makeDocument(['>> Hello ^zMissing^']);
            const declaredVariables = new Map();
            const options = {
                executionClassificationMap: [outputLine()],
                interpolationTargetsByLine: [[{ variableName: 'zMissing', startPos: 9, endPos: 18, hasClosing: true, isFunctionLike: false }]]
            };
            const diags = validateStringInterpolation(doc, alwaysWarn, { declaredVariables, ...options });
            expect(messageIds(diags)).toContain('ACU-INT-001');
        });
    });

    describe('ACU-INT-002 — case mismatch', () => {
        test('flags interpolated variable with wrong case', () => {
            const doc = makeDocument(['>> Hello ^zname^']);
            const declaredVariables = new Map([['global:zName', { name: 'zName', type: 'STRING' }]]);
            const options = {
                executionClassificationMap: [outputLine()],
                interpolationTargetsByLine: [[{ variableName: 'zname', startPos: 9, endPos: 15, hasClosing: true, isFunctionLike: false }]]
            };
            const diags = validateStringInterpolation(doc, alwaysWarn, { declaredVariables, ...options });
            expect(messageIds(diags)).toContain('ACU-INT-002');
        });
    });

    describe('ACU-INT-003 — unclosed interpolation', () => {
        test('flags interpolation without closing delimiter', () => {
            const doc = makeDocument(['>> Hello ^zName']);
            const declaredVariables = new Map([['global:zName', { name: 'zName', type: 'STRING' }]]);
            const options = {
                executionClassificationMap: [outputLine()],
                interpolationTargetsByLine: [[{ variableName: 'zName', startPos: 9, endPos: 15, hasClosing: false, isFunctionLike: false }]]
            };
            const diags = validateStringInterpolation(doc, alwaysWarn, { declaredVariables, ...options });
            expect(messageIds(diags)).toContain('ACU-INT-003');
        });
    });

    describe('severity', () => {
        test('produces no diagnostics when severity is off', () => {
            const doc = makeDocument(['>> Hello ^zMissing^']);
            const declaredVariables = new Map();
            const options = {
                executionClassificationMap: [outputLine()],
                interpolationTargetsByLine: [[{ variableName: 'zMissing', startPos: 9, endPos: 18, hasClosing: true, isFunctionLike: false }]]
            };
            const diags = validateStringInterpolation(doc, alwaysOff, { declaredVariables, ...options });
            expect(diags).toHaveLength(0);
        });
    });
});
