import { ReactElement, FC } from 'react';
import { render, renderHook } from '@testing-library/react';
import { renderToString } from 'react-dom/server';
import { userEvent } from '@testing-library/user-event';

import { Provider } from '..';
import { DEFAULT_LOCALE } from '../common';
import en from '../i18n/en.json';

/**
 * Custom `render` function which wraps passed elements in Provider component
 * Source: https://testing-library.com/docs/example-react-intl/#creating-a-custom-render-function
 *
 */
function customRender(
  ui: ReactElement,
  { locale = DEFAULT_LOCALE, messages = en, ...renderOptions } = {},
): ReturnType<typeof render> {
  const Wrapper: FC<{ children: React.ReactNode }> = ({ children }) => {
    return <Provider i18n={{ locale, messages }}>{children}</Provider>;
  };
  return render(ui, { wrapper: Wrapper, ...renderOptions });
}

function customRenderToString(ui: ReactElement, { locale = DEFAULT_LOCALE, messages = en } = {}) {
  const Wrapper: FC<{ children: React.ReactNode }> = ({ children }) => {
    return <Provider i18n={{ locale, messages }}>{children}</Provider>;
  };

  return renderToString(<Wrapper>{ui}</Wrapper>);
}

/**
 * Custom `renderHook` function which wraps passed elements in Provider component
 * For more info: https://react-hooks-testing-library.com/usage/advanced-hooks#context
 */
function customRenderHook(
  callback: () => unknown,
  { locale = DEFAULT_LOCALE, messages = en } = {},
) {
  return renderHook(callback, {
    wrapper: ({ children }) => <Provider i18n={{ locale, messages }}>{children}</Provider>,
  });
}

export * from '@testing-library/react';
export * from './fake-data';
export * from './story-config';
export * from './window-mock';
export {
  customRender as render,
  customRenderToString as renderToString,
  customRenderHook as renderHook,
  userEvent,
};
