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

// Mock DrizzleClient
const executeMock = mock(() => Promise.resolve());
mock.module("@shared/db/DrizzleClient", () => ({
    DrizzleClient: {
        execute: executeMock
    }
}));

// Mock BotClient (already has lastCommandTimestamp if imported, but we might want to control it)
AuroraClient.lastCommandTimestamp = 1641481200000; // Fixed timestamp for testing

describe("Health Command", () => {
    beforeEach(() => {
        executeMock.mockClear();
    });

    test("should execute successfully and return health embed", async () => {
        const interaction = {
            deferReply: mock(() => Promise.resolve()),
            editReply: mock(() => Promise.resolve()),
            client: {
                ws: {
                    ping: 42
                }
            },
            user: { id: "123", username: "testuser" },
            commandName: "health"
        } as unknown as ChatInputCommandInteraction;

        await health.execute(interaction);

        expect(interaction.deferReply).toHaveBeenCalled();
        expect(executeMock).toHaveBeenCalled();
        expect(interaction.editReply).toHaveBeenCalled();

        const editReplyCall = (interaction.editReply as any).mock.calls[0][0];
        const embed = editReplyCall.embeds[0];

        expect(embed.data.title).toBe("System Health Status");
        expect(embed.data.color).toBe(Colors.Aqua);

        // Check fields
        const fields = embed.data.fields;
        expect(fields).toBeDefined();

        // Connectivity field
        const connectivityField = fields.find((f: any) => f.name === "📡 Connectivity");
        expect(connectivityField.value).toContain("42ms");
        expect(connectivityField.value).toContain("Connected");

        // Activity field
        const activityField = fields.find((f: any) => f.name === "⌨️ Activity");
        expect(activityField.value).toContain("R>"); // Relative Discord timestamp
    });

    test("should handle database disconnection", async () => {
        executeMock.mockImplementationOnce(() => Promise.reject(new Error("DB Down")));

        const interaction = {
            deferReply: mock(() => Promise.resolve()),
            editReply: mock(() => Promise.resolve()),
            client: {
                ws: {
                    ping: 42
                }
            },
            user: { id: "123", username: "testuser" },
            commandName: "health"
        } as unknown as ChatInputCommandInteraction;

        await health.execute(interaction);

        const editReplyCall = (interaction.editReply as any).mock.calls[0][0];
        const embed = editReplyCall.embeds[0];
        const connectivityField = embed.data.fields.find((f: any) => f.name === "📡 Connectivity");

        expect(connectivityField.value).toContain("Disconnected");
    });
});
