"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
jest.mock("../../../src/utils", () => ({
    readFile: jest.fn().mockReturnValue(Buffer.from("test")),
    fileExists: jest.fn().mockReturnValue(true),
    fileStat: jest.fn().mockResolvedValue({
        isDirectory: jest.fn().mockReturnValue(false),
        isFile: jest.fn().mockReturnValue(true),
        size: 1024,
    }),
}));
jest.mock("../../../src/services/EventService", () => ({
    EventService: jest.fn().mockImplementation(() => ({
        on: jest.fn(),
        emit: jest.fn(),
    })),
}));
jest.mock("../../../src/config", () => ({
    getConfig: jest.fn(),
    getConfigSync: jest.fn(),
    getLanguageConfig: jest.fn(),
}));
jest.mock("../../../src/plugins/plugins", () => ({
    PluginService: jest.fn().mockImplementation(() => ({
        listPlugins: jest.fn(),
        call: jest.fn(),
    })),
}));
const language_1 = require("../../../src/plugins/language");
const EventService_1 = require("../../../src/services/EventService");
const utils = __importStar(require("../../../src/utils"));
const config_1 = require("../../../src/config");
const plugins_1 = require("../../../src/plugins/plugins");
const minimatch_1 = require("minimatch");
const mockedConfig = config_1.getConfig;
const mockedLanguageConfig = config_1.getLanguageConfig;
const matchGlobPattern = (pattern, text) => (0, minimatch_1.minimatch)(text, pattern);
describe("matchGlobPattern", () => {
    it("should match exact patterns", () => {
        expect(matchGlobPattern("src/components/Button.ts", "src/components/Button.ts")).toBe(true);
    });
    it("should match wildcard patterns", () => {
        expect(matchGlobPattern("**/*.ts", "Button.ts")).toBe(true);
        expect(matchGlobPattern("**/*.ts", "src/components/Button.ts")).toBe(true);
        expect(matchGlobPattern("src/**", "src/components")).toBe(true);
    });
});
const MockedPluginService = plugins_1.PluginService;
const MockedEventService = EventService_1.EventService;
describe("LanguagePlugin", () => {
    const userPrompt = "test prompt including terms";
    test("should call the correct plugins based on the user prompt", async () => {
        const mockPluginService = new MockedPluginService({});
        const mockEventService = {
            on: jest.fn(),
            emit: jest.fn(),
            log: jest.fn(),
        };
        const mockListPlugins = jest.fn().mockReturnValue(["github", "asana"]);
        const mockCall = jest.fn().mockResolvedValue(["mocked plugin response"]);
        mockPluginService.listPlugins = mockListPlugins;
        mockPluginService.call = mockCall;
        mockedConfig.mockResolvedValue({
            plugins: { enabled: ["github", "asana"], disabled: [] },
        });
        mockedLanguageConfig.mockResolvedValue({
            test: {
                events: [],
                sources: [
                    { kind: "github", data: ["http://github.com/test"] },
                    { kind: "asana", data: ["http://asana.com/test"] },
                    { kind: "file", data: ["../.knowhow/knowhow.json"] },
                ],
            },
        });
        const languagePlugin = new language_1.LanguagePlugin({
            Events: mockEventService,
            Plugins: mockPluginService,
        });
        const pluginResponse = await languagePlugin.call(userPrompt);
        expect(utils.fileExists).toHaveBeenCalled();
        expect(utils.readFile).toHaveBeenCalled();
        expect(mockListPlugins).toHaveBeenCalled();
        expect(mockCall).toHaveBeenCalledWith("github", expect.any(String));
        expect(mockCall).toHaveBeenCalledWith("asana", expect.any(String));
        expect(pluginResponse).toContain("LANGUAGE PLUGIN: The user mentioned these terms triggering contextual expansions");
    });
    describe("Event-driven context expansion", () => {
        let mockEventService;
        let mockPluginService;
        let eventHandlers;
        beforeEach(() => {
            eventHandlers = new Map();
            mockEventService = {
                on: jest.fn((event, handler) => {
                    eventHandlers.set(event, handler);
                }),
                emit: jest.fn((event, data) => {
                    return true;
                }),
            };
            mockPluginService = new MockedPluginService({});
            mockPluginService.listPlugins = jest.fn().mockReturnValue(["github"]);
            mockPluginService.call = jest
                .fn()
                .mockResolvedValue(["plugin context data"]);
        });
        test("should register event handlers for configured events during initialization", async () => {
            mockedLanguageConfig.mockResolvedValue({
                "*.ts,*.js": {
                    events: ["file:post-edit", "file:create"],
                    sources: [{ kind: "file", data: ["src/config.ts"] }],
                },
                "package.json": {
                    events: ["file:post-edit"],
                    sources: [{ kind: "text", data: ["Package configuration"] }],
                },
            });
            new language_1.LanguagePlugin({
                Events: mockEventService,
                Plugins: mockPluginService,
            });
            await new Promise((resolve) => setTimeout(resolve, 0));
            expect(mockEventService.on).toHaveBeenCalledWith("file:post-edit", expect.any(Function));
            expect(mockEventService.on).toHaveBeenCalledWith("file:create", expect.any(Function));
        });
        test("should handle file:post-edit event and emit agent:msg when file pattern matches", async () => {
            mockedConfig.mockResolvedValue({
                plugins: { enabled: ["github"], disabled: [] },
            });
            mockedLanguageConfig.mockResolvedValue({
                "**/*.ts": {
                    events: ["file:post-edit"],
                    sources: [
                        { kind: "file", data: ["src/types.ts"] },
                        { kind: "github", data: ["https://github.com/repo/issues/123"] },
                    ],
                },
            });
            new language_1.LanguagePlugin({
                Events: mockEventService,
                Plugins: mockPluginService,
            });
            await new Promise((resolve) => setTimeout(resolve, 0));
            const fileEditHandler = eventHandlers.get("file:post-edit");
            expect(fileEditHandler).toBeDefined();
            await fileEditHandler({
                filePath: "src/components/Button.ts",
                operation: "edit",
            });
            await new Promise((resolve) => setTimeout(resolve, 100));
            expect(mockEventService.emit).toHaveBeenCalledWith("agent:msg", expect.any(String));
            const emitCall = mockEventService.emit.mock.calls.find((call) => call[0] === "agent:msg");
            expect(emitCall).toBeDefined();
            const workflowContent = emitCall[1].match(/<Workflow>\s*(\{[\s\S]*?\})\s*<\/Workflow>/);
            expect(workflowContent).toBeDefined();
            const eventData = JSON.parse(workflowContent[1]);
            expect(eventData.type).toBe("language_context_trigger");
            expect(eventData.matchingTerms).toEqual(["**/*.ts"]);
            expect(eventData.eventType).toBe("file:post-edit");
            expect(eventData.resolvedSources).toBeDefined();
        });
        test("should not emit agent:msg when file pattern does not match", async () => {
            mockedLanguageConfig.mockResolvedValue({
                "*.ts": {
                    events: ["file:post-edit"],
                    sources: [{ kind: "file", data: ["src/types.ts"] }],
                },
            });
            new language_1.LanguagePlugin({
                Events: mockEventService,
                Plugins: mockPluginService,
            });
            await new Promise((resolve) => setTimeout(resolve, 0));
            const fileEditHandler = eventHandlers.get("file:post-edit");
            await fileEditHandler({
                filePath: "README.md",
                operation: "edit",
            });
            expect(mockEventService.emit).not.toHaveBeenCalledWith("agent:msg", expect.anything());
        });
        test("should handle multiple matching patterns for a single file", async () => {
            mockedConfig.mockResolvedValue({
                plugins: { enabled: [], disabled: [] },
            });
            mockedLanguageConfig.mockResolvedValue({
                "**/*.ts": {
                    events: ["file:post-edit"],
                    sources: [{ kind: "text", data: ["TypeScript context"] }],
                },
                "src/**": {
                    events: ["file:post-edit"],
                    sources: [{ kind: "text", data: ["Source directory context"] }],
                },
            });
            new language_1.LanguagePlugin({
                Events: mockEventService,
                Plugins: mockPluginService,
            });
            await new Promise((resolve) => setTimeout(resolve, 0));
            const fileEditHandler = eventHandlers.get("file:post-edit");
            await fileEditHandler({
                filePath: "src/components/Button.ts",
            });
            await new Promise((resolve) => setTimeout(resolve, 10));
            const emitCall = mockEventService.emit.mock.calls.find((call) => call[0] === "agent:msg");
            const workflowContent = emitCall[1].match(/<Workflow>\s*(\{[\s\S]*?\})\s*<\/Workflow>/);
            expect(workflowContent).toBeDefined();
            const eventData = JSON.parse(workflowContent[1]);
            expect(eventData.matchingTerms).toContain("src/**");
        });
        test("should only trigger on configured events for a term", async () => {
            mockedLanguageConfig.mockResolvedValue({
                "*.ts": {
                    events: ["file:create"],
                    sources: [{ kind: "text", data: ["TypeScript context"] }],
                },
            });
            new language_1.LanguagePlugin({
                Events: mockEventService,
                Plugins: mockPluginService,
            });
            await new Promise((resolve) => setTimeout(resolve, 0));
            const fileEditHandler = eventHandlers.get("file:post-edit");
            if (fileEditHandler) {
                await fileEditHandler({
                    filePath: "src/Button.ts",
                });
            }
            expect(mockEventService.emit).not.toHaveBeenCalledWith("agent:msg", expect.anything());
        });
        test("should resolve different source types in event context", async () => {
            mockedConfig.mockResolvedValue({
                plugins: { enabled: ["github"], disabled: [] },
            });
            mockedLanguageConfig.mockResolvedValue({
                "package.json": {
                    events: ["file:post-edit"],
                    sources: [
                        { kind: "file", data: ["config/settings.json"] },
                        { kind: "text", data: ["JSON configuration files"] },
                        { kind: "github", data: ["https://github.com/repo/config"] },
                    ],
                },
            });
            new language_1.LanguagePlugin({
                Events: mockEventService,
                Plugins: mockPluginService,
            });
            await new Promise((resolve) => setTimeout(resolve, 0));
            const fileEditHandler = eventHandlers.get("file:post-edit");
            await fileEditHandler({
                filePath: "package.json",
            });
            expect(utils.fileExists).toHaveBeenCalledWith("config/settings.json");
            expect(utils.readFile).toHaveBeenCalledWith("config/settings.json", "utf8");
            expect(mockPluginService.call).toHaveBeenCalledWith("github", "https://github.com/repo/config");
            expect(mockEventService.emit).toHaveBeenCalledWith("agent:msg", expect.stringMatching(/<Workflow>[\s\S]*language_context_trigger[\s\S]*<\/Workflow>/));
        });
    });
    test("should return a message if no matching terms found", async () => {
        const mockEventService = {
            on: jest.fn(),
            emit: jest.fn(),
            log: jest.fn(),
        };
        const mockPluginService = new MockedPluginService({});
        const mockListPlugins = jest.fn().mockReturnValue(["github"]);
        mockPluginService.listPlugins = mockListPlugins;
        mockedConfig.mockResolvedValue({
            plugins: { enabled: ["github"], disabled: [] },
        });
        mockedLanguageConfig.mockResolvedValue({});
        const languagePlugin = new language_1.LanguagePlugin({
            Events: mockEventService,
            Plugins: mockPluginService,
        });
        const pluginResponse = await languagePlugin.call(userPrompt);
        expect(pluginResponse).toEqual("LANGUAGE PLUGIN: No matching terms found");
    });
});
//# sourceMappingURL=languagePlugin.test.js.map