import React from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { MemoryRouter, MemoryRouterProps } from 'react-router';

interface RenderWithProvidersOptions extends Omit<RenderOptions, 'wrapper'> {
  route?: string;
  routerProps?: Omit<MemoryRouterProps, 'children'>;
}

/**
 * Renders a component wrapped with necessary providers for testing.
 *
 * @param ui - The React element to render
 * @param options - Configuration options including route and router props
 * @returns The render result from @testing-library/react
 */
export const renderWithProviders = (
  ui: React.ReactElement,
  { route = '/', routerProps, ...renderOptions }: RenderWithProvidersOptions = {}
) => {
  const Wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    return (
      <MemoryRouter initialEntries={[route]} {...routerProps}>
        {children}
      </MemoryRouter>
    );
  };

  return {
    ...render(ui, { wrapper: Wrapper, ...renderOptions }),
  };
};

/**
 * Renders a component wrapped with MemoryRouter at a specific route.
 * Useful for testing components that use useParams, useSearchParams, etc.
 *
 * @param ui - The React element to render
 * @param route - The initial route to render at
 * @returns The render result
 */
export const renderWithRouter = (
  ui: React.ReactElement,
  route: string = '/'
) => {
  return renderWithProviders(ui, { route });
};

/**
 * Creates a mock search params string from an object
 *
 * @param params - Object with key-value pairs for search params
 * @returns A route string with search params
 */
export const createRouteWithParams = (
  path: string,
  params: Record<string, string>
): string => {
  const searchParams = new URLSearchParams(params);
  return `${path}?${searchParams.toString()}`;
};

export default renderWithProviders;
