import { describe, it, expect } from "vitest";
import { ifParser } from "./parsers.js";
describe("ifParser", () => {
    const testCases = [
        // Happy path - simple if statements with literals as conditions
        {
            input: "if (true) {\n  x = 1\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "boolean", value: true },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "x",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        {
            input: "if (false) {\n  y = 2\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "boolean", value: false },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "y",
                            value: { type: "number", value: "2" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        {
            input: "if (x) {\n  foo = 1\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "foo",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        {
            input: "if (1) {\n  x = 2\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "number", value: "1" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "x",
                            value: { type: "number", value: "2" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        {
            input: 'if ("yes") {\n  x = 3\n}',
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "string", segments: [{ type: "text", value: "yes" }] },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "x",
                            value: { type: "number", value: "3" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        // Function calls as conditions
        {
            input: "if (isValid()) {\n  x = 1\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: {
                        type: "functionCall",
                        functionName: "isValid",
                        arguments: [],
                    },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "x",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        // Access expressions as conditions
        {
            input: "if (obj.isReady) {\n  x = 1\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: {
                        type: "valueAccess",
                        base: { type: "variableName", value: "obj" },
                        chain: [{ kind: "property", name: "isReady" }],
                    },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "x",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        // Index access as conditions
        // TODO fix
        /* {
          input: "if (arr[0]) {\n  x = 1\n}",
          expected: {
            success: true,
            result: {
              type: "ifElse",
              condition: {
                type: "indexAccess",
                object: { type: "variableName", value: "arr" },
                index: { type: "number", value: "0" },
              },
              thenBody: [
                {
                  type: "assignment",
                  variableName: "x",
                  value: { type: "number", value: "1" },
                },
              ],
              elseBody: undefined,
            },
          },
        },
     */
        // Empty bodies
        {
            input: "if (true) {\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "boolean", value: true },
                    thenBody: [],
                    elseBody: undefined,
                },
            },
        },
        // Multiple statements in bodies
        {
            input: "if (x) {\n  a = 1\n  b = 2\n  c = 3\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "a",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                        {
                            type: "assignment",
                            variableName: "b",
                            value: { type: "number", value: "2" },
                        },
                        {
                            type: "newLine",
                        },
                        {
                            type: "assignment",
                            variableName: "c",
                            value: { type: "number", value: "3" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        // Whitespace variations
        {
            input: "if(x){\n  foo = 1\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "foo",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        {
            input: "if  (  x  )  {\n  foo = 1\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "foo",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        {
            input: "if(x){\nfoo=1\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "foo",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: undefined,
                },
            },
        },
        // Failure cases - missing parentheses
        {
            input: "if x {\n  foo = 1\n}",
            expected: { success: false },
        },
        {
            input: "if (x {\n  foo = 1\n}",
            expected: { success: false },
        },
        {
            input: "if x) {\n  foo = 1\n}",
            expected: { success: false },
        },
        // Failure cases - missing braces
        {
            input: "if (x) \n  foo = 1\n",
            expected: { success: false },
            throws: true,
        },
        {
            input: "if (x) {\n  foo = 1",
            expected: { success: false },
            throws: true,
        },
        {
            input: "if (x) \n  foo = 1\n}",
            expected: { success: false },
            throws: true,
        },
        // Failure cases - missing condition
        {
            input: "if () {\n  foo = 1\n}",
            expected: { success: false },
        },
        // Failure cases - empty or malformed
        {
            input: "",
            expected: { success: false },
        },
        {
            input: "if",
            expected: { success: false },
        },
        {
            input: "if ()",
            expected: { success: false },
        },
        {
            input: "if (x)",
            expected: { success: false },
            throws: true,
        },
        // Basic else
        {
            input: "if (x) {\n  a = 1\n} else {\n  b = 2\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "a",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: [
                        {
                            type: "assignment",
                            variableName: "b",
                            value: { type: "number", value: "2" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                },
            },
        },
        // else if chain
        {
            input: "if (x) {\n  a = 1\n} else if (y) {\n  b = 2\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "a",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: [
                        {
                            type: "ifElse",
                            condition: { type: "variableName", value: "y" },
                            thenBody: [
                                {
                                    type: "assignment",
                                    variableName: "b",
                                    value: { type: "number", value: "2" },
                                },
                                {
                                    type: "newLine",
                                },
                            ],
                        },
                    ],
                },
            },
        },
        // Full chain: if / else if / else
        {
            input: "if (x) {\n  a = 1\n} else if (y) {\n  b = 2\n} else {\n  c = 3\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "a",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: [
                        {
                            type: "ifElse",
                            condition: { type: "variableName", value: "y" },
                            thenBody: [
                                {
                                    type: "assignment",
                                    variableName: "b",
                                    value: { type: "number", value: "2" },
                                },
                                {
                                    type: "newLine",
                                },
                            ],
                            elseBody: [
                                {
                                    type: "assignment",
                                    variableName: "c",
                                    value: { type: "number", value: "3" },
                                },
                                {
                                    type: "newLine",
                                },
                            ],
                        },
                    ],
                },
            },
        },
        // Whitespace variation: no spaces around else
        {
            input: "if (x) {\n  a = 1\n}else{\n  b = 2\n}",
            expected: {
                success: true,
                result: {
                    type: "ifElse",
                    condition: { type: "variableName", value: "x" },
                    thenBody: [
                        {
                            type: "assignment",
                            variableName: "a",
                            value: { type: "number", value: "1" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                    elseBody: [
                        {
                            type: "assignment",
                            variableName: "b",
                            value: { type: "number", value: "2" },
                        },
                        {
                            type: "newLine",
                        },
                    ],
                },
            },
        },
    ];
    testCases.forEach(({ input, expected, throws }) => {
        if (expected.success) {
            it(`should parse "${input.replace(/\n/g, "\\n")}" successfully`, () => {
                const result = ifParser(input);
                expect(result.success).toBe(true);
                if (result.success) {
                    expect(result.result).toEqualWithoutLoc(expected.result);
                }
            });
        }
        else if (throws) {
            it(`should fail to parse "${input.replace(/\n/g, "\\n")}"`, () => {
                expect(() => ifParser(input)).toThrow();
            });
        }
        else {
            it(`should fail to parse "${input.replace(/\n/g, "\\n")}"`, () => {
                const result = ifParser(input);
                expect(result.success).toBe(false);
            });
        }
    });
});
