import { mock } from "bun:test";
import type { IJobQueue, JobKind, JobPayload } from "@/types/index.js";

export interface FakeQueueOptions {
  /** Whether the queue reports itself as busy. */
  busy?: boolean;
  /** What getCurrentJobKind() returns. */
  currentJobKind?: JobKind | null;
  /** What getCurrentJobKey() returns. */
  currentJobKey?: string | null;
  /** Initial pending count. */
  pendingCount?: number;
}

export interface FakeQueue extends IJobQueue {
  enqueued: JobPayload[];
  reset: () => void;
}

/**
 * Creates a lightweight IJobQueue stub that records enqueue() calls.
 * All methods are bun:test mocks so they can be asserted on.
 */
export function createFakeQueue(opts: FakeQueueOptions = {}): FakeQueue {
  const enqueued: JobPayload[] = [];

  const queue: FakeQueue = {
    enqueued,

    enqueue: mock(async (job: JobPayload) => {
      enqueued.push(job);
    }),

    start: mock((_handler: unknown) => {}),
    stop: mock(() => {}),
    shutdown: mock(async (_graceMs: number) => {}),
    isBusy: mock(() => opts.busy ?? false),
    getCurrentJobKind: mock(() => opts.currentJobKind ?? null),
    getCurrentJobKey: mock(() => opts.currentJobKey ?? null),
    pendingCount: mock(() => opts.pendingCount ?? 0),
    getPendingJobKeys: mock(() => []),

    reset() {
      enqueued.length = 0;
      for (const key of [
        "enqueue",
        "start",
        "stop",
        "shutdown",
        "isBusy",
        "getCurrentJobKind",
        "getCurrentJobKey",
        "pendingCount",
        "getPendingJobKeys",
      ] as const) {
        (this[key] as ReturnType<typeof mock>).mockClear();
      }
    },
  };

  return queue;
}
