import { beforeEach, describe, expect, it, vi } from "vitest";
import type { ContainerLifecycleService } from "../container-lifecycle/container-lifecycle.service";
import { ContainerReaperService } from "./container-reaper.service";

describe("ContainerReaperService", () => {
  let service: ContainerReaperService;
  let containerLifecycle: Pick<ContainerLifecycleService, "reapIdle">;

  beforeEach(() => {
    containerLifecycle = {
      reapIdle: vi.fn(),
    };
    service = new ContainerReaperService(containerLifecycle as ContainerLifecycleService);
  });

  it("reapIdleContainers calls containerLifecycle.reapIdle()", async () => {
    vi.mocked(containerLifecycle.reapIdle).mockResolvedValue({ stopped: [] });

    await service.reapIdleContainers();

    expect(containerLifecycle.reapIdle).toHaveBeenCalledTimes(1);
  });

  it("reapIdleContainers handles errors gracefully", async () => {
    const error = new Error("reap failure");
    vi.mocked(containerLifecycle.reapIdle).mockRejectedValue(error);
    const loggerError = vi.spyOn(service["logger"], "error").mockImplementation(() => {});

    await expect(service.reapIdleContainers()).resolves.toBeUndefined();

    expect(loggerError).toHaveBeenCalledWith(
      "Failed to reap idle containers",
      expect.stringContaining("reap failure")
    );
  });

  it("reapIdleContainers logs stopped container count", async () => {
    vi.mocked(containerLifecycle.reapIdle).mockResolvedValue({ stopped: ["user-1", "user-2"] });
    const loggerLog = vi.spyOn(service["logger"], "log").mockImplementation(() => {});

    await service.reapIdleContainers();

    expect(loggerLog).toHaveBeenCalledWith("Stopped 2 idle containers: user-1, user-2");
  });
});
