import { vi } from "vitest";
import type { Queue, Job } from "bullmq";

/**
 * Mock BullMQ job for testing
 */
export function createMockBullMqJob(overrides?: Partial<Job>): Partial<Job> {
  return {
    id: "mock-bull-job-id",
    name: "runner-job",
    data: {
      jobId: "mock-job-id",
      workspaceId: "mock-workspace-id",
      type: "code-task",
    },
    progress: vi.fn().mockReturnValue(0),
    updateProgress: vi.fn().mockResolvedValue(undefined),
    log: vi.fn().mockResolvedValue(undefined),
    remove: vi.fn().mockResolvedValue(undefined),
    ...overrides,
  };
}

/**
 * Mock BullMQ queue for testing
 */
export function createMockBullMqQueue(): Partial<Queue> {
  const jobs = new Map<string, Partial<Job>>();

  return {
    add: vi.fn().mockImplementation((name: string, data: unknown) => {
      const job = createMockBullMqJob({
        id: `job-${Date.now()}`,
        name,
        data: data as never,
      });
      jobs.set(job.id as string, job);
      return Promise.resolve(job);
    }),
    getJob: vi.fn().mockImplementation((jobId: string) => {
      return Promise.resolve(jobs.get(jobId) || null);
    }),
    getJobs: vi.fn().mockResolvedValue([]),
    pause: vi.fn().mockResolvedValue(undefined),
    resume: vi.fn().mockResolvedValue(undefined),
    clean: vi.fn().mockResolvedValue([]),
    close: vi.fn().mockResolvedValue(undefined),
    on: vi.fn(),
    once: vi.fn(),
  };
}

/**
 * Mock BullMQ service for testing
 */
export function createMockBullMqService() {
  const queues = new Map<string, Partial<Queue>>();

  return {
    addJob: vi
      .fn()
      .mockImplementation((queueName: string, jobName: string, data: unknown, opts?: unknown) => {
        let queue = queues.get(queueName);
        if (!queue) {
          queue = createMockBullMqQueue();
          queues.set(queueName, queue);
        }
        return queue.add?.(jobName, data, opts as never);
      }),
    getQueue: vi.fn().mockImplementation((queueName: string) => {
      let queue = queues.get(queueName);
      if (!queue) {
        queue = createMockBullMqQueue();
        queues.set(queueName, queue);
      }
      return queue;
    }),
    getJob: vi.fn().mockImplementation((queueName: string, jobId: string) => {
      const queue = queues.get(queueName);
      return queue?.getJob?.(jobId);
    }),
  };
}
