import { Test, TestingModule } from "@nestjs/testing";
import { BridgeModule } from "./bridge.module";
import { DiscordService } from "./discord/discord.service";
import { StitcherService } from "../stitcher/stitcher.service";
import { PrismaService } from "../prisma/prisma.service";
import { BullMqService } from "../bullmq/bullmq.service";
import { describe, it, expect, beforeEach, vi } from "vitest";

// Mock discord.js
const mockReadyCallbacks: Array<() => void> = [];
const mockClient = {
  login: vi.fn().mockImplementation(async () => {
    mockReadyCallbacks.forEach((cb) => cb());
    return Promise.resolve();
  }),
  destroy: vi.fn().mockResolvedValue(undefined),
  on: vi.fn(),
  once: vi.fn().mockImplementation((event: string, callback: () => void) => {
    if (event === "ready") {
      mockReadyCallbacks.push(callback);
    }
  }),
  user: { tag: "TestBot#1234" },
  channels: {
    fetch: vi.fn(),
  },
  guilds: {
    fetch: vi.fn(),
  },
};

vi.mock("discord.js", () => {
  return {
    Client: class MockClient {
      login = mockClient.login;
      destroy = mockClient.destroy;
      on = mockClient.on;
      once = mockClient.once;
      user = mockClient.user;
      channels = mockClient.channels;
      guilds = mockClient.guilds;
    },
    Events: {
      ClientReady: "ready",
      MessageCreate: "messageCreate",
      Error: "error",
    },
    GatewayIntentBits: {
      Guilds: 1 << 0,
      GuildMessages: 1 << 9,
      MessageContent: 1 << 15,
    },
  };
});

describe("BridgeModule", () => {
  let module: TestingModule;

  beforeEach(async () => {
    // Set environment variables
    process.env.DISCORD_BOT_TOKEN = "test-token";
    process.env.DISCORD_GUILD_ID = "test-guild-id";
    process.env.DISCORD_CONTROL_CHANNEL_ID = "test-channel-id";
    process.env.ENCRYPTION_KEY = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";

    // Clear ready callbacks
    mockReadyCallbacks.length = 0;

    module = await Test.createTestingModule({
      imports: [BridgeModule],
    })
      .overrideProvider(PrismaService)
      .useValue({})
      .overrideProvider(BullMqService)
      .useValue({})
      .compile();

    // Clear all mocks
    vi.clearAllMocks();
  });

  it("should be defined", () => {
    expect(module).toBeDefined();
  });

  it("should provide DiscordService", () => {
    const discordService = module.get<DiscordService>(DiscordService);
    expect(discordService).toBeDefined();
    expect(discordService).toBeInstanceOf(DiscordService);
  });

  it("should provide StitcherService", () => {
    const stitcherService = module.get<StitcherService>(StitcherService);
    expect(stitcherService).toBeDefined();
    expect(stitcherService).toBeInstanceOf(StitcherService);
  });
});
