import React from 'react';
import { renderHook, cleanup } from '@testing-library/react-hooks';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';
import { ACTION } from '../../reducer';

/*
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { NavigationStackProp } from 'react-navigation-stack';
import { NavigationScreenProp } from 'react-navigation';
import { ACTION } from '../reducer';

export const useFocusPage = ({
  navigation,
  page,
}: {
  navigation: NavigationStackProp<any> | NavigationScreenProp<any, any>;
  page: string;
}) => {
  const d = useDispatch();
  const setFocus = (o: { focus?: string; blur?: string }) =>
    d(ACTION.toggleFocusPage(o));

  useEffect(() => {
    setFocus({ focus: page });

    const didBlurSubscription = navigation.addListener('willBlur', () => {
      setFocus({ blur: page });
    });
    const willFocusSubscription = navigation.addListener('willFocus', () => {
      setFocus({ focus: page });
    });

    // Remove the listener when you are done
    return () => {
      didBlurSubscription.remove();
      willFocusSubscription.remove();
    };
  }, []);
};
*/




describe('useFocusPage hook', () => {
  let removeListener;
  let navigation;

  let middlewares;
  let mockStore;
  let spies;
  let page;

  beforeEach(() => {
    middlewares = [];
    mockStore = configureStore(middlewares);
    spies = [];
    page = 'PAGE';
  });

  beforeEach(() => {
    removeListener = jest.fn((navigation, eventName) => {
      delete navigation.events[eventName];
    });

    navigation = {
      events: {},
      addListener: (eventName, callback) => {
        navigation.events[eventName] = callback;

        return {
          remove: () => {
            removeListener(navigation, eventName);
          },
        };
      },
      trigger: (eventName, payload) => {
        if (navigation.events[eventName]) {
          navigation.events[eventName](payload);
        }
      },
    };
  });

  afterEach(() => {
    spies.forEach(spy => {
      spy.mockRestore();
    });
  });

  afterEach(() => {
    cleanup();
  });

  it('should trigger toggleFocusPage on page mount', () => {
    const store = mockStore();
    store.dispatch = jest.fn();

    const wrapper = ({ children }) => (
      <Provider store={store}>{children}</Provider>
    );

    renderHook(() => useFocusPage({ navigation, page }), { wrapper });

    expect(store.dispatch).toHaveBeenCalledWith(
      ACTION.toggleFocusPage({
        focus: page,
      }),
    );
  });

  it('should trigger toggleFocusPage in case switch to blur', () => {
    const store = mockStore();
    store.dispatch = jest.fn();

    const wrapper = ({ children }) => (
      <Provider store={store}>{children}</Provider>
    );

    renderHook(() => useFocusPage({ navigation, page }), { wrapper });

    navigation.trigger('willBlur');

    expect(store.dispatch).toHaveBeenNthCalledWith(
      1,
      ACTION.toggleFocusPage({ focus: page }),
    );
    expect(store.dispatch).toHaveBeenNthCalledWith(
      2,
      ACTION.toggleFocusPage({ blur: page }),
    );
  });

  it('should trigger toggleFocusPage in case switch to focus', () => {
    const store = mockStore();
    store.dispatch = jest.fn();

    const wrapper = ({ children }) => (
      <Provider store={store}>{children}</Provider>
    );

    renderHook(() => useFocusPage({ navigation, page }), { wrapper });

    navigation.trigger('willFocus');

    expect(store.dispatch).toHaveBeenNthCalledWith(
      1,
      ACTION.toggleFocusPage({ focus: page }),
    );
    expect(store.dispatch).toHaveBeenNthCalledWith(
      2,
      ACTION.toggleFocusPage({ focus: page }),
    );
  });

  it('should remove listeners on unmount', () => {
    const store = mockStore();
    store.dispatch = jest.fn();

    const wrapper = ({ children }) => (
      <Provider store={store}>{children}</Provider>
    );

    const { unmount } = renderHook(() => useFocusPage({ navigation, page }), {
      wrapper,
    });

    unmount();

    expect(removeListener).toHaveBeenNthCalledWith(1, navigation, 'willBlur');
    expect(removeListener).toHaveBeenNthCalledWith(2, navigation, 'willFocus');
  });
});
