import React, { type ReactNode } from "react";
import { BrowserRouter } from "react-router";

import {
  type AccessControlProvider,
  type AuthProvider,
  type NotificationProvider,
  Refine,
  type I18nProvider,
  type DataProvider,
  type IResourceItem,
  type RouterProvider,
  type IRefineOptions,
} from "@refinedev/core";

import { MockJSONServer, mockRouterProvider } from "./dataMocks";

export interface ITestWrapperProps {
  dataProvider?: DataProvider;
  routerProvider?: RouterProvider;
  authProvider?: AuthProvider;
  resources?: IResourceItem[];
  notificationProvider?: NotificationProvider;
  accessControlProvider?: AccessControlProvider;
  i18nProvider?: I18nProvider;
  routerInitialEntries?: string[];
  options?: IRefineOptions;
}

export const TestWrapper: (
  props: ITestWrapperProps,
) => React.FC<{ children?: ReactNode }> = ({
  dataProvider,
  authProvider,
  routerProvider,
  resources,
  notificationProvider,
  accessControlProvider,
  routerInitialEntries,
  i18nProvider,
  options,
}) => {
  // Previously, MemoryRouter was used in this wrapper. However, the
  // recommendation by react-router developers (see
  // https://github.com/remix-run/react-router/discussions/8241#discussioncomment-159686)
  // is essentially to use the same router as your actual application. Besides
  // that, it's impossible to check for location changes with MemoryRouter if
  // needed.
  if (routerInitialEntries) {
    routerInitialEntries.forEach((route) => {
      window.history.replaceState({}, "", route);
    });
  }

  return ({ children }): React.JSX.Element => {
    return (
      <BrowserRouter>
        {(Refine as any)({
          dataProvider: dataProvider ?? MockJSONServer,
          i18nProvider,
          routerProvider: routerProvider ?? mockRouterProvider(),
          authProvider,
          notificationProvider,
          resources: resources ?? [{ name: "posts", list: "/posts" }],
          accessControlProvider,
          options: {
            ...options,
            disableTelemetry: true,
            reactQuery: {
              clientConfig: {
                defaultOptions: {
                  queries: {
                    gcTime: 0,
                    staleTime: 0,
                    networkMode: "always",
                  },
                },
              },
            },
          },
          children,
        })}
      </BrowserRouter>
    );
  };
};

export {
  MockJSONServer,
  MockAccessControlProvider,
  MockLiveProvider,
} from "./dataMocks";

// re-export everything
export * from "@testing-library/react";
