import { describe, test, expect, mock, beforeEach } from "bun:test";
import { buildMockCWActivity } from "../setup";

// ---------------------------------------------------------------------------
// Stable mock factory (same pattern as generatedQuotesManager.test.ts)
// ---------------------------------------------------------------------------

function createStablePrismaMock(
  overrides: Record<string, Record<string, any>> = {}
) {
  return new Proxy(
    {},
    {
      get(_target, model: string) {
        if (model === "$connect" || model === "$disconnect")
          return mock(() => Promise.resolve());
        if (overrides[model]) return overrides[model];
        return new Proxy({}, { get: () => mock(() => Promise.resolve(null)) });
      },
    }
  );
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe("activities manager", () => {
  beforeEach(() => {
    mock.restore();
  });

  // -------------------------------------------------------------------
  // fetchItem
  // -------------------------------------------------------------------
  describe("fetchItem()", () => {
    test("throws NotAvailable error (not yet implemented)", async () => {
      const { activities } = await import("../../src/managers/activities");
      try {
        await activities.fetchItem(5001);
        expect(true).toBe(false); // Should not reach here
      } catch (e: any) {
        expect(e.name).toBe("NotAvailable");
        expect(e.status).toBe(501);
        expect(e.message).toContain("not yet implemented");
      }
    });
  });

  // -------------------------------------------------------------------
  // fetchPages
  // -------------------------------------------------------------------
  describe("fetchPages()", () => {
    test("returns empty array (not yet implemented)", async () => {
      const { activities } = await import("../../src/managers/activities");
      const result = await activities.fetchPages(1, 10);
      expect(result).toBeArrayOfSize(0);
    });

    test("returns empty array for negative page (not yet implemented)", async () => {
      const { activities } = await import("../../src/managers/activities");
      const result = await activities.fetchPages(-5, 10);
      expect(result).toBeArrayOfSize(0);
    });
  });

  // -------------------------------------------------------------------
  // fetchByCompany
  // -------------------------------------------------------------------
  describe("fetchByCompany()", () => {
    test("returns empty array (not yet implemented)", async () => {
      const { activities } = await import("../../src/managers/activities");
      const result = await activities.fetchByCompany(123);
      expect(result).toBeArrayOfSize(0);
    });
  });

  // -------------------------------------------------------------------
  // fetchByOpportunity
  // -------------------------------------------------------------------
  describe("fetchByOpportunity()", () => {
    test("returns empty array (not yet implemented)", async () => {
      const { activities } = await import("../../src/managers/activities");
      const result = await activities.fetchByOpportunity(1001);
      expect(result).toBeArrayOfSize(0);
    });
  });

  // -------------------------------------------------------------------
  // delete
  // -------------------------------------------------------------------
  describe("delete()", () => {
    test("delegates to activityCw.delete", async () => {
      const deleteMock = mock(() => Promise.resolve());
      mock.module("../../src/modules/cw-utils/activities/activities", () => ({
        activityCw: { delete: deleteMock },
      }));
      mock.module("../../src/constants", () => ({
        prisma: createStablePrismaMock(),
        connectWiseApi: {
          get: mock(() => Promise.resolve({ data: {} })),
        },
      }));

      const { activities } = await import("../../src/managers/activities");
      await activities.delete(5001);
      expect(deleteMock).toHaveBeenCalledWith(5001);
    });

    test("throws GenericError on failure", async () => {
      mock.module("../../src/modules/cw-utils/activities/activities", () => ({
        activityCw: {
          delete: mock(() => Promise.reject(new Error("fail"))),
        },
      }));
      mock.module("../../src/constants", () => ({
        prisma: createStablePrismaMock(),
        connectWiseApi: {
          get: mock(() => Promise.resolve({ data: {} })),
        },
      }));

      const { activities } = await import("../../src/managers/activities");
      try {
        await activities.delete(9999);
        expect(true).toBe(false);
      } catch (e: any) {
        expect(e.name).toBe("DeleteActivityError");
      }
    });
  });

  // -------------------------------------------------------------------
  // count
  // -------------------------------------------------------------------
  describe("count()", () => {
    test("returns 0 (not yet implemented)", async () => {
      const { activities } = await import("../../src/managers/activities");
      const result = await activities.count();
      expect(result).toBe(0);
    });
  });
});
