import { Dispatch } from 'react-redux';

import { logger } from 'tachyon-logger';
import { RootState } from 'mweb/common/reducers/root';
import { Location } from 'mweb/common/reducers/app';
import {
  OptOutCookieName,
  MOBILE_OPT_OUT_COOKIE_NAME,
  UPSELL_OPT_OUT_COOKIE_NAME,
} from 'mweb/common/utils/cookie';
import { trackingTrackPageView } from 'mweb/common/actions/tracking';
import { fetchBranchURL } from 'branch-io';

export const NAVIGATION_UPDATED_LOCATION_ACTION_TYPE =
  'NAVIGATION_UPDATED_LOCATION_ACTION_TYPE';
export interface NavigationUpdatedLocationAction {
  readonly type: typeof NAVIGATION_UPDATED_LOCATION_ACTION_TYPE;
  readonly payload: {
    readonly location: Location;
  };
}

export const NAVIGATION_SWITCHED_TO_DESKTOP_ACTION_TYPE =
  'NAVIGATION_SWITCHED_TO_DESKTOP_ACTION_TYPE';
export interface NavigationSwitchedToDesktopAction {
  readonly type: typeof NAVIGATION_SWITCHED_TO_DESKTOP_ACTION_TYPE;
  readonly payload: {
    readonly cookieName: OptOutCookieName;
  };
}

export const NAVIGATION_LOADED_BRANCH_DEEPLINK_URL =
  'NAVIGATION_LOADED_BRANCH_DEEPLINK_URL';
export interface NavigationLoadedBranchDeeplinkURLAction {
  readonly type: typeof NAVIGATION_LOADED_BRANCH_DEEPLINK_URL;
  readonly payload: {
    readonly url: string;
  };
}

export type NavigationAction =
  | NavigationUpdatedLocationAction
  | NavigationSwitchedToDesktopAction
  | NavigationLoadedBranchDeeplinkURLAction;

export function navigationUpdateLocation(
  location: Location,
): (dispatch: Dispatch<RootState>) => void {
  return dispatch => {
    dispatch(navigationUpdatedLocationActionBuilder(location));
    dispatch(trackingTrackPageView(location));
    dispatch(navigationFetchBranchDeeplinkURL(location));
  };
}

export function navigationUpdatedLocationActionBuilder(
  location: Location,
): NavigationUpdatedLocationAction {
  return {
    type: NAVIGATION_UPDATED_LOCATION_ACTION_TYPE,
    payload: {
      location,
    },
  };
}

export function navigationFetchBranchDeeplinkURL(
  location: Location,
): (dispatch: Dispatch<RootState>, getState: () => RootState) => Promise<void> {
  return async (dispatch, getState) => {
    try {
      const { sessionID, deviceID } = getState().device;
      const url = await fetchBranchURL(location, sessionID, deviceID);
      dispatch(navigationLoadBranchDeeplinkURL(url));
    } catch (fetchBranchURLError) {
      logger.warn(fetchBranchURLError);
    }
  };
}

export function navigationLoadBranchDeeplinkURL(
  url: string,
): NavigationLoadedBranchDeeplinkURLAction {
  return {
    type: NAVIGATION_LOADED_BRANCH_DEEPLINK_URL,
    payload: {
      url,
    },
  };
}

function navigationSwitchToDesktop(
  cookieName: OptOutCookieName,
): NavigationSwitchedToDesktopAction {
  return {
    type: NAVIGATION_SWITCHED_TO_DESKTOP_ACTION_TYPE,
    payload: {
      cookieName,
    },
  };
}

export function navigationDeclineMobileWebExperience(): NavigationSwitchedToDesktopAction {
  return navigationSwitchToDesktop(MOBILE_OPT_OUT_COOKIE_NAME);
}

export function navigationDeclineUpsell(): NavigationSwitchedToDesktopAction {
  return navigationSwitchToDesktop(UPSELL_OPT_OUT_COOKIE_NAME);
}

// Tracked events

export const PAGEVIEW_EVENT_TYPE = 'pageview';
export interface PageviewEvent {
  type: typeof PAGEVIEW_EVENT_TYPE;
}
