import { NavigationActions, NavigationNavigateAction } from 'react-navigation';
import { Allow, createLogic, Done, Reject } from 'redux-logic';
import {
  AuthActions,
  ChatActions,
  EmployeeActions,
  EmployerActions,
  NavActions,
  OfferActions,
  UserActions,
} from '../actions';
import { Dispatch, RootState, UserRole } from '../models';
import { Routes } from '../navigation';

const loginSuccessLogic = createLogic({
  type: [AuthActions.ActionKey.LOGIN_SUCCESS, AuthActions.ActionKey.INITIALIZE_USER_FLOW],
  process({ action, getState }: { action: AuthActions.LoginSuccess, getState: () => RootState },
    dispatch: Dispatch, done: Done) {
    dispatch(
      NavigationActions.reset({
        index: 0,
        actions: [NavigationActions.navigate({
          routeName:
            action.userRole === UserRole.EMPLOYEE
              ? Routes.APP_EMPLOYEE
              : Routes.APP_EMPLOYER,
        })],
      }),
    );
    if (getState().user.firstLogin) {
      dispatch(
        NavigationActions.navigate({
          routeName:
            action.userRole === UserRole.EMPLOYEE
              ? Routes.EMPLOYEE_PROFILE_EDIT
              : Routes.EMPLOYER_PROFILE_EDIT,
        }));
    }
    done();
  },
});

function shallowEquals(a: any = {}, b: any = {}) {
  return Object.keys(a).every((key) => a[key] === b[key]);
}

const preventDuplicateRoute = createLogic({
  type: 'Navigation/NAVIGATE',
  latest: true,
  validate({ action, getState }: { action: NavigationNavigateAction, getState: () => RootState },
    allow: Allow, reject: Reject) {
    const navigation = getState().navigation;
    const currentRoute = navigation.routes[navigation.index];
    const sameRoute = action.routeName === currentRoute.routeName;
    const sameParams = shallowEquals(action.params, currentRoute.params);
    if (sameRoute && sameParams) {
      reject(undefined);
    } else {
      allow(action);
    }
  },
});

const goToLogin = createLogic({
  type: [AuthActions.ActionKey.USER_UNAUTHORIZED, AuthActions.ActionKey.LOGOUT_REQUESTED],
  process({ action }: { action: ChatActions.FetchChatHistoryRequested }, dispatch: Dispatch, done: Done) {
    dispatch(
      NavigationActions.reset({
        index: 0,
        actions: [NavigationActions.navigate({ routeName: Routes.LOGIN })],
      }),
    );
    done();
  },
});
const goToUnsupported = createLogic({
  type: AuthActions.ActionKey.APP_VERSION_SUPPORT_TERMINATED,
  process({ action: { message } }: { action: AuthActions.AppVersionSupportTerminated },
    dispatch: Dispatch, done: Done) {
    dispatch(
      NavigationActions.reset({
        index: 0,
        actions: [NavigationActions.navigate({
          routeName: Routes.VERSION_UNSUPPORTED,
          params: {
            message,
          },
        })],
      }),
    );
    done();
  },
});

const goToOfferEditDetails = createLogic({
  type: NavActions.ActionKey.NAVIGATE_TO_OFFER_EDIT_DETAILS,
  process({ action }: { action: NavActions.NavigateToOfferEditDetails }, dispatch: Dispatch, done: Done) {
    dispatch(NavigationActions.navigate({
      routeName: Routes.EDIT_OFFER,
      params: {
        offer: action.offer,
      },
    }));
    done();
  },
});

const openChatLogic = createLogic({
  type: ChatActions.ActionKey.FETCH_CHAT_HISTORY_REQUESTED,
  process({ action }: { action: ChatActions.FetchChatHistoryRequested }, dispatch: Dispatch, done: Done) {
    dispatch(NavigationActions.navigate({
      routeName: Routes.CHATROOM,
      params: {
        conversationId: action.conversationId,
      },
    }));
    done();
  },
});

const logoutSuccessLogic = createLogic({
  type: [AuthActions.ActionKey.LOGOUT_SUCCESS, AuthActions.ActionKey.LOGOUT_FAIL],
  process({ action }: { action: AuthActions.LogoutSuccess }, dispatch: Dispatch, done: Done) {
    dispatch(
      NavigationActions.reset({
        index: 0,
        actions: [NavigationActions.navigate({ routeName: Routes.LOGIN })],
      }),
    );
    done();
  },
});

const popBackLogic = createLogic({
  type: [
    UserActions.ActionKey.USER_PROFILE_EDIT_SUCCESS,
    OfferActions.ActionKey.NEW_OFFER_SUCCESS,
    OfferActions.ActionKey.UPDATE_OFFER_SUCCESS,
    OfferActions.ActionKey.DELETE_OFFER_SUCCESS,
  ],
  process({ action }: { action: UserActions.UserProfileEditSuccess }, dispatch: Dispatch, done: Done) {
    dispatch(
      NavigationActions.back(),
    );
    done();
  },
});

const navigateToEmployeeDetails = createLogic({
  type: NavActions.ActionKey.NAVIGATE_TO_EMPLOYEE_DETAILS,
  process({ getState, action }: { action: NavActions.NavigateToEmployeeDetails, getState: () => RootState },
    dispatch: Dispatch, done: Done) {
    const employeeId = action.employeeId;
    if (!getState().employerData.employees[employeeId]) {
      dispatch(EmployerActions.employeeDetailsRequest(employeeId));
    }
    dispatch(NavigationActions.navigate({
      routeName: Routes.EMPLOYEE_PROFILE_DETAILS,
      params: {
        employeeId,
      },
    }));
    done();
  },
});

const navigateToEmployerDetails = createLogic({
  type: NavActions.ActionKey.NAVIGATE_TO_EMPLOYER_DETAILS,
  process({ getState, action }: { action: NavActions.NavigateToEmployerDetails, getState: () => RootState },
    dispatch: Dispatch, done: Done) {
    const employerId = action.employerId;
    if (!getState().employeeData.employers[employerId]) {
      dispatch(EmployeeActions.employerDetailsRequest(employerId));
    }
    dispatch(NavigationActions.navigate({
      routeName: Routes.EMPLOYER_PROFILE_DETAILS,
      params: {
        employerId,
      },
    }));
    done();
  },
});

export const navigationLogic = [
  loginSuccessLogic,
  logoutSuccessLogic,
  popBackLogic,
  navigateToEmployeeDetails,
  navigateToEmployerDetails,
  openChatLogic,
  goToLogin,
  goToOfferEditDetails,
  preventDuplicateRoute,
  goToUnsupported,
];
