import React, { memo, useCallback } from 'react';
import { Platform, Keyboard, Pressable } from 'react-native';
import { RefreshableView } from '../../common/components/refreshable-view';
import { theme } from '../../app/theme';
import { SBoxAnimated } from '../../common/s-components/layout/s-box-animated';
import { ViewLoadFailed } from '../../common/components/view-load-failed';
import { ViewNetworkFailed } from '../../common/components/view-network-failed';
import { SBox } from '../../common/s-components/layout/s-box';
import {
  getStatusBarHeight,
  addSafeArea,
  detectIosDeviceSafeArea,
  getAnimations,
} from '../../common/transducers';
import { BackButton } from '../../common/components/back-button';
import { Icon } from '../../common/components/icon';
import { SHeaderBg } from '../../track/s-components/s-header-bg';
import { SHeaderGradient } from '../../track/s-components/s-header-gradient';
import { TData } from '../../track/types';
import { Tabs } from '../../common/components/tabs';
import {
  TDateRangeOption,
  TRangeEntity,
  TRefreshableRenderer,
} from '../../common/types';
import { togglePopup } from '../../common/utils/swipeable-popup-service';
import { fp as _ } from '../../common/utils/fp';
import { Portal } from '../../common/utils/portal/portal';
import { SwipeablePopup } from '../../common/components/bottom-sheet/swipeable-popup';
import { DateRange } from '../../common/components/date-range';
import { BgArc } from './bg-arc';
import { SearchInput } from '../../common/components/search-input';
import { ViewNoStreams } from './view-no-streams';
import { TActiveTab, TVisibility } from '../types';
import { RotationOverlay } from '../../common/components/rotation-overlay';
import Tab1 from '../containers/tab1';
import Tab2 from '../containers/tab2';
import { updateTabAnalytics } from '../services';
import { datepickerOpened, DATEPICKER_SOURCE } from '../../analytics';
import { ROUTES } from '../../app/constants';
import { Router } from '../../common/utils/navigation-service';
import { SkeletonsSmall } from '../../common/components/skeleton-small';
import { SH3 } from '../../common/s-components/typography/s-h3';
import { SRow } from '../../common/s-components/layout/s-row';
import { SPageTitle } from '../s-components/s-page-title';
import { SDateRange } from '../s-components/s-date-range';

const maxHeight = addSafeArea(123);
const minHeight = addSafeArea(82);
const safeArea = getStatusBarHeight();
const heightDiff = maxHeight - minHeight;

type TProps = {
  trackData: TData | {};
  refreshing: boolean;
  refresh: () => void;
  dateRange?: TRangeEntity | undefined;
  preSetDateRange: () => void;
  setActiveTab: (tab: TActiveTab) => void;
  search: string;
  visibility: TVisibility;
  setSearch: (str: string) => void;
  dateRangeOptions: TDateRangeOption[];
  activeTab?: TActiveTab;
  loaded: boolean;
};

const Animation = getAnimations({
  headerBg: {
    opacity: {
      inputRange: [0, heightDiff],
      outputRange: [0, 1],
    },
    translateY: {
      inputRange: [0, heightDiff],
      outputRange: [0, -heightDiff],
    },
  },

  title: {
    opacity: {
      inputRange: [0, heightDiff / 2, heightDiff / 1.5, heightDiff],
      outputRange: [1, 1, 0, 0],
    },
    translateY: {
      inputRange: [0, heightDiff / 1.5, heightDiff / 1.5, heightDiff],
      outputRange: [safeArea + 21, safeArea + 12, safeArea - 80, safeArea - 80],
    },
  },

  titleSmall: {
    opacity: {
      inputRange: [0, heightDiff / 2, heightDiff / 1.5, heightDiff],
      outputRange: [0, 0, 1, 1],
    },
    translateY: {
      inputRange: [0, heightDiff / 3, heightDiff / 2, heightDiff],
      outputRange: [safeArea + 45, safeArea + 45, safeArea + 20, safeArea + 3],
    },
    scaleY: {
      inputRange: [0, heightDiff / 3, heightDiff / 2],
      outputRange: [0, 1, 1],
    },
  },

  arrow: {
    translateY: {
      inputRange: [0, heightDiff],
      outputRange: [safeArea + 12, safeArea],
    },
  },

  tabs: {
    translateY: {
      inputRange: [0, heightDiff],
      outputRange: [safeArea + 101, safeArea + 59],
    },
  },

  searchBox: {
    translateY: {
      inputRange: [0, heightDiff / 1.5, heightDiff / 1.5, heightDiff],
      outputRange: [safeArea + 156, safeArea + 144, safeArea + 144, -44],
    },
    opacity: {
      inputRange: [0, heightDiff / 1.5, heightDiff / 1.5, heightDiff],
      outputRange: [1, 1, 0, 0],
    },
  },
  input: {
    translateY: 0,
    scaleY: {
      inputRange: [0, heightDiff / 1.5, heightDiff],
      outputRange: [1, 0, 0],
    },
  },
});

export const Markets: React.FC<TProps> = memo(props => {
  const {
    refreshing,
    refresh,
    activeTab,
    loaded,
    dateRangeOptions,
    preSetDateRange,
    dateRange,
    setActiveTab,
    search,
    setSearch,
    visibility,
    trackData,
  } = props;
  const indicatorOffsetTop = activeTab === 'all' ? 100 : 15;

  const infoPressHandler = (variant: 'date-range-markets') => {
    togglePopup(variant);
  };

  const goBack = () => {
    Router.goBack();
  };

  const goToMarket = (marketCode: string) => {
    Router.goTo(ROUTES.market, {
      marketCode,
    });
  };

  const renderFgLayer = useCallback(() => {
    const days = _.path('days', dateRange);

    return (
      <Portal id="markets" updateIfAnyChanged={{ days }}>
        <SwipeablePopup
          fullheight
          variant="date-range-markets"
          content={
            <DateRange
              rangeTitle="Streams Period"
              value={days!}
              options={dateRangeOptions}
              onRange={preSetDateRange}
              confirmRange={() => {
                setTimeout(() => {
                  togglePopup('date-range-markets');
                }, 100);
              }}
              source={DATEPICKER_SOURCE.STREAMS_BY_MARKET}
            />
          }
        />
      </Portal>
    );
  }, [dateRangeOptions, preSetDateRange, dateRange]);

  const renderFgLayer2 = () => <RotationOverlay />;

  const renderHeader: TRefreshableRenderer = useCallback(
    ({ animationY, scrollToTop, isScrolled }) => {
      const { offline, empty, error, skeleton } = visibility;

      const onPress = () => {
        if (isScrolled) {
          scrollToTop();
        } else {
          infoPressHandler('date-range-markets');
          datepickerOpened({
            datepicker_source: DATEPICKER_SOURCE.STREAMS_BY_MARKET,
          });
          Keyboard.dismiss();
        }
      };

      return (
        <>
          {!(offline || error) ? (
            <>
              <SBoxAnimated
                style={Animation.headerBg(animationY)}
                height={maxHeight}
                bg={theme.colors.vulcan}
                position="absolute"
                width={1}
              />
              <SBoxAnimated
                style={Animation.title(animationY)}
                position="absolute"
                width={1}
              >
                <Pressable onPress={onPress} testID="markets">
                  {({ pressed }) => (
                    <SBox opacity={pressed ? 0.7 : 1}>
                      <SRow justifyContent="center">
                        <SPageTitle>Streams by Market</SPageTitle>
                        <Icon
                          name="down-ind"
                          size={12}
                          color="white"
                          pl={9}
                          pt={7}
                        />
                      </SRow>

                      {skeleton && !dateRange ? (
                        <SBox alignItems="center" mt={3}>
                          <SkeletonsSmall width={80} />
                        </SBox>
                      ) : null}
                      <SBox mt={7}>
                        <SDateRange>{_.path('standard', dateRange)}</SDateRange>
                      </SBox>
                    </SBox>
                  )}
                </Pressable>
              </SBoxAnimated>

              <SBoxAnimated
                style={Animation.titleSmall(animationY)}
                position="absolute"
                alignItems="center"
                width={1}
              >
                <Pressable onPress={onPress} testID="markets">
                  {({ pressed }) => (
                    <SBox opacity={pressed ? 0.7 : 1} py={10} px={5}>
                      <SH3>Streams by Market</SH3>
                    </SBox>
                  )}
                </Pressable>
              </SBoxAnimated>
            </>
          ) : null}

          {!(offline || empty || error) ? (
            <SBoxAnimated
              style={Animation.tabs(animationY)}
              position="absolute"
              width={1}
            >
              <Tabs
                // testID="markets-tabs"
                active={activeTab}
                tabs={[
                  { id: 'top', name: 'top 5 markets' },
                  { id: 'all', name: 'all markets' },
                ]}
                onSelect={(tab: string) => {
                  setActiveTab(tab as TActiveTab);
                  updateTabAnalytics();
                }}
              />
            </SBoxAnimated>
          ) : null}

          {!(offline || error || empty) && activeTab === 'all' ? (
            <SBoxAnimated
              style={[Animation.searchBox(animationY)]}
              width={1}
              position="absolute"
            >
              <SBoxAnimated style={[Animation.input(animationY)]} mx={16}>
                <SearchInput
                  value={search}
                  placeholder="Find a market"
                  onChange={(val: string) => {
                    setSearch(val);
                    setTimeout(() => {
                      scrollToTop(true);
                    }, 100);
                  }}
                />
              </SBoxAnimated>
            </SBoxAnimated>
          ) : null}

          <SBoxAnimated
            style={[Animation.arrow(animationY)]}
            position="absolute"
            left={16}
          >
            <BackButton testID="markets-back-button" onPress={goBack} fixed />
          </SBoxAnimated>
        </>
      );
    },
    [setActiveTab, activeTab, dateRange, search, setSearch, visibility]
  );

  const renderBody = useCallback(() => {
    const isIos = Platform.OS === 'ios';
    const oldIosTopOffset = isIos && !detectIosDeviceSafeArea() ? 240 : 210;
    const dataOffset = activeTab === 'top' ? oldIosTopOffset : 318;
    const emptyOffset = 142;
    const topOffset = visibility.empty ? emptyOffset : dataOffset;
    const { skeleton, data, empty, error, offline } = visibility;
    const topPadding = error || offline ? 0 : maxHeight + 33;
    const noPeriodTopOffset = isIos ? 36 : 70;
    const offlineTopOffset = isIos ? 5 : -90;

    return (
      <>
        <SBox position="relative" flex={1} pt={topPadding}>
          {!(error || offline) ? (
            <BgArc
              statusBarHeight={false}
              bg={theme.colors.mirage}
              arcBg={theme.colors.ebonyClay}
              gradient={theme.gradients.marketStreams}
              topOffset={topOffset}
            />
          ) : null}

          {error ? (
            <ViewLoadFailed
              variant="markets"
              verticalOffset={3}
              // maxHeight={-85}
              // minHeight={0}
            />
          ) : null}

          {offline ? (
            <ViewNetworkFailed verticalOffset={offlineTopOffset} />
          ) : null}

          {empty ? <ViewNoStreams verticalOffset={noPeriodTopOffset} /> : null}

          {activeTab === 'top' ? (
            <Tab1
              onCardClick={goToMarket}
              show={!offline && (skeleton || data)}
            />
          ) : null}
          {activeTab === 'all' ? (
            <Tab2
              onCardClick={goToMarket}
              show={!offline && (skeleton || data)}
            />
          ) : null}
        </SBox>
      </>
    );
  }, [activeTab, visibility]);

  const renderBgLayer2 = useCallback(() => {
    const image_url = _.path('image_url', trackData);
    const { error, offline } = visibility;

    if (offline || error) return null;

    return (
      <SBox position="relative" height={400}>
        {image_url ? (
          <SHeaderBg top={0} source={{ uri: image_url }} />
        ) : (
          <SBox
            height={375}
            width="100%"
            position="absolute"
            top={0}
            bg={theme.colors.lavenderGray}
          />
        )}
        <SHeaderGradient
          height={375}
          top={0}
          colors={theme.gradients.marketsTrackAvatar}
          location={[0.1, 0.6, 1]}
        />
        <SHeaderGradient
          top={273}
          height={102}
          colors={theme.gradients.trackShadow}
          location={[0, 0.2, 1]}
        />
      </SBox>
    );
  }, [trackData, visibility]);

  return (
    <RefreshableView
      testID="markets-refreshable-view"
      indicatorLight
      indicatorOffsetTop={maxHeight + indicatorOffsetTop}
      loading={refreshing}
      renderBgLayer2={renderBgLayer2}
      onPullDown={() => {
        if (loaded) {
          refresh();
        }
      }}
      renderHeader={renderHeader}
      renderBody={renderBody}
      renderFgLayer={renderFgLayer}
      renderFgLayer2={renderFgLayer2}
      name={ROUTES.markets}
      withNativeDriver
    />
  );
});
