import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { Animated, Dimensions, Modal, View } from 'react-native';
import { PanGestureHandler, PanGestureHandlerStateChangeEvent, State, FlatList } from 'react-native-gesture-handler';
import { FormHandles } from '@unform/core';
import { CreateRange } from '../../../services';
import AppContext from '../../AppProvider/AppContext';
import { NavActions } from '../../NavActions/native';
import { RSValue } from '../../RFValue';
import { ITabsRef } from '../../Tabs/Tabs.interface';
import { ITagFilterRef } from '../../TagsFilters/TagsFilters.interface';
import { CardsListingContainer } from './CardsListingContainer';
import { FiltersContainer } from './FiltersContainer';
import { HeaderListingContainer } from './HeaderListingContainer';
import { IPageListingChildrenProps, IPageListingProps } from './PageListing.interface';
import { HeaderSection } from './PageListing.style';
import { SubHeaderListingContainer } from './SubHeaderListingContainer';

export const PageListing: React.FunctionComponent<IPageListingProps> = (props) => {
   const { FiltersComponent, navActions, viewList } = props;
   const { registerOnSearch, starting, filters } = viewList;
   // Sizes
   const tabsSize = RSValue(50);
   const navigationBarSize = RSValue(55);
   const resultsSize = RSValue(45);
   const [tagsFilterSize, setTagsFilterSize] = useState(RSValue(0));
   const paddingScroll = tabsSize + navigationBarSize + resultsSize + tagsFilterSize;
   const navActionsSize = RSValue(65);

   // Animated
   const animateScrollY = useRef(new Animated.Value(0)).current;
   const animatedNavActions = useRef(new Animated.Value(0)).current;
   const animatedNavActions2 = useRef(new Animated.Value(0)).current;
   const scrollTop = useRef(new Animated.Value(0)).current;
   const animateHeaderTranslateY = useRef(
      Animated.add(
         Animated.multiply(
            Animated.diffClamp(
               // Remover valores negativos do scroll da FlatList
               animateScrollY.interpolate({
                  inputRange: [0, 1],
                  outputRange: [0, 1],
                  extrapolateLeft: 'clamp',
               }),
               0,
               navigationBarSize + tabsSize,
            ),
            -1,
         ),
         scrollTop,
      ),
   ).current;

   useEffect(() => {
      registerOnSearch(() => {
         if (navActions) {
            navActions?.onUnselectAll();
         }
      });
   }, []);

   const animateTop = useRef(new Animated.Value(0)).current;

   const navactionEnabled = useRef<any>(false);
   const navactionEnabled2 = useRef<any>(false);

   useLayoutEffect(() => {
      if (navActions?.selected) {
         if (!navactionEnabled2.current) {
            navactionEnabled2.current = true;
            animatedNavActions.setValue(1);
            Animated.timing(animatedNavActions2, {
               toValue: 1,
               duration: 200,
               useNativeDriver: true,
            }).start();

            if (scrollPosRef.current < paddingScroll) {
               animateTop.setValue(paddingScroll - scrollPosRef.current - navActionsSize);
               Animated.timing(animateTop, {
                  toValue: 0,
                  duration: 200,
                  useNativeDriver: true,
               }).start();
            }
         }
      } else if (navactionEnabled2.current) {
         navactionEnabled2.current = false;
         const newScrollY = scrollPosRef.current + paddingScroll - navActionsSize;
         animatedNavActions.setValue(0);
         Animated.timing(animatedNavActions2, {
            toValue: 0,
            duration: 200,
            useNativeDriver: true,
         }).start();
      }
   }, [navActions?.selected]);

   const forceScroll = useRef<any>(-1);

   useLayoutEffect(() => {
      forceScroll.current = -1;
      if (navActions?.selected) {
         /**
          * Subtrai Scroll atual por paddingScroll,
          * pois todo o conteudo foi jogando a
          * translateY = -paddingScroll a cima da tela
          */
         const newScrollY = scrollPosRef.current - paddingScroll + navActionsSize;

         if (!navactionEnabled.current) {
            navactionEnabled.current = true;
            scrollListingRef?.current?.scrollToOffset({
               animated: false,
               offset: newScrollY,
            });
            forceScroll.current = newScrollY;
         }
      } else if (navactionEnabled.current) {
         navactionEnabled.current = false;
         const newScrollY = scrollPosRef.current + paddingScroll - navActionsSize;

         if (scrollPosRef.current >= scrollCardHeightRef.current - ListingHeightRef.current - paddingScroll) {
            const MaxScroll = scrollCardHeightRef.current - ListingHeightRef.current;
            const rest = scrollCardHeightRef.current - ListingHeightRef.current - scrollPosRef.current;

            scrollListingRef?.current?.scrollToOffset({
               animated: false,
               offset: MaxScroll + paddingScroll - navActionsSize - rest,
            });
            forceScroll.current = MaxScroll + paddingScroll - navActionsSize - rest;
         } else {
            scrollListingRef?.current?.scrollToOffset({
               animated: false,
               offset: newScrollY,
            });
            forceScroll.current = newScrollY;
         }
      }
   }, [paddingScroll, navActions?.selected]);

   useEffect(() => {
      if (forceScroll.current != -1) {
         scrollListingRef?.current?.scrollToOffset({
            animated: false,
            offset: forceScroll.current,
         });
      }
   }, [paddingScroll, navActions?.selected]);

   useLayoutEffect(() => {
      if (!filters?.offset || filters?.offset == 0) {
         Animated.timing(animateScrollY, {
            toValue: -200,
            duration: 200,
            useNativeDriver: true,
         }).start();
      }
   }, [filters]);

   /**
    * Refs
    */
   const tabsRef = useRef<ITabsRef>();
   const formSortRef = useRef<FormHandles>();
   const tagsFiltersRef = useRef<ITagFilterRef>();
   const scrollListingRef = useRef<any>();
   const scrollPosRef = useRef<any>(0);
   const scrollCardHeightRef = useRef<any>(0);
   const ListingHeightRef = useRef<any>(0);

   /**
    * Filters
    */
   const [filterMobileOpen, setFilterMobileOpen] = useState<boolean>(false);
   const openFilters = useCallback(() => {
      setFilterMobileOpen(true);
   }, []);
   const closeFilters = useCallback(() => {
      setFilterMobileOpen(false);
   }, []);

   const propsChildren: IPageListingChildrenProps = {
      ...props,
      tabsRef,
      scrollListingRef,
      formSortRef,
      tagsFiltersRef,
      filterMobileOpen,
      setFilterMobileOpen,
      openFilters,
      closeFilters,
      animateScrollY,
      paddingScroll,
      navActionsSize,
      setTagsFilterSize,
      scrollPosRef,
      scrollCardHeightRef,
      animatedNavActions,
   };

   const [pageListingHeight, setPageListingHeight] = useState(0);
   //
   return (
      <View
         style={{ flex: 1 }}
         onLayout={(event) => {
            setPageListingHeight(event.nativeEvent.layout.height);
         }}
      >
         <FiltersContainer {...propsChildren} />

         {navActions && !!navActions?.selected && (
            <Animated.View
               testID="nav-actions-container"
               style={{
                  position: 'absolute',
                  top: 0,
                  left: 0,
                  width: '100%',
                  zIndex: 10,
                  // opacity: animatedNavActions2,
                  transform: [
                     {
                        translateY: animatedNavActions2.interpolate({
                           inputRange: [0, 1],
                           outputRange: [-navActionsSize, 0],
                        }),
                     },
                  ],
               }}
            >
               <NavActions {...navActions} />
            </Animated.View>
         )}

         <Animated.View
            onLayout={(event) => {
               ListingHeightRef.current = event.nativeEvent.layout.height;
            }}
            style={{
               backgroundColor: 'white',
               height: pageListingHeight + 2 * paddingScroll + navActionsSize,
               transform: [
                  {
                     translateY: Animated.add(animateTop, !navActions?.selected ? -paddingScroll : 0),
                  },
               ],
            }}
         >
            <HeaderSection
               style={{
                  transform: [
                     {
                        translateY: Animated.add(
                           Animated.add(animateHeaderTranslateY, paddingScroll),
                           animatedNavActions.interpolate({
                              inputRange: [0, 1],
                              outputRange: [0, -paddingScroll * 2 + navActionsSize - navActionsSize / 10],
                           }),
                        ),
                     },
                  ],
               }}
            >
               <HeaderListingContainer {...propsChildren} />
               <SubHeaderListingContainer {...propsChildren} />
            </HeaderSection>
            <View style={{ flex: 1 }}>
               <CardsListingContainer {...propsChildren} />
            </View>
         </Animated.View>
      </View>
   );
};
