import React, { useEffect, useMemo, useState } from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { createStructuredSelector } from 'reselect';
import { Undefinable } from 'tsdef';
import { withReducer } from '../../app/core/with-reducer';
import { withEpics } from '../../app/core/with-epics';
import { fp as _ } from '../../common/utils/fp';
import { MarketSelector } from '../components';
import reducer, { ACTION } from '../reducer';
import { ACTION as COMMON_ACTION } from '../../common/reducer';
import { ACTION as NOTIFICATION_SETTINGS_ACTION } from '../../notification-settings/reducer';
import * as epics from '../epics';
import { withErrorBoundary } from '../../common/hoc/with-error-boundary';
import {
  makeVisibilityConfigSelector,
  makeRefreshSelector,
  makeMarketVariantSelector,
  makeActiveSelector,
  makeSortedSelector,
  makeSearchSelector,
  makeYoutubeMarketsVisibilitySelector,
  makeSortedYoutubeSelector,
  makeSortedTiktokSelector,
  makeTiktokMarketsVisibilitySelector,
  makePlaylistMarketsVisibilitySelector,
} from '../selectors';
import { MARKET_VARIANT_PARAMS, MODULE_NAME } from '../constants';
import { withNavigationSync } from '../../common/hoc/with-navigation-sync';
import {
  makeMarketCodeSelector,
  makeMarketsAssocSelector,
} from '../../common/selectors';

import { updateAnalytics } from '../services';
import { TEntityVisibility, TMarket, TMarketsAssoc } from '../../common/types';
import {
  TEntityMarket,
  TMarketSelectorRootState,
  TMarketSourcePage,
  TNavigation,
  TSetActive,
} from '../types';
import { withMarkets } from '../../common/hoc/with-markets';
import { TUpdateNotificationSettings } from '../../notification-settings/types';

type TStructured = {
  visibility: TEntityVisibility;
  refreshing: boolean;
  markets: TEntityMarket;
  marketVariant: Undefinable<TMarketSourcePage>;
  active: Undefinable<string>;
  searchValue: Undefinable<string>;
  userMarket: Undefinable<string>;
  marketsAssoc: TMarketsAssoc;
  youtubeMarkets: TEntityMarket;
  youtubeVisibility: TEntityVisibility;
  tiktokMarkets: TEntityMarket;
  tiktokVisibility: TEntityVisibility;
  playlistMarketsVisibility: TEntityVisibility;
};
type TConnected = TStructured & {
  navigation: any;
  route: {
    params: TNavigation & {
      homeMarket: string;
      playlistrootMarket: string;
      marketCodePlaylistOwner: string;
      marketCodePlaylistStreams: string;
      marketCodeYoutube?: string;
      marketCodeTiktok?: string;
      playlistrootPerformanceMarket?: string;
    };
  };
  getMarkets: () => void;
  getYoutubeMarkets: () => void;
  getTiktokMarkets: () => void;
  getPlaylistMarkets: () => void;
  setActive: TSetActive;
  flush: () => void;
  setUserMarket: (market: TMarket) => void;
  setSearch: (value: Undefinable<string>) => void;
  refresh: () => void;
  updateNotificationSettings: TUpdateNotificationSettings;
};
type TPropsExternal = {};

const mapStateToProps = createStructuredSelector<
  TMarketSelectorRootState,
  TStructured
>({
  visibility: makeVisibilityConfigSelector(),
  refreshing: makeRefreshSelector(),
  markets: makeSortedSelector(),
  marketVariant: makeMarketVariantSelector(),
  active: makeActiveSelector(),
  searchValue: makeSearchSelector(),
  userMarket: makeMarketCodeSelector(),
  marketsAssoc: makeMarketsAssocSelector(),
  youtubeMarkets: makeSortedYoutubeSelector(),
  youtubeVisibility: makeYoutubeMarketsVisibilitySelector(),
  tiktokMarkets: makeSortedTiktokSelector(),
  tiktokVisibility: makeTiktokMarketsVisibilitySelector(),
  playlistMarketsVisibility: makePlaylistMarketsVisibilitySelector(),
  //†prop
});
const mapDispatchToProps = {
  getMarkets: ACTION.getMarkets,
  flush: ACTION.flush,
  refresh: ACTION.refresh,
  setActive: ACTION.setActive,
  setUserMarket: COMMON_ACTION.setMarket,
  setSearch: ACTION.setSearch,
  updateNotificationSettings:
    NOTIFICATION_SETTINGS_ACTION.updateNotificationSettings,
  getYoutubeMarkets: ACTION.getYoutubeMarkets,
  getTiktokMarkets: ACTION.getTiktokMarkets,
  getPlaylistMarkets: ACTION.getPlaylistMarkets,
  //†action
};

// Uncomment to write componentDidMount hook
const Connected = ({
  getMarkets,
  setActive,
  marketVariant,
  flush,
  userMarket,
  marketsAssoc,
  setUserMarket,
  getYoutubeMarkets,
  youtubeMarkets,
  youtubeVisibility,
  getTiktokMarkets,
  getPlaylistMarkets,
  tiktokMarkets,
  tiktokVisibility,
  playlistMarketsVisibility,
  ...rest
}: TConnected) => {
  const { route } = rest;
  const {
    marketCode,
    marketCodes,
    homeMarket,
    playlistrootMarket,
    playlistrootPerformanceMarket,
    marketCodePlaylistOwner,
    marketCodePlaylistStreams,
    marketCodeYoutube,
    marketCodeTiktok,
  } = route.params!;
  const [localVariant] = useState(marketVariant);
  const isYoutube =
    marketVariant === MARKET_VARIANT_PARAMS.youtubeVideo ||
    marketVariant === MARKET_VARIANT_PARAMS.youtubeAllVideos;
  const isTiktok = marketVariant === MARKET_VARIANT_PARAMS.tiktok;
  const isPlaylist = marketVariant === MARKET_VARIANT_PARAMS.playlist;
  // const isPlaylistPerformance =
  //   marketVariant === MARKET_VARIANT_PARAMS.playlistPerformance;

  useEffect(() => {
    if (isYoutube) {
      getYoutubeMarkets();
      return () => flush();
    }
    if (isTiktok) {
      getTiktokMarkets();
      return () => flush();
    }

    if (isPlaylist) {
      getPlaylistMarkets();
      return () => flush();
    }

    getMarkets();

    return () => flush();
  }, []);

  const marketsConfig = {
    profile: userMarket,
    market: marketCode,
    trackMarkets: userMarket,
    home: homeMarket,
    playlist: playlistrootMarket,
    notificationSettings: marketCodes,
    trackPlaylistSpotifyOwner: marketCodePlaylistOwner,
    trackPlaylistSpotifyStreams: marketCodePlaylistStreams,
    trackPlaylistAppleOwner: marketCodePlaylistOwner,
    trackPlaylistAmazonOwner: marketCodePlaylistOwner,
    youtubeVideo: marketCodeYoutube,
    youtubeAllVideos: marketCodeYoutube,
    tiktok: marketCodeTiktok,
    playlistPerformance: playlistrootPerformanceMarket,
  };
  const activeRouteMarket = useMemo(() => {
    const code = marketsConfig[marketVariant as TMarketSourcePage];
    return code;
  }, [marketsConfig, marketVariant]);

  useEffect(() => {
    setActive(activeRouteMarket!);
  }, [activeRouteMarket]);

  useEffect(() => {
    updateAnalytics(localVariant!);
  }, []);

  if (!marketVariant && !localVariant) {
    return null;
  }

  return (
    <MarketSelector
      {...rest}
      markets={
        isYoutube ? youtubeMarkets : isTiktok ? tiktokMarkets : rest.markets
      }
      visibility={
        isYoutube
          ? youtubeVisibility
          : isTiktok
          ? tiktokVisibility
          : isPlaylist
          ? playlistMarketsVisibility
          : rest.visibility
      }
      marketVariant={marketVariant! || localVariant!}
      setActive={setActive}
      userMarket={userMarket}
      setUserMarket={code => setUserMarket(_.path(code, marketsAssoc!))}
      marketCodePlaylistOwner={marketCodePlaylistOwner}
      marketCodePlaylistStreams={marketCodePlaylistStreams}
      activeRouteMarket={activeRouteMarket}
    />
  );
};

export default compose(
  _.hoistStatics(MarketSelector),
  withReducer(MODULE_NAME, reducer),
  withEpics(MODULE_NAME, epics),
  withErrorBoundary(MODULE_NAME),
  withNavigationSync(),
  withMarkets,
  connect(
    mapStateToProps,
    mapDispatchToProps
  )
)(Connected) as React.FC<TPropsExternal>;
