// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { parseGrammarRules } from "../src/grammarRuleParser.js";
import { escapedSpaces, spaces } from "./testUtils.js";

const testParamGrammarRules = (fileName: string, content: string) =>
    parseGrammarRules(fileName, content, false).definitions;

describe("Grammar Rule Parser", () => {
    describe("Basic Rule Definitions", () => {
        it("a simple rule with string expression", () => {
            const grammar = "<greeting> = hello world;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result).toEqual([
                {
                    name: "greeting",
                    rules: [
                        {
                            expressions: [
                                {
                                    type: "string",
                                    value: ["hello", "world"],
                                },
                            ],
                        },
                    ],
                },
            ]);
        });

        it("a rule with multiple alternatives", () => {
            const grammar = "<greeting> = hello | hi | hey;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result).toHaveLength(1);
            expect(result[0].name).toBe("greeting");
            expect(result[0].rules).toHaveLength(3);
            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello"],
            });
            expect(result[0].rules[1].expressions[0]).toEqual({
                type: "string",
                value: ["hi"],
            });
            expect(result[0].rules[2].expressions[0]).toEqual({
                type: "string",
                value: ["hey"],
            });
        });

        it("a rule with value mapping", () => {
            const grammar = '<greeting> = hello -> "greeting";';
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result).toHaveLength(1);
            expect(result[0].rules[0].value).toEqual({
                type: "literal",
                value: "greeting",
            });
        });

        it("multiple rule definitions", () => {
            const grammar = `
                <greeting> = hello;
                <farewell> = goodbye;
            `;
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result).toHaveLength(2);
            expect(result[0].name).toBe("greeting");
            expect(result[1].name).toBe("farewell");
        });

        it("rule with rule reference", () => {
            const grammar = "<sentence> = <greeting> world;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions).toHaveLength(2);
            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "ruleReference",
                name: "greeting",
            });
            expect(result[0].rules[0].expressions[1]).toEqual({
                type: "string",
                value: ["world"],
            });
        });
    });

    describe("Expression Parsing", () => {
        it("variable expressions with default type", () => {
            const grammar = "<rule> = $(name);";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "variable",
                name: "name",
                refName: "string",
                ruleReference: false,
            });
        });

        it("variable expressions with specified type", () => {
            const grammar = "<rule> = $(count:number);";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "variable",
                name: "count",
                refName: "number",
                ruleReference: false,
            });
        });

        it("variable expressions with rule reference", () => {
            const grammar = "<rule> = $(item:<ItemType>);";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "variable",
                name: "item",
                refName: "ItemType",
                ruleReference: true,
            });
        });

        it("variable expressions - optional", () => {
            const grammar = "<rule> = $(item:<ItemType>)?;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "variable",
                name: "item",
                refName: "ItemType",
                ruleReference: true,
                optional: true,
            });
        });

        it("group expressions", () => {
            const grammar = "<rule> = (hello | hi) world;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions).toHaveLength(2);
            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "rules",
                rules: [
                    {
                        expressions: [{ type: "string", value: ["hello"] }],
                        value: undefined,
                    },
                    {
                        expressions: [{ type: "string", value: ["hi"] }],
                        value: undefined,
                    },
                ],
            });
        });

        it("optional group expressions", () => {
            const grammar = "<rule> = (please)? help;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "rules",
                rules: [
                    {
                        expressions: [{ type: "string", value: ["please"] }],
                        value: undefined,
                    },
                ],
                optional: true,
            });
        });

        it("complex expressions with multiple components", () => {
            const grammar = "<rule> = $(action) the <object> $(adverb:string);";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions).toHaveLength(4);
            expect(result[0].rules[0].expressions[0].type).toBe("variable");
            expect(result[0].rules[0].expressions[1]).toEqual({
                type: "string",
                value: ["the"],
            });
            expect(result[0].rules[0].expressions[2].type).toBe(
                "ruleReference",
            );
            expect(result[0].rules[0].expressions[3].type).toBe("variable");
        });

        it("should handle escaped characters in string expressions", () => {
            const grammar = "<rule> = hello\\0world;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello\0world"],
            });
        });
    });

    describe("Value Parsing", () => {
        it("boolean literal values", () => {
            const grammar1 = "<rule> = test -> true;";
            const grammar2 = "<rule> = test -> false;";

            const result1 = testParamGrammarRules("test.agr", grammar1);
            const result2 = testParamGrammarRules("test.agr", grammar2);

            expect(result1[0].rules[0].value).toEqual({
                type: "literal",
                value: true,
            });
            expect(result2[0].rules[0].value).toEqual({
                type: "literal",
                value: false,
            });
        });

        it("float literal values", () => {
            const grammar = "<rule> = test -> 42.5;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "literal",
                value: 42.5,
            });
        });

        it("integer literal values", () => {
            const grammar = "<rule> = test -> 12;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "literal",
                value: 12,
            });
        });

        it("integer hex literal values", () => {
            const grammar = "<rule> = test -> 0xC;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "literal",
                value: 12,
            });
        });

        it("integer oct literal values", () => {
            const grammar = "<rule> = test -> 0o14;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "literal",
                value: 12,
            });
        });

        it("integer binary literal values", () => {
            const grammar = "<rule> = test -> 0b1100;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "literal",
                value: 12,
            });
        });

        it("string literal values", () => {
            const grammar1 = '<rule> = test -> "hello world";';
            const grammar2 = "<rule> = test -> 'hello world';";

            const result1 = testParamGrammarRules("test.agr", grammar1);
            const result2 = testParamGrammarRules("test.agr", grammar2);

            expect(result1[0].rules[0].value).toEqual({
                type: "literal",
                value: "hello world",
            });
            expect(result2[0].rules[0].value).toEqual({
                type: "literal",
                value: "hello world",
            });
        });

        it("string values with escape sequences", () => {
            const grammar = '<rule> = test -> "hello\\tworld\\n";';
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "literal",
                value: "hello\tworld\n",
            });
        });

        it("array values", () => {
            const grammar = '<rule> = test -> [1, "hello", true];';
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "array",
                value: [
                    { type: "literal", value: 1 },
                    { type: "literal", value: "hello" },
                    { type: "literal", value: true },
                ],
            });
        });

        it("empty array values", () => {
            const grammar = "<rule> = test -> [];";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "array",
                value: [],
            });
        });

        it("object values", () => {
            const grammar = '<rule> = test -> {type: "greeting", count: 1};';
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "object",
                value: {
                    type: { type: "literal", value: "greeting" },
                    count: { type: "literal", value: 1 },
                },
            });
        });

        it("empty object values", () => {
            const grammar = "<rule> = test -> {};";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "object",
                value: {},
            });
        });

        it("object values with single quote properties", () => {
            const grammar =
                "<rule> = test -> {'type': \"greeting\", 'count': 1};";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "object",
                value: {
                    type: { type: "literal", value: "greeting" },
                    count: { type: "literal", value: 1 },
                },
            });
        });

        it("object values with double quote properties", () => {
            const grammar =
                '<rule> = test -> {"type": "greeting", "count": 1};';
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "object",
                value: {
                    type: { type: "literal", value: "greeting" },
                    count: { type: "literal", value: 1 },
                },
            });
        });

        it("variable reference values", () => {
            const grammar = "<rule> = $(name) -> name;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "variable",
                name: "name",
            });
        });

        it("nested object and array values", () => {
            const grammar =
                "<rule> = test -> {items: [1, 2], meta: {count: 2}};";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "object",
                value: {
                    items: {
                        type: "array",
                        value: [
                            { type: "literal", value: 1 },
                            { type: "literal", value: 2 },
                        ],
                    },
                    meta: {
                        type: "object",
                        value: {
                            count: { type: "literal", value: 2 },
                        },
                    },
                },
            });
        });

        it("should handle nested groups and complex expressions", () => {
            const grammar = `
                <complex> = (please)? ($(action) | do) (the)? $(object) ($(adverb))? -> {
                    politeness,
                    actions: [action, "execute"],
                    target: {
                        name: object,
                        metadata: {
                            hasArticle: true,
                            modifier: adverb
                        }
                    }
                };
            `;

            const result = testParamGrammarRules("nested.agr", grammar);

            expect(result).toEqual([
                {
                    name: "complex",
                    rules: [
                        {
                            expressions: [
                                {
                                    type: "rules",
                                    rules: [
                                        {
                                            expressions: [
                                                {
                                                    type: "string",
                                                    value: ["please"],
                                                },
                                            ],
                                        },
                                    ],
                                    optional: true,
                                },
                                {
                                    type: "rules",
                                    rules: [
                                        {
                                            expressions: [
                                                {
                                                    type: "variable",
                                                    name: "action",
                                                    refName: "string",
                                                    ruleReference: false,
                                                },
                                            ],
                                        },
                                        {
                                            expressions: [
                                                {
                                                    type: "string",
                                                    value: ["do"],
                                                },
                                            ],
                                        },
                                    ],
                                },
                                {
                                    type: "rules",
                                    rules: [
                                        {
                                            expressions: [
                                                {
                                                    type: "string",
                                                    value: ["the"],
                                                },
                                            ],
                                        },
                                    ],
                                    optional: true,
                                },
                                {
                                    type: "variable",
                                    name: "object",
                                    refName: "string",
                                    ruleReference: false,
                                },
                                {
                                    type: "rules",
                                    rules: [
                                        {
                                            expressions: [
                                                {
                                                    type: "variable",
                                                    name: "adverb",
                                                    refName: "string",
                                                    ruleReference: false,
                                                },
                                            ],
                                        },
                                    ],
                                    optional: true,
                                },
                            ],
                            value: {
                                type: "object",
                                value: {
                                    politeness: null,
                                    actions: {
                                        type: "array",
                                        value: [
                                            {
                                                type: "variable",
                                                name: "action",
                                            },
                                            {
                                                type: "literal",
                                                value: "execute",
                                            },
                                        ],
                                    },
                                    target: {
                                        type: "object",
                                        value: {
                                            name: {
                                                type: "variable",
                                                name: "object",
                                            },
                                            metadata: {
                                                type: "object",
                                                value: {
                                                    hasArticle: {
                                                        type: "literal",
                                                        value: true,
                                                    },
                                                    modifier: {
                                                        type: "variable",
                                                        name: "adverb",
                                                    },
                                                },
                                            },
                                        },
                                    },
                                },
                            },
                        },
                    ],
                },
            ]);
        });

        it("grammar with unicode and special characters", () => {
            const grammar = `
                <unicode> = café \\u00E9 -> "café";
                <special> = hello\\tworld\\n -> "formatted";
                <escaped> = \\| \\( \\) -> "escaped";
            `;

            const result = testParamGrammarRules("unicode.agr", grammar);

            expect(result).toHaveLength(3);
            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["café", "é"],
            });
            expect(result[1].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello\tworld\n"],
            });
            expect(result[2].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["|", "(", ")"],
            });
        });
    });

    describe("Whitespace and Comments", () => {
        it("should handle collapse whitespace between tokens", () => {
            const spaces =
                "  \t\v\f\u00a0\ufeff\n\r\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000";
            const grammar = `${spaces}<greeting>${spaces}=${spaces}hello${spaces}world${spaces}->${spaces}true${spaces};`;
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result).toEqual([
                {
                    name: "greeting",
                    rules: [
                        {
                            expressions: [
                                {
                                    type: "string",
                                    value: ["hello", "world"],
                                },
                            ],
                            value: {
                                type: "literal",
                                value: true,
                            },
                        },
                    ],
                },
            ]);
        });

        it("should keep escaped whitespace in expression", () => {
            const grammar = `<greeting>=${escapedSpaces}hello${escapedSpaces}world${escapedSpaces}->true;`;
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result).toEqual([
                {
                    name: "greeting",
                    rules: [
                        {
                            expressions: [
                                {
                                    type: "string",
                                    value: [
                                        `${spaces}hello${spaces}world${spaces}`,
                                    ],
                                },
                            ],
                            value: {
                                type: "literal",
                                value: true,
                            },
                        },
                    ],
                },
            ]);
        });

        it("should handle single-line comments", () => {
            const grammar = `
                // This is a greeting rule
                <greeting> = hello; // End of line comment
                // Another comment
            `;
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result).toHaveLength(1);
            expect(result[0].name).toBe("greeting");
        });

        it("should handle multi-line comments", () => {
            const grammar = `
                /*
                 * This is a multi-line comment
                 * describing the greeting rule
                 */
                <greeting> = hello /* inline comment */ world;
            `;
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello", "world"],
            });
        });

        it("should handle mixed whitespace types", () => {
            const grammar = "<rule>\t=\r\nhello\n\t world;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello", "world"],
            });
        });

        it("should collapse multiple whitespace in strings to single space", () => {
            const grammar = "<rule> = hello     world\t\t\ttest;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello", "world", "test"],
            });
        });

        it("should handle comments in values", () => {
            const grammar = `
                <rule> = test -> {
                    // Property comment
                    type: "greeting", /* inline */
                    count: 1
                };
            `;
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].value).toEqual({
                type: "object",
                value: {
                    type: { type: "literal", value: "greeting" },
                    count: { type: "literal", value: 1 },
                },
            });
        });

        it("should treat // comment with no preceding space as flex space in string expression", () => {
            const grammar = "<rule> = hello//comment\nworld;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello", "world"],
            });
        });

        it("should treat /* */ comment with no preceding space as flex space in string expression", () => {
            const grammar = "<rule> = hello/*comment*/world;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello", "world"],
            });
        });

        it("should collapse multiple consecutive comments to a single flex space", () => {
            const grammar = "<rule> = hello//c1\n//c2\nworld;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello", "world"],
            });
        });

        it("should collapse mixed adjacent comment styles to a single flex space", () => {
            const grammar = "<rule> = hello//line\n/*block*/world;";
            const result = testParamGrammarRules("test.agr", grammar);

            expect(result[0].rules[0].expressions[0]).toEqual({
                type: "string",
                value: ["hello", "world"],
            });
        });
    });

    describe("Error Handling", () => {
        it("should throw error for missing rule terminator", () => {
            const grammar = "<greeting> = hello";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "';' expected",
            );
        });

        it("should throw error for malformed rule name", () => {
            const grammar = "greeting = hello;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Expected rule definition, 'import' statement, or 'entity' declaration",
            );
        });

        it("should throw error for missing equals sign", () => {
            const grammar = "<greeting> hello;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "'=' expected",
            );
        });

        it("should throw error for unterminated string literal", () => {
            const grammar = '<rule> = test -> "unterminated';
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Unterminated string literal",
            );
        });

        it("should throw error for unterminated variable", () => {
            const grammar = "<rule> = $(name;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "')' expected",
            );
        });

        it("should throw error for unterminated group", () => {
            const grammar = "<rule> = (hello;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "')' expected",
            );
        });

        it("should throw error for invalid escape sequence", () => {
            const grammar = '<rule> = test -> "invalid\\';
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Missing escaped character.",
            );
        });

        it("should throw error for invalid hex escape", () => {
            const grammar = '<rule> = test -> "\\xZZ";';
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Invalid hex escape sequence",
            );
        });

        it("should throw error for invalid unicode escape", () => {
            const grammar = '<rule> = test -> "\\uZZZZ";';
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Invalid Unicode escape sequence",
            );
        });

        it("should throw error for unterminated array", () => {
            const grammar = "<rule> = test -> [1, 2";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Unexpected end of file in array value",
            );
        });

        it("should throw error for unterminated object", () => {
            const grammar = '<rule> = test -> {type: "test"';
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Unexpected end of file in object value",
            );
        });

        it("should throw error for missing colon in object", () => {
            const grammar = '<rule> = test -> {type "test"};';
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "':' expected",
            );
        });

        it("should throw error for invalid number", () => {
            const grammar = "<rule> = test -> 1abc;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Invalid literal",
            );
        });

        it("should throw error for infinity values", () => {
            const grammar = "<rule> = test -> Infinity;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Infinity values are not allowed",
            );
        });

        it("should throw error for unescaped special characters", () => {
            const grammar = "<rule> = hello-world;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Special character needs to be escaped",
            );
        });

        it("should throw error for empty expression", () => {
            const grammar = "<rule> = ;";
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                "Empty expression",
            );
        });

        it("should include line and column information in errors", () => {
            const grammar = `
                <valid> = hello;
                invalid = world;
            `;
            expect(() => testParamGrammarRules("test.agr", grammar)).toThrow(
                /test\.agr:\d+:\d+:/,
            );
        });
    });

    describe("Complex Integration", () => {
        it("should handle deeply nested value structures", () => {
            const grammar = `
                <nested> = test -> {
                    config: {
                        settings: [
                            {name: "debug", value: true},
                            {name: "timeout", value: 30}
                        ],
                        metadata: {
                            version: "1.0",
                            features: ["async", "cache"]
                        }
                    },
                    variables: [param1, param2]
                };
            `;

            const result = testParamGrammarRules("deeply-nested.agr", grammar);

            const value = result[0].rules[0].value as any;
            expect(value.type).toBe("object");
            expect(value.value.config.type).toBe("object");
            expect(value.value.config.value.settings.type).toBe("array");
            expect(value.value.variables.value).toHaveLength(2);
        });

        it("real-world conversation patterns", () => {
            const grammar = `
                // Weather queries
                <weather> = (what's | what is) the weather (like)? (in $(location))? -> {
                    intent: "weather.query",
                    location,
                    type: "current"
                };

                // Calendar operations
                <calendar> = (schedule | book) (a)? $(event) (for | on) $(date) (at $(time))? -> {
                    intent: "calendar.create",
                    event: {
                        title: event,
                        date,
                        time
                    }
                };

                // Music control
                <music> = (play | start) $(song)? (by $(artist))? -> {
                    intent: "music.play",
                    query: {
                        song,
                        artist
                    },
                    shuffle: false
                };
            `;

            const result = testParamGrammarRules("conversation.agr", grammar);

            expect(result).toHaveLength(3);

            // Verify each intent has proper structure
            result.forEach((rule) => {
                expect(rule.name).toMatch(/^(weather|calendar|music)$/);
                expect(rule.rules[0].value).toBeDefined();
                const value = rule.rules[0].value as any;
                expect(value.type).toBe("object");
                expect(value.value.intent).toBeDefined();
            });
        });
    });

    describe("Import Statements", () => {
        it("parse granular import statement", () => {
            const grammar = 'import { Name1, Name2 } from "file.agr";';
            const result = parseGrammarRules("test.agr", grammar, false);

            expect(result.imports).toHaveLength(1);
            expect(result.imports[0].names).toEqual(["Name1", "Name2"]);
            expect(result.imports[0].source).toBe("file.agr");
        });

        it("parse wildcard import statement", () => {
            const grammar = 'import * from "file.agr";';
            const result = parseGrammarRules("test.agr", grammar, false);

            expect(result.imports).toHaveLength(1);
            expect(result.imports[0].names).toBe("*");
            expect(result.imports[0].source).toBe("file.agr");
        });

        it("parse multiple import statements", () => {
            const grammar = `
                import { Action1, Action2 } from "actions.agr";
                import * from "types.ts";
                import { Helper } from "helpers.agr";
            `;
            const result = parseGrammarRules("test.agr", grammar, false);

            expect(result.imports).toHaveLength(3);
            expect(result.imports[0].names).toEqual(["Action1", "Action2"]);
            expect(result.imports[0].source).toBe("actions.agr");
            expect(result.imports[1].names).toBe("*");
            expect(result.imports[1].source).toBe("types.ts");
            expect(result.imports[2].names).toEqual(["Helper"]);
            expect(result.imports[2].source).toBe("helpers.agr");
        });

        it("parse imports with grammar rules", () => {
            const grammar = `
                import { BaseRule } from "base.agr";

                <Start> = <BaseRule> world;
                <BaseRule> = hello;
            `;
            const result = parseGrammarRules("test.agr", grammar, false);

            expect(result.imports).toHaveLength(1);
            expect(result.imports[0].names).toEqual(["BaseRule"]);
            expect(result.definitions).toHaveLength(2);
            expect(result.definitions[0].name).toBe("Start");
            expect(result.definitions[1].name).toBe("BaseRule");
        });

        it("parse single name import", () => {
            const grammar = 'import { SingleName } from "file.agr";';
            const result = parseGrammarRules("test.agr", grammar, false);

            expect(result.imports).toHaveLength(1);
            expect(result.imports[0].names).toEqual(["SingleName"]);
            expect(result.imports[0].source).toBe("file.agr");
        });
    });
});
