import React, { memo, useCallback } from 'react';
import { Animated, Keyboard, Platform, Pressable } from 'react-native';
import { Undefinable } from 'tsdef';
import { SText } from '../../common/s-components/typography/s-text';
import { SH1 } from '../../common/s-components/typography/s-h1';
import { SBoxAnimated } from '../../common/s-components/layout/s-box-animated';
import { Router } from '../../common/utils/navigation-service';
import { SBox } from '../../common/s-components/layout/s-box';
import { MarketTags } from './market-tags';
import { SearchInput } from '../../common/components/search-input';
import { TLightMarketVariant, TMarketSourcePage, TSetActive } from '../types';
import {
  addSafeArea,
  getAnimations,
  getStatusBarHeight,
} from '../../common/transducers';
import { theme } from '../../app/theme';
import {
  updateMarketSelectedAnalytics,
  updatePlaylistMarketSelectedAnalytics,
  updateTiktokMarketSelectedAnalytics,
  updateYoutubeVideoViewsMarketSelectedAnalytics,
} from '../services';
import { ROUTE_PARAMS, ROUTES } from '../../app/constants';
import {
  checkIsLight,
  getHeaderTitle,
  getMarketFragments,
} from '../transducers';
import { TUpdateNotificationSettings } from '../../notification-settings/types';
import { MARKET_VARIANT_PARAMS } from '../constants';
import { TEntityVisibility } from '../../common/types';
import { SDoneContainer } from '../s-components/s-done-container';
import { useAppDispatch } from '../../app/core/redux';
import { ACTION } from '../reducer';

type TProps = {
  animationY: Animated.Value;
  isScrolled: boolean;
  scrollToTop: (withoutAnimation?: boolean) => void;
  visibility: TEntityVisibility;
  setSearch: (value: Undefinable<string>) => void;
  searchValue: Undefinable<string>;
  marketVariant: TMarketSourcePage;
  active: Undefinable<string>;
  setActive: TSetActive;
  setUserMarket: (code: string) => void;
  updateNotificationSettings: TUpdateNotificationSettings;
  userMarket: Undefinable<string>;
  marketCodePlaylistOwner?: string;
  marketCodePlaylistStreams?: string;
  activeRouteMarket?: string;
};

export const Header: React.FC<TProps> = memo(props => {
  const {
    marketVariant,
    animationY,
    isScrolled,
    scrollToTop,
    visibility,
    setSearch,
    searchValue,
    active,
    setActive,
    userMarket,
    setUserMarket,
    updateNotificationSettings,
    marketCodePlaylistOwner,
    marketCodePlaylistStreams,
    activeRouteMarket,
  } = props;
  const maxHeight = addSafeArea(
    marketVariant === MARKET_VARIANT_PARAMS.notificationSettings ? 176 : 142
  );
  const minHeight = addSafeArea(52);
  const heightDiff = maxHeight - minHeight;
  const safeArea = getStatusBarHeight();
  const lightVariant = checkIsLight(marketVariant as TLightMarketVariant);
  const titleColor = isScrolled ? 'white' : lightVariant ? 'black' : 'white';
  const headerTitle = getHeaderTitle(marketVariant);
  const noErrors = !visibility.error && !visibility.offline;
  const dispatch = useAppDispatch();

  const animation = getAnimations({
    headerBg: {
      opacity: {
        inputRange: [0, heightDiff],
        outputRange: [0, 1],
      },
      translateY: {
        inputRange: [0, heightDiff],
        outputRange: [0, -heightDiff],
      },
    },
    cancel: {
      translateY: {
        inputRange: [0, heightDiff],
        outputRange: [safeArea + 20, safeArea + 8],
      },
      translateX: 6,
    },
    done: {
      translateY: {
        inputRange: [0, heightDiff],
        outputRange: [safeArea + 20, safeArea + 8],
      },
    },
    title: {
      opacity: {
        inputRange: [0, heightDiff / 2, heightDiff],
        outputRange: [1, 0, 0],
      },
      translateY: {
        inputRange: [0, heightDiff],
        outputRange: [safeArea + 20, safeArea + 6],
      },
    },
    smallTitle: {
      translateY: {
        inputRange: [0, heightDiff],
        outputRange: [safeArea + 21, safeArea + 12],
      },
      opacity: {
        inputRange: [0, heightDiff / 2, heightDiff],
        outputRange: [0, 0, 1],
      },
    },
    input: {
      translateY: {
        inputRange: [0, heightDiff],
        outputRange: [safeArea + 88, 0],
      },
      scaleY: {
        inputRange: [0, heightDiff / 3, heightDiff],
        outputRange: [1, 0, 0],
      },
      opacity: {
        inputRange: [0, heightDiff / 3, heightDiff],
        outputRange: [1, 0, 0],
      },
    },
    inputMarkets: {
      translateY: {
        inputRange: [0, heightDiff / 3, heightDiff],
        outputRange: [safeArea + 204, safeArea + 176, 0],
      },
      scaleY: {
        inputRange: [0, heightDiff / 5, heightDiff],
        outputRange: [1, 0, 0],
      },
      opacity: {
        inputRange: [0, heightDiff / 3, heightDiff],
        outputRange: [1, 0, 0],
      },
    },
    marketTags: {
      translateY: {
        inputRange: [0, heightDiff],
        outputRange: [safeArea + 68, safeArea + 52],
      },
    },
  });

  const goTo = useCallback(() => {
    let switchDelay = 0;

    if (activeRouteMarket === active) {
      Router.goBack();
      return;
    }

    if (
      [
        MARKET_VARIANT_PARAMS.trackPlaylistSpotifyOwner,
        MARKET_VARIANT_PARAMS.trackPlaylistSpotifyStreams,
        MARKET_VARIANT_PARAMS.trackPlaylistAppleOwner,
        MARKET_VARIANT_PARAMS.trackPlaylistAmazonOwner,
        MARKET_VARIANT_PARAMS.playlist,
        MARKET_VARIANT_PARAMS.playlistPerformance,
      ].includes(marketVariant as MARKET_VARIANT_PARAMS)
    ) {
      updatePlaylistMarketSelectedAnalytics(marketVariant, active!);
    }

    if (
      [
        MARKET_VARIANT_PARAMS.youtubeVideo,
        MARKET_VARIANT_PARAMS.youtubeAllVideos,
      ].includes(marketVariant as MARKET_VARIANT_PARAMS)
    ) {
      updateYoutubeVideoViewsMarketSelectedAnalytics(marketVariant, active!);
    }
    if (
      [MARKET_VARIANT_PARAMS.tiktok].includes(
        marketVariant as MARKET_VARIANT_PARAMS
      )
    ) {
      updateTiktokMarketSelectedAnalytics(marketVariant, active!);
    }
    updateMarketSelectedAnalytics(marketVariant, active!);

    if (
      [
        MARKET_VARIANT_PARAMS.profile,
        MARKET_VARIANT_PARAMS.trackMarkets,
      ].includes(marketVariant as MARKET_VARIANT_PARAMS)
    ) {
      setUserMarket(active!);
    }

    if (Platform.OS === 'android') {
      Keyboard.dismiss();
      switchDelay = 50;
    }

    setTimeout(() => {
      const overrides: Record<string, string | undefined> = {
        [ROUTE_PARAMS.marketCodePlaylistOwner]: undefined,
        [ROUTE_PARAMS.marketCodePlaylistStreams]: undefined,
      };
      if (
        marketVariant === MARKET_VARIANT_PARAMS.home ||
        marketVariant === MARKET_VARIANT_PARAMS.trackMarkets
      ) {
        const params = {
          [ROUTE_PARAMS.homeMarket]: active,
        };
        Router.setParamsFor(ROUTES.home, params);
        Router.setParamsFor(ROUTES.homelist, params);
        Router.setParamsFor(ROUTES.charts, params);
        Router.setParamsFor(ROUTES.track, params);
      }
      if (
        marketVariant !== MARKET_VARIANT_PARAMS.home &&
        marketVariant !== MARKET_VARIANT_PARAMS.notificationSettings
      ) {
        overrides[ROUTE_PARAMS.marketCode] = active;
      }
      if (marketVariant === MARKET_VARIANT_PARAMS.playlist) {
        overrides[ROUTE_PARAMS.playlistrootMarket] = active;
        dispatch(ACTION.getPlaylistMarketsLoading());
      }
      if (marketVariant === MARKET_VARIANT_PARAMS.playlistPerformance) {
        // hack for compatibility - ideally we should teach playlist page - spotify performance section
        // to listen to changes of this particular element and render inside the pill this market
        overrides[ROUTE_PARAMS.playlistrootMarket] = active;
        // overrides[ROUTE_PARAMS.playlistrootPerformanceMarket] = active;
      }

      if (marketVariant === MARKET_VARIANT_PARAMS.notificationSettings) {
        updateNotificationSettings(getMarketFragments(active), ['markets']);
      }
      if (
        [
          MARKET_VARIANT_PARAMS.trackPlaylistSpotifyOwner,
          MARKET_VARIANT_PARAMS.trackPlaylistAppleOwner,
          MARKET_VARIANT_PARAMS.trackPlaylistAmazonOwner,
        ].includes(marketVariant as MARKET_VARIANT_PARAMS) &&
        ![MARKET_VARIANT_PARAMS.trackMarkets].includes(
          marketVariant as MARKET_VARIANT_PARAMS
        )
      ) {
        Router.goBack({
          [ROUTE_PARAMS.marketCodePlaylistOwner]: active,
          [ROUTE_PARAMS.marketCodePlaylistStreams]: marketCodePlaylistStreams,
          [ROUTE_PARAMS.marketVariant]: marketVariant,
        });
        return;
      }
      if (
        [MARKET_VARIANT_PARAMS.trackPlaylistSpotifyStreams].includes(
          marketVariant as MARKET_VARIANT_PARAMS
        ) &&
        ![MARKET_VARIANT_PARAMS.trackMarkets].includes(
          marketVariant as MARKET_VARIANT_PARAMS
        )
      ) {
        Router.goBack({
          [ROUTE_PARAMS.marketCodePlaylistOwner]: marketCodePlaylistOwner,
          [ROUTE_PARAMS.marketCodePlaylistStreams]: active,
          [ROUTE_PARAMS.marketVariant]: marketVariant,
        });
        return;
      }
      if (
        marketVariant === MARKET_VARIANT_PARAMS.youtubeVideo ||
        marketVariant === MARKET_VARIANT_PARAMS.youtubeAllVideos
      ) {
        Router.goBack({
          [ROUTE_PARAMS.marketCodeYoutube]: active,
        });
        return;
      }
      if (marketVariant === MARKET_VARIANT_PARAMS.tiktok) {
        Router.goBack({
          [ROUTE_PARAMS.marketCodeTiktok]: active,
        });
        return;
      }

      Router.goBack({
        [ROUTE_PARAMS.marketVariant]: undefined,
        ...overrides,
      });
    }, switchDelay);
  }, [
    active,
    marketVariant,
    setUserMarket,
    updateNotificationSettings,
    marketCodePlaylistOwner,
    marketCodePlaylistStreams,
  ]);

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

  const renderCancelBtn = useCallback(() => {
    return (
      <SBoxAnimated position="absolute" style={animation.cancel(animationY)}>
        <Pressable testID="market-selector-cancel-button" onPress={goBack}>
          {({ pressed }) => (
            <SBox opacity={pressed ? 0.7 : 1} px={10} py={5}>
              <SText semibold color={theme.colors.azureRadiance}>
                Cancel
              </SText>
            </SBox>
          )}
        </Pressable>
      </SBoxAnimated>
    );
  }, [animationY]);

  const onPress = () => {
    if (isScrolled) {
      scrollToTop();
    }
  };

  if (visibility.offline) return renderCancelBtn();

  return (
    <>
      {noErrors ? (
        <>
          <SBoxAnimated
            style={animation.headerBg(animationY)}
            height={maxHeight}
            bg={theme.colors.vulcan}
            position="absolute"
            width={1}
          />
          <SBoxAnimated
            style={animation.title(animationY)}
            alignItems="center"
            position="absolute"
            width={1}
          >
            <SH1 color={titleColor}>{headerTitle}</SH1>
          </SBoxAnimated>
        </>
      ) : null}

      {marketVariant === MARKET_VARIANT_PARAMS.notificationSettings ? (
        <SBoxAnimated
          position="absolute"
          width={1}
          style={animation.marketTags(animationY)}
        >
          <MarketTags
            userMarket={userMarket}
            value={active!}
            onChange={setActive}
          />
        </SBoxAnimated>
      ) : null}

      {noErrors ? (
        <>
          <SBoxAnimated
            position="absolute"
            width={1}
            style={
              marketVariant === MARKET_VARIANT_PARAMS.notificationSettings
                ? animation.inputMarkets(animationY)
                : animation.input(animationY)
            }
          >
            <SBox mx={16} overflow="hidden" bg="white" borderRadius={22}>
              <SearchInput
                value={searchValue}
                placeholder="Find a market"
                bg="athensGray2"
                onChange={setSearch}
              />
            </SBox>
          </SBoxAnimated>

          <SBoxAnimated
            style={animation.smallTitle(animationY)}
            position="absolute"
            width={1}
            alignItems="center"
          >
            <Pressable testID="back-market" onPress={onPress}>
              {({ pressed }) => (
                <SText
                  fontSize={16}
                  bold
                  color={titleColor}
                  style={{ opacity: pressed ? 0.7 : 1 }}
                >
                  {headerTitle}
                </SText>
              )}
            </Pressable>
          </SBoxAnimated>

          <SBoxAnimated
            position="absolute"
            style={animation.done(animationY)}
            right={6}
          >
            {visibility.skeleton || !active ? (
              <SDoneContainer>
                <SText
                  semibold
                  color={
                    lightVariant
                      ? theme.colors.columbiaBlue
                      : theme.colors.chathamsBlue
                  }
                >
                  Done
                </SText>
              </SDoneContainer>
            ) : (
              <Pressable
                testID="market-selector-done-button"
                onPress={() => {
                  if (active) {
                    goTo();
                  }
                }}
              >
                {({ pressed }) => (
                  <SDoneContainer opacity={pressed ? 0.7 : 1}>
                    <SText semibold color={theme.colors.azureRadiance}>
                      Done
                    </SText>
                  </SDoneContainer>
                )}
              </Pressable>
            )}
          </SBoxAnimated>
        </>
      ) : null}

      {renderCancelBtn()}
    </>
  );
});
