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

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

import {
  useCurrentScreenIsHook,
  useCurrentScreenIsStartupHook,
  useIsStandaloneFullscreen,
} from "@applicaster/zapp-react-native-utils/reactHooks/screen";

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

jest.mock("@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor");
jest.mock("../hooks");
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen");

const mockUseSubscriberFor = useSubscriberFor as jest.Mock;

const setupFocusManager = (overrides: Partial<typeof focusManager>) => {
  Object.assign(focusManager, overrides);
};

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

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

    return <></>;
  };

  const Wrapped = withBackToTopActionHOC(BaseComponent);

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

    mockUseSubscriberFor.mockImplementation(() => jest.fn());

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

    setupFocusManager({
      isFocusOnMenu: () => false,
      isFocusOnContent: () => false,
      isTabsScreenContentFocused: () => false,
    });
  });

  it("returns PLATFORM_BACK for startup hook", () => {
    expect.assertions(1);

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

    render(<Wrapped />);

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

  it("returns GO_BACK_FROM_HOOK when isHook", () => {
    expect.assertions(1);

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

    render(<Wrapped />);

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

  it("returns GO_HOME for standalone full screen", () => {
    expect.assertions(1);

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

    render(<Wrapped />);

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

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

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

    setupFocusManager({
      isFocusOnMenu: () => true,
    });

    render(<Wrapped />);

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

  it("returns GO_HOME when root + menu focus + NOT home", () => {
    expect.assertions(1);

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

    setupFocusManager({
      isFocusOnMenu: () => true,
    });

    render(<Wrapped />);

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

  it("returns FOCUS_ON_SELECTED_TAB_ITEM when tabs content focused", () => {
    expect.assertions(1);

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

    setupFocusManager({
      isTabsScreenContentFocused: () => true,
    });

    render(<Wrapped />);

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

  it("returns FOCUS_ON_SELECTED_TOP_MENU_ITEM when content focused", () => {
    expect.assertions(1);

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

    setupFocusManager({
      isFocusOnContent: () => true,
    });

    render(<Wrapped />);

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

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

    render(<Wrapped />);

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