import { SafeAreaProvider } from "react-native-safe-area-context";
import { render } from "@testing-library/react-native";
import React, { PropsWithChildren } from "react";
import configureStore from "redux-mock-store";
import { Provider } from "react-redux";
import { View } from "react-native";
import thunk from "redux-thunk";
import * as R from "ramda";

import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";

import { ThemeContext } from "../theme";
import { AnalyticsProvider } from "../analyticsUtils";

export { getByTestId } from "./getByTestId";

/** Helper function for react-test-renderer, accepts type and renderer
 * * @param {*} type React Component type instance  or name of component
 * * @param {*} renderer renderer instance
 */
export const findByType = (type, renderer) => {
  try {
    renderer.root ? renderer.root.findByType(type) : renderer.findByType(type);
  } catch {
    return undefined;
  }
};

export function createComponentMock(mockName, hasChildren = false) {
  return hasChildren
    ? jest.fn(({ children }) => (
        <View testID={mockName}>
          {typeof children === "function" ? children() : children}
        </View>
      ))
    : jest.fn(() => <View testID={mockName} />);
}

const initialState = {
  styles: {},
  remoteConfigurations: {
    styles: {},
  },
  components: {
    River: createComponentMock("river"),
    AppContainer: createComponentMock("appContainer", true),
    DisplayError: createComponentMock("displayError"),
  },
  rivers: { id: "A1234", home: true },
  appSettings: {},
  plugins: [],
  appState: { appReady: true, appLaunched: true },
  pluginConfigurations: {},
  appData: { layoutVersion: "v1" },
  zappPipes: {},
  contentTypes: null,
};

export const WrappedWithProviders = ({
  children,
  store: storeObj = {},
}: any) => {
  const _store = configureStore([thunk])(
    R.mergeDeepRight(initialState, { ...storeObj })
  );

  appStore.set(_store);

  return (
    <ThemeContext.Provider
      value={{
        themes: {
          light: {
            component_margin_top: 0,
            component_margin_bottom: 0,
            component_margin_left: 0,
            component_margin_right: 0,
            component_padding_top: 0,
            component_padding_bottom: 0,
            component_padding_left: 0,
            component_padding_right: 0,
            component_gutter_vertical: 0,
            component_gutter_horizontal: 0,
            component_corner_radius: 0,
            app_background_color: "rgba(0,0,0,0)",
            screen_margin_top: 0,
            screen_margin_bottom: 0,
            component_anchor_point_y: 0,
            assets: "",
          },
        },
        selectedThemeId: "light",
        setSelectedThemeId: () => {},
      }}
    >
      <SafeAreaProvider
        initialMetrics={{
          insets: { top: 0, left: 0, right: 0, bottom: 0 },
          frame: { x: 0, y: 0, width: 0, height: 0 },
        }}
      >
        <Provider store={_store}>
          <AnalyticsProvider>{children}</AnalyticsProvider>
        </Provider>
      </SafeAreaProvider>
    </ThemeContext.Provider>
  );
};

/**
 * Helper test function - replacement of render() - with providers
 * @param component component to render in test
 * @param store optional store to pass to the provider
 * @returns
 */
export const renderWithProviders = (component, storeObj?: unknown) => {
  return render(component, {
    wrapper: function TestWrapper({ children }: PropsWithChildren<any>) {
      return (
        <WrappedWithProviders store={storeObj}>{children}</WrappedWithProviders>
      );
    },
  });
};
