/**
 * Database Mock for Testing
 *
 * Provides mock implementations of database operations.
 */

import { QueryResult, PoolClient } from 'pg';

/**
 * Mock database query results
 */
export const createMockQueryResult = <T>(rows: T[] = []): QueryResult<T> => ({
  rows,
  command: 'SELECT',
  rowCount: rows.length,
  oid: 0,
  fields: [],
});

/**
 * Mock PoolClient for transaction testing
 */
export const createMockPoolClient = (): jest.Mocked<PoolClient> => ({
  query: jest.fn(),
  release: jest.fn(),
  connect: jest.fn(),
  on: jest.fn(),
  removeListener: jest.fn(),
  emit: jest.fn(),
  eventNames: jest.fn(),
  listenerCount: jest.fn(),
  listeners: jest.fn(),
  off: jest.fn(),
  addListener: jest.fn(),
  once: jest.fn(),
  prependListener: jest.fn(),
  prependOnceListener: jest.fn(),
  removeAllListeners: jest.fn(),
  setMaxListeners: jest.fn(),
  getMaxListeners: jest.fn(),
  rawListeners: jest.fn(),
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any);

/**
 * Mock database instance
 */
export const mockDb = {
  query: jest.fn(),
  getClient: jest.fn(),
  transaction: jest.fn(),
  healthCheck: jest.fn(),
  close: jest.fn(),
  getPoolStatus: jest.fn(),
};

/**
 * Setup database mock with default behaviors
 */
export const setupDatabaseMock = () => {
  const mockClient = createMockPoolClient();

  // Default implementations
  mockDb.query.mockResolvedValue(createMockQueryResult([]));
  mockDb.getClient.mockResolvedValue(mockClient);
  mockDb.transaction.mockImplementation(async (callback) => {
    return callback(mockClient);
  });
  mockDb.healthCheck.mockResolvedValue(true);
  mockDb.getPoolStatus.mockReturnValue({
    total: 10,
    idle: 5,
    waiting: 0,
  });

  // Mock client methods
  mockClient.query.mockResolvedValue(createMockQueryResult([]));

  return { mockDb, mockClient };
};

/**
 * Reset all database mocks
 */
export const resetDatabaseMocks = () => {
  mockDb.query.mockClear();
  mockDb.getClient.mockClear();
  mockDb.transaction.mockClear();
  mockDb.healthCheck.mockClear();
  mockDb.close.mockClear();
  mockDb.getPoolStatus.mockClear();
};

// Export for use in test files
export { mockDb };

// Note: Tests should import mockDb and manually mock the database module
// in their test file using:
// jest.mock('path/to/database', () => ({
//   db: mockDb,
// }));
