import React from "react";
import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
import {
  getMenuPlugin,
  isBottomTabVisible,
  SIDE_MENU_PLUGIN_ID,
} from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";

const mockUseMenuToggleContext = jest.fn(() => ({
  toggleMenu: jest.fn(),
  setToggleMenu: jest.fn(),
  openMenu: jest.fn(),
  setOpenMenu: jest.fn(),
  closeMenu: jest.fn(),
  setCloseMenu: jest.fn(),
}));

jest.mock("../layoutHelpers", () => {
  const { View } = jest.requireActual("react-native");
  const { isVideoOverlayVisible } = jest.requireActual("../layoutHelpers");

  return {
    // eslint-disable-next-line react/display-name
    getNavigationPluginModule: () => (props) => (
      <View testID="menu" {...props} />
    ),
    isVideoOverlayVisible,
  };
});

jest.mock(
  "@applicaster/zapp-react-native-ui-components/Components/Transitioner",
  () => {
    const { View } = jest.requireActual("react-native");

    return {
      // eslint-disable-next-line react/display-name
      Transitioner: (props) => <View testID="transitioner" {...props} />,
    };
  }
);

jest.mock(
  "@applicaster/zapp-react-native-ui-components/Components/Screen",
  () => {
    const { View } = jest.requireActual("react-native");

    return {
      // eslint-disable-next-line react/display-name
      Screen: (props) => <View {...props} />,
    };
  }
);

jest.mock(
  "@applicaster/zapp-react-native-ui-components/Contexts/MenuToggleContext",
  () => ({
    useMenuToggleContext: mockUseMenuToggleContext,
  })
);

const mockUseNavigation = jest.fn();

jest.mock(
  "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation",
  () => ({
    useNavigation: mockUseNavigation,
  })
);

jest.mock(
  "@applicaster/zapp-react-native-utils/reactHooks/navigation/useGetBottomTabBarHeight",
  () => ({
    useGetBottomTabBarHeight: jest.fn(() => 50),
  })
);

jest.mock(
  "@applicaster/zapp-react-native-utils/reactHooks/layout/useDimensions",
  () => ({
    useDimensions: jest.fn(() => ({ width: 100, height: 100 })),
  })
);

jest.mock(
  "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext",
  () => ({
    useNavbarState: jest.fn(() => ({ title: "Test Title" })),
  })
);

jest.mock("@applicaster/zapp-react-native-utils/localizationUtils", () => ({
  useIsRTL: jest.fn(() => false),
}));

jest.mock(
  "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation",
  () => ({
    withModalAnimationProvider: jest.fn((Component) => Component),
  })
);

jest.mock(
  "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/useModalAnimationContext",
  () => ({
    useModalAnimationContext: jest.fn(() => ({
      isActiveGesture: false,
    })),
  })
);

jest.mock("@applicaster/zapp-react-native-utils/dimensionsProvider", () => ({
  withDimensionsProvider: jest.fn((Component) => Component),
}));

jest.mock(
  "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler",
  () => ({
    isMenuVisible: jest.fn(() => true),
    isBottomTabVisible: jest.fn(() => true),
    getMenuPlugin: jest.fn(() => ({ identifier: "test-plugin" })),
    SIDE_MENU_PLUGIN_ID: "quick_brick_side_menu",
  })
);

jest.mock(
  "@applicaster/zapp-react-dom-ui-components/Components/ZappHooksModal",
  () => {
    const { View } = jest.requireActual("react-native");

    return {
      // eslint-disable-next-line react/display-name
      ZappHooksModal: (props) => <View testID="zappHooksModal" {...props} />,
    };
  }
);

jest.mock(
  "@applicaster/zapp-react-native-ui-components/Components/VideoModal",
  () => {
    const { View } = jest.requireActual("react-native");

    return {
      // eslint-disable-next-line react/display-name
      VideoModal: (props) => <View testID="videoModal" {...props} />,
    };
  }
);

jest.mock("@applicaster/zapp-react-native-utils/navigationUtils", () => ({
  ...(jest.requireActual(
    "@applicaster/zapp-react-native-utils/navigationUtils"
  ) as jest.Mock<any>),
  getNavigationProps: () => ({}),
  resolveNavigationPlugin: () => ({
    identifier: "quick-brick-bottom-tabs",
  }),
}));

const { Layout } = require("../");

describe("Layout", () => {
  beforeAll(() => {
    mockUseNavigation.mockImplementation(() => ({
      activeRiver: { navigations: [] },
      videoModalState: { visible: false, mode: "MINIMIZED" },
      isVideoModalDocked: false,
      currentRoute: "home",
      data: {},
    }));
  });

  beforeEach(() => {
    jest.clearAllMocks();

    mockUseNavigation.mockImplementation(() => ({
      activeRiver: { navigations: [] },
      videoModalState: { visible: false, mode: "MINIMIZED" },
      isVideoModalDocked: false,
      currentRoute: "home",
      data: {},
    }));
  });

  it("should match snapshot when appReady is true", () => {
    const { toJSON } = renderWithProviders(<Layout />);

    expect(toJSON()).toMatchSnapshot();
  });

  it("should not render transitioner with screen when appReady is false", () => {
    const { queryByTestId } = renderWithProviders(<Layout />, {
      appState: {
        appReady: false,
        appLaunched: true,
      },
    });

    expect(queryByTestId("transitioner")).toBeNull();
  });

  it("should render menu when showMenu is true", () => {
    const { queryByTestId } = renderWithProviders(<Layout />);
    expect(queryByTestId("menu")).toBeTruthy();
  });

  it("should render VideoModal when visible & VideoModal is true", () => {
    mockUseNavigation.mockReturnValue({
      activeRiver: { navigations: [] },
      videoModalState: { visible: true, mode: "MINIMIZED" },
      isVideoModalDocked: false,
      currentRoute: "home",
      data: {},
    });

    const { getByTestId } = renderWithProviders(<Layout />);
    expect(getByTestId("videoModal")).toBeTruthy();
  });

  it("should render ZappHooksModal", () => {
    const { getByTestId } = renderWithProviders(<Layout />);
    expect(getByTestId("zappHooksModal")).toBeTruthy();
  });

  it("padding should be non-0 when showMenu is true and isBottomTabsPlugin is true", () => {
    mockUseNavigation.mockReturnValueOnce({
      activeRiver: { navigations: [{ identifier: "quick-brick-bottom-tabs" }] },
      videoModalState: { visible: false, mode: "MINIMIZED" },
      isVideoModalDocked: false,
      currentRoute: "home",
      data: {},
    });

    const { getByTestId } = renderWithProviders(<Layout />);

    return expect(
      getByTestId("transitioner").props.contentStyle.paddingBottom
    ).toBe(50);
  });

  it("transitioner should have contentStyle with specific styles", () => {
    const { getByTestId } = renderWithProviders(<Layout />);

    expect(getByTestId("transitioner").props.contentStyle).toEqual({
      height: "100%",
      paddingBottom: 50,
      opacity: 1,
    });
  });

  it("should render menu when Side Menu is active and VideoModal is FULLSCREEN", () => {
    (getMenuPlugin as jest.Mock).mockReturnValue({
      identifier: SIDE_MENU_PLUGIN_ID,
    });

    mockUseNavigation.mockReturnValue({
      activeRiver: { navigations: [] },
      videoModalState: { visible: true, mode: "FULLSCREEN" },
      isVideoModalDocked: false,
      currentRoute: "home",
      data: {},
    });

    const { queryByTestId } = renderWithProviders(<Layout />);
    expect(queryByTestId("menu")).toBeTruthy();
  });

  it("should NOT render menu when Bottom Tabs are active and VideoModal is FULLSCREEN", () => {
    (getMenuPlugin as jest.Mock).mockReturnValue({
      identifier: "quick-brick-bottom-tabs",
    });

    mockUseNavigation.mockReturnValue({
      activeRiver: { navigations: [] },
      videoModalState: { visible: true, mode: "FULLSCREEN" },
      isVideoModalDocked: false,
      currentRoute: "home",
      data: {},
    });

    const { queryByTestId } = renderWithProviders(<Layout />);
    expect(queryByTestId("menu")).toBeNull();
  });

  it("should not add padding when Side Menu is active", () => {
    (getMenuPlugin as jest.Mock).mockReturnValue({
      identifier: SIDE_MENU_PLUGIN_ID,
    });

    (isBottomTabVisible as jest.Mock).mockReturnValue(false);

    mockUseNavigation.mockReturnValue({
      activeRiver: { navigations: [] },
      videoModalState: { visible: false, mode: "MINIMIZED" },
      isVideoModalDocked: false,
      currentRoute: "home",
      data: {},
    });

    const { getByTestId } = renderWithProviders(<Layout />);

    expect(getByTestId("transitioner").props.contentStyle.paddingBottom).toBe(
      0
    );
  });
});
