import { describe, test, expect, mock, beforeEach } from "bun:test";
import { CommandHandler } from "./CommandHandler";
import { AuroraClient } from "@/lib/BotClient";
import { ChatInputCommandInteraction } from "discord.js";

// Mock UserService
mock.module("@/modules/user/user.service", () => ({
    userService: {
        getOrCreateUser: mock(() => Promise.resolve())
    }
}));

describe("CommandHandler", () => {
    beforeEach(() => {
        AuroraClient.commands.clear();
        AuroraClient.lastCommandTimestamp = null;
    });

    test("should update lastCommandTimestamp on successful execution", async () => {
        const executeSuccess = mock(() => Promise.resolve());
        AuroraClient.commands.set("test", {
            data: { name: "test" } as any,
            execute: executeSuccess
        } as any);

        const interaction = {
            commandName: "test",
            user: { id: "123", username: "testuser" }
        } as unknown as ChatInputCommandInteraction;

        await CommandHandler.handle(interaction);

        expect(executeSuccess).toHaveBeenCalled();
        expect(AuroraClient.lastCommandTimestamp).not.toBeNull();
        expect(AuroraClient.lastCommandTimestamp).toBeGreaterThan(0);
    });

    test("should not update lastCommandTimestamp on failed execution", async () => {
        const executeError = mock(() => Promise.reject(new Error("Command Failed")));
        AuroraClient.commands.set("fail", {
            data: { name: "fail" } as any,
            execute: executeError
        } as any);

        const interaction = {
            commandName: "fail",
            user: { id: "123", username: "testuser" },
            replied: false,
            deferred: false,
            reply: mock(() => Promise.resolve()),
            followUp: mock(() => Promise.resolve())
        } as unknown as ChatInputCommandInteraction;

        await CommandHandler.handle(interaction);

        expect(executeError).toHaveBeenCalled();
        expect(AuroraClient.lastCommandTimestamp).toBeNull();
    });
});
