import { describe, it, expect, vi, beforeEach } from "vitest";

const mockCloseDb = vi.fn();
const mockCloseNeo4j = vi.fn();

vi.mock("../../config/database.js", () => ({
  closeDb: () => mockCloseDb(),
}));

vi.mock("../../config/neo4j.js", () => ({
  closeNeo4j: () => mockCloseNeo4j(),
}));

import { LifecycleService } from "./lifecycle.service.js";

describe("LifecycleService", () => {
  let service: LifecycleService;

  beforeEach(() => {
    vi.clearAllMocks();
    service = new LifecycleService();
  });

  describe("onModuleInit", () => {
    it("should not throw on init", () => {
      expect(() => service.onModuleInit()).not.toThrow();
    });
  });

  describe("onApplicationShutdown", () => {
    it("should close neo4j and db on shutdown", async () => {
      mockCloseNeo4j.mockResolvedValue(undefined);
      mockCloseDb.mockResolvedValue(undefined);
      await service.onApplicationShutdown("SIGTERM");
      expect(mockCloseNeo4j).toHaveBeenCalled();
      expect(mockCloseDb).toHaveBeenCalled();
    });

    it("should handle signal undefined as unknown", async () => {
      mockCloseNeo4j.mockResolvedValue(undefined);
      mockCloseDb.mockResolvedValue(undefined);
      await service.onApplicationShutdown();
      expect(mockCloseDb).toHaveBeenCalled();
    });

    it("should swallow errors during shutdown", async () => {
      mockCloseNeo4j.mockRejectedValue(new Error("neo4j close failed"));
      mockCloseDb.mockResolvedValue(undefined);
      await expect(
        service.onApplicationShutdown("SIGTERM"),
      ).resolves.not.toThrow();
    });
  });
});
