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

import { TeamBilling } from "@calcom/features/ee/billing/teams";
import { deleteDomain } from "@calcom/lib/domainManager/organization";
import { TeamRepository } from "@calcom/lib/server/repository/team";
import { WorkflowService } from "@calcom/lib/server/service/workflows";

import { TeamService } from "./teamService";

vi.mock("@calcom/features/ee/billing/teams");
vi.mock("@calcom/lib/server/repository/team");
vi.mock("@calcom/lib/server/service/workflows");
vi.mock("@calcom/lib/domainManager/organization");
vi.mock("@calcom/features/ee/teams/lib/removeMember");
class Database {
  teams = new Map();
  domains = new Set();
  billings = new Map();
  workflowReminders = new Map();
  clear() {
    this.teams.clear();
    this.domains.clear();
    this.billings.clear();
    this.workflowReminders.clear();
  }
}
// In-memory database for testing
const database = new Database();

const mockTeamBilling = {
  cancel: vi.fn(),
  updateQuantity: vi.fn(),
  publish: vi.fn(),
  downgrade: vi.fn(),
};

// Mock implementations that modify the in-memory database
const mockTeamRepo = {
  deleteById: vi.fn().mockImplementation(async ({ id }) => {
    const team = database.teams.get(id);
    if (team) {
      database.teams.delete(id);
      return team;
    }
    throw new Error(`Team with id ${id} not found`);
  }),
};
vi.mocked(TeamRepository).mockImplementation(() => mockTeamRepo as any);

vi.mocked(deleteDomain).mockImplementation(async (slug) => {
  database.domains.delete(slug);
});

vi.mocked(WorkflowService.deleteWorkflowRemindersOfRemovedTeam).mockImplementation(async (teamId) => {
  database.workflowReminders.delete(teamId);
});

vi.mocked(TeamBilling.findAndInit).mockImplementation(async (teamId) => {
  // Create a team-specific billing mock
  const teamSpecificBilling = {
    ...mockTeamBilling,
    teamId,
    cancel: vi.fn().mockImplementation(() => {
      const billing = database.billings.get(teamId);
      if (billing) {
        billing.cancelled = true;
      }
    }),
  };
  return teamSpecificBilling;
});

describe("TeamService", () => {
  beforeEach(() => {
    database.clear();

    database.teams.set(1, {
      id: 1,
      name: "Deleted Team",
      isOrganization: true,
      slug: "deleted-team",
    });
    database.domains.add("deleted-team");
    database.billings.set(1, { teamId: 1, cancelled: false });
    database.workflowReminders.set(1, ["reminder1", "reminder2"]);
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  describe("delete", () => {
    it("should delete team, cancel billing, and clean up", async () => {
      const result = await TeamService.delete({ id: 1 });

      // Verify the team was deleted from the database
      expect(database.teams.has(1)).toBe(false);

      // Verify the domain was deleted
      expect(database.domains.has("deleted-team")).toBe(false);

      // Verify billing was cancelled
      expect(database.billings.get(1)?.cancelled).toBe(true);

      // Verify workflow reminders were deleted
      expect(database.workflowReminders.has(1)).toBe(false);

      // Verify the returned team data
      expect(result).toEqual({
        id: 1,
        name: "Deleted Team",
        isOrganization: true,
        slug: "deleted-team",
      });
    });
  });
});
