import { jest, afterEach } from "@jest/globals"
import * as dotenv from "dotenv"

// Load test environment variables
dotenv.config({ path: ".env.test" })

// Ensure critical test environment variables are set
process.env.NODE_ENV = "test"

// Mock github-repo-setup module early to prevent background Prisma calls
// Note: Jest moduleNameMapper strips .js extensions, so this should match the import
// @ts-ignore
jest.mock("./endpoints/utils/github-repo-setup", () => ({
  registerRepositoryAndMember: jest
    .fn()
    .mockImplementation(async () => await Promise.resolve(12345)),
  getInstallationId: jest.fn().mockImplementation(async () => await Promise.resolve(12345)),
}))

// Also mock the direct import paths that might be used
jest.mock("./endpoints/utils/github-repo-setup.js", () => ({
  registerRepositoryAndMember: jest
    .fn()
    .mockImplementation(async () => await Promise.resolve(12345)),
  getInstallationId: jest.fn().mockImplementation(async () => await Promise.resolve(12345)),
}))

// Set environment variable to disable Prisma in tests
process.env.SKIP_DB_INIT = "true"
// Mock Prisma globally
jest.mock(
  "@codeflash-ai/common",
  () => {
    const mockPrisma = {
      repositories: {
        findUnique: jest.fn(),
        findMany: jest.fn(),
        create: jest.fn(),
        update: jest.fn(),
        upsert: jest.fn(),
        delete: jest.fn(),
      },
      users: {
        findUnique: jest.fn(),
        findMany: jest.fn(),
        create: jest.fn(),
        update: jest.fn(),
        upsert: jest.fn(),
        delete: jest.fn(),
      },
      repository_members: {
        findUnique: jest.fn(),
        findMany: jest.fn(),
        create: jest.fn(),
        update: jest.fn(),
        upsert: jest.fn(),
        delete: jest.fn(),
      },
      app_installations: {
        findUnique: jest.fn(),
        findMany: jest.fn(),
        create: jest.fn(),
        update: jest.fn(),
        upsert: jest.fn(),
        delete: jest.fn(),
      },
      optimization_features: {
        findUnique: jest.fn(),
        findMany: jest.fn(),
        create: jest.fn(),
        update: jest.fn(),
        upsert: jest.fn(),
        delete: jest.fn(),
      },
      optimization_events: {
        findUnique: jest.fn(),
        findMany: jest.fn(),
        create: jest.fn(),
        update: jest.fn(),
        upsert: jest.fn(),
        delete: jest.fn(),
      },
      $disconnect: jest.fn(),
    }

    return {
      prisma: mockPrisma,
      getAppInstallationByInstalltionId: jest.fn(),
      createAppInstallation: jest.fn(),
      upsertRepository: jest.fn(),
      createRepositoryMember: jest.fn(),
      createOrUpdateUser: jest.fn(),
      stripeClient: {
        subscriptions: {
          list: jest.fn(),
          retrieve: jest.fn(),
        },
        customers: {
          list: jest.fn(),
          retrieve: jest.fn(),
        },
      },
      getActiveSubscriptionByUserId: jest.fn(),
      getUserByAuth0Id: jest.fn(),
      createUser: jest.fn(),
      updateUser: jest.fn(),
    }
  },
  { virtual: true },
)

// Mock Sentry globally
jest.mock("@sentry/node", () => ({
  captureException: jest.fn(),
  captureMessage: jest.fn(),
  addBreadcrumb: jest.fn(),
}))

// Mock is handled at the top of the file

// Increase test timeout for longer running tests
jest.setTimeout(30000)

// Clean up after each test
afterEach(async () => {
  jest.clearAllMocks()
  // Allow any pending promises to resolve
  await new Promise(resolve => setImmediate(resolve))
})
