import { vi } from 'vitest';

/**
 * Dynamically creates a fully mocked repository from a repository class.
 * Recursively walks the prototype chain (inheritance-aware) to gather all methods,
 * and assigns them a Vitest mock function (vi.fn()).
 *
 * @param repoClass The repository class constructor to mock
 * @returns An object with all methods mocked as vi.fn()
 *
 * @example
 * const mockRepo = createMockRepository(ProductsRepository);
 * mockRepo.findById.mockResolvedValue(mockProduct);
 */
export function createMockRepository<T>(
  repoClass: new (...args: any[]) => T
): Record<keyof T, any> {
  const mock: Record<string, any> = {};
  let proto = repoClass.prototype;

  while (proto && proto !== Object.prototype) {
    const methods = Object.getOwnPropertyNames(proto).filter(
      (name) => name !== 'constructor' && typeof (proto as any)[name] === 'function'
    );
    for (const method of methods) {
      if (!(method in mock)) {
        mock[method] = vi.fn();
      }
    }
    proto = Object.getPrototypeOf(proto);
  }

  return mock as Record<keyof T, any>;
}
