import React from "react";
import { render } from "@testing-library/react-native";
import { withBackToTopActionHOC } from "../withBackToTopAction";

// Mock focusManager and hook
jest.mock("@applicaster/zapp-react-native-utils/appUtils", () => ({
  focusManager: {
    isFocusOnMenu: jest.fn(),
    isFocusOnContent: jest.fn(),
    isTabsScreenContentFocused: jest.fn(),
  },
}));

jest.mock("../hooks", () => ({
  useCurrentScreenIsHome: jest.fn(),
  useCurrentScreenIsRoot: jest.fn(),
  useCurrentScreenIsTabs: jest.fn(),
}));

import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils";
import {
  useCurrentScreenIsHome,
  useCurrentScreenIsRoot,
  useCurrentScreenIsTabs,
} from "../hooks";

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

import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";

describe("withBackToTopActionHOC", () => {
  let receivedProps: any;

  const BaseComponent = (props) => {
    receivedProps = props; // capture injected props

    return <></>;
  };

  const Wrapped = withBackToTopActionHOC(BaseComponent);

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

  it("returns PLATFORM_BACK when on root screen, and startup hooks", () => {
    expect.assertions(1);

    (useCurrentScreenIsRoot as jest.Mock).mockReturnValue(true);

    (useNavigation as jest.Mock).mockReturnValue({
      startUpHooks: ["some_startup_hook"],
    });

    render(<Wrapped />);

    expect(receivedProps.backToTopAction()).toBe("PLATFORM_BACK");
  });

  it("returns PLATFORM_BACK when on root screen, focus on menu, and is home", () => {
    expect.assertions(1);

    (useCurrentScreenIsRoot as jest.Mock).mockReturnValue(true);
    (useCurrentScreenIsHome as jest.Mock).mockReturnValue(true);
    (useCurrentScreenIsTabs as jest.Mock).mockReturnValue(false);

    (useNavigation as jest.Mock).mockReturnValue({
      startUpHooks: [],
    });

    (focusManager.isFocusOnMenu as jest.Mock).mockReturnValue(true);
    (focusManager.isFocusOnContent as jest.Mock).mockReturnValue(false);

    render(<Wrapped />);

    expect(receivedProps.backToTopAction()).toBe("PLATFORM_BACK");
  });

  it("returns GO_HOME when on root screen, focus on menu, and not home", () => {
    expect.assertions(1);

    (useCurrentScreenIsRoot as jest.Mock).mockReturnValue(true);
    (useCurrentScreenIsHome as jest.Mock).mockReturnValue(false);
    (useCurrentScreenIsTabs as jest.Mock).mockReturnValue(false);

    (useNavigation as jest.Mock).mockReturnValue({
      startUpHooks: [],
    });

    (focusManager.isFocusOnMenu as jest.Mock).mockReturnValue(true);
    (focusManager.isFocusOnContent as jest.Mock).mockReturnValue(false);

    render(<Wrapped />);
    expect(receivedProps.backToTopAction()).toBe("GO_HOME");
  });

  it("returns FOCUS_ON_SELECTED_TOP_MENU_ITEM when on root screen and focus on content without tabs_screen", () => {
    (useCurrentScreenIsRoot as jest.Mock).mockReturnValue(true);
    (useCurrentScreenIsHome as jest.Mock).mockReturnValue(false);
    (useCurrentScreenIsTabs as jest.Mock).mockReturnValue(false);

    (useNavigation as jest.Mock).mockReturnValue({
      startUpHooks: [],
    });

    (focusManager.isFocusOnMenu as jest.Mock).mockReturnValue(false);
    (focusManager.isFocusOnContent as jest.Mock).mockReturnValue(true);

    render(<Wrapped />);

    expect(receivedProps.backToTopAction()).toBe(
      "FOCUS_ON_SELECTED_TOP_MENU_ITEM"
    );
  });

  it("returns FOCUS_ON_SELECTED_TAB_ITEM when on root screen and focus on content with tabs_screen", () => {
    (useCurrentScreenIsRoot as jest.Mock).mockReturnValue(true);
    (useCurrentScreenIsHome as jest.Mock).mockReturnValue(false);
    (useCurrentScreenIsTabs as jest.Mock).mockReturnValue(true);

    (useNavigation as jest.Mock).mockReturnValue({
      startUpHooks: [],
    });

    (focusManager.isFocusOnMenu as jest.Mock).mockReturnValue(false);
    (focusManager.isFocusOnContent as jest.Mock).mockReturnValue(true);

    (focusManager.isTabsScreenContentFocused as jest.Mock).mockReturnValue(
      true
    );

    render(<Wrapped />);

    expect(receivedProps.backToTopAction()).toBe("FOCUS_ON_SELECTED_TAB_ITEM");
  });

  it("returns GO_BACK in default case", () => {
    expect.assertions(1);

    (useCurrentScreenIsRoot as jest.Mock).mockReturnValue(false);
    (useCurrentScreenIsHome as jest.Mock).mockReturnValue(false);
    (useCurrentScreenIsTabs as jest.Mock).mockReturnValue(false);

    (useNavigation as jest.Mock).mockReturnValue({
      startUpHooks: [],
    });

    (focusManager.isFocusOnMenu as jest.Mock).mockReturnValue(false);
    (focusManager.isFocusOnContent as jest.Mock).mockReturnValue(false);

    (focusManager.isTabsScreenContentFocused as jest.Mock).mockReturnValue(
      false
    );

    render(<Wrapped />);
    expect(receivedProps.backToTopAction()).toBe("GO_BACK");
  });

  it("returns FORCE_GO_BACK in hook case", () => {
    expect.assertions(1);

    (useCurrentScreenIsRoot as jest.Mock).mockReturnValue(false);
    (useCurrentScreenIsHome as jest.Mock).mockReturnValue(false);
    (useCurrentScreenIsTabs as jest.Mock).mockReturnValue(false);

    (useNavigation as jest.Mock).mockReturnValue({
      startUpHooks: [],
      currentRoute: "/hooks/some_route",
    });

    (focusManager.isFocusOnMenu as jest.Mock).mockReturnValue(false);
    (focusManager.isFocusOnContent as jest.Mock).mockReturnValue(false);

    (focusManager.isTabsScreenContentFocused as jest.Mock).mockReturnValue(
      false
    );

    render(<Wrapped />);
    expect(receivedProps.backToTopAction()).toBe("FORCE_GO_BACK");
  });
});
