import React, {useEffect, useMemo, useRef, useState} from 'react';
import {Keyboard, ScrollView, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import Animated, {FadeInRight} from 'react-native-reanimated';
import {IconChevronDown} from '@tabler/icons-react-native';
import {Button, RenderSceneProps, Tabs, TabsRef} from '@components';
import {OrderBy} from '@config/api';
import i18n, {Language} from '@config/i18n';
import {Navigation} from '@interfaces/navigation';
import {
  CourseCategory,
  CoursesFilterType,
  CoursesTab,
  CourseStatus,
  FullFilters,
} from '@modules/learning/interfaces';
import {ALL_CATEGORIES_ID} from '@modules/learning/constants';
import {useGetCourseCategories} from '@modules/learning/hooks';
import {SearchHeader} from '@modules/learning/components/SearchHeader';
import {useCategoriesDialogStore} from '@modules/learning/stores/categoriesDialogStore';
import {useInstanceId, useModuleNames, useUserId} from '@redux/selectors';
import {AMPLITUDE_EVENTS, Screens} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {
  logAmplitudeEvent,
  capitalize,
  getCroppedText,
  isAndroid,
} from '@shared/utils';

import CourseList from './screens/CourseList';
import {
  ANIMATION_INITIAL_DELAY_MS,
  ANIMATION_STAGGER_MS,
  styles,
} from './styles';
import Filters from './screens/CourseList/components/Filters';
import {CategoryChipsSk} from './screens/CourseList/components/CourseListSk';
import CategoriesDialog from './components/CategoriesDialog';
import SeeMoreModal from './components/SeeMoreModal';

function Courses({navigation}: Navigation<Screens.COURSES>) {
  const instanceId = useInstanceId();
  const userId = useUserId();
  const tabsRef = useRef<Nullable<TabsRef>>(null);
  const categoriesScrollViewRef = useRef<ScrollView>(null);
  const hasAnimatedRef = useRef(false);
  const {theme} = useTheme();
  const {t} = useTranslation();
  const {categories, isFetching: loadingCategories} = useGetCourseCategories();
  const {
    openDialog,
    clearSelectionForRoot,
    setSubCategoryForCurrentRoot,
    setLeafCategorySelection,
    selectedByRootId,
    activeSelectionRootId,
    promoteAndSelect,
    initCategories,
    firstFiveCategories: firstFiveCategoriesRaw,
    remainingCategories,
  } = useCategoriesDialogStore();

  const moduleNames = useModuleNames();
  const moduleName =
    capitalize(moduleNames?.[i18n.language as Language]?.COURSES, false) ||
    t('learning.course.title_other');
  const [searchText, setSearchText] = useState('');
  const [filterType, setFilterType] = useState<CoursesFilterType>();
  const [isFiltersOpen, setIsFiltersOpen] = useState(false);
  const [sortingOption, setSortingOption] = useState<OrderBy>();
  const [isSeeMoreModalVisible, setIsSeeMoreModalVisible] = useState(false);

  useEffect(() => {
    initCategories(categories);
  }, [categories, initCategories]);

  // Reset animation flag when categories change
  useEffect(() => {
    if (firstFiveCategoriesRaw.length > 0) {
      hasAnimatedRef.current = false;
    }
  }, [firstFiveCategoriesRaw]);

  const firstFiveCategories = useMemo(
    () =>
      (firstFiveCategoriesRaw || []).map(
        cat => selectedByRootId[cat.id] ?? cat,
      ),
    [firstFiveCategoriesRaw, selectedByRootId],
  );

  const routes = [
    {
      key: CoursesTab.All,
      label: t('learning.path.tabs.all'),
    },
    {
      key: CoursesTab.Pending,
      label: t('learning.path.tabs.pending'),
    },
    {
      key: CoursesTab.Ongoing,
      label: t('learning.path.tabs.in_progress'),
    },
    {
      key: CoursesTab.Finished,
      label: t('learning.common.finished'),
    },
  ];

  const applyFilter = ({filter, order}: FullFilters) => {
    setIsFiltersOpen(false);
    setFilterType(filter);
    setSortingOption(order);
  };

  useEffect(() => {
    logAmplitudeEvent(AMPLITUDE_EVENTS.COURSE_MINIAPP_ENTERED, {
      userId,
      instanceId,
    });
  }, [instanceId, userId]);

  useEffect(() => {
    navigation.setOptions({
      title: moduleName,
    });
  }, [moduleName, navigation]);

  const onShowFilters = () => {
    Keyboard.dismiss();
    setIsFiltersOpen(true);
  };

  const selectedCategoryForFilter =
    !activeSelectionRootId || activeSelectionRootId === ALL_CATEGORIES_ID
      ? undefined
      : selectedByRootId[activeSelectionRootId];

  const renderScene = ({route: {key}}: RenderSceneProps) => {
    const commonProps = {
      selectedCategoryId: selectedCategoryForFilter?.id,
      searchText,
      filterType,
      sortingOption,
    };
    switch (key) {
      case CoursesTab.All:
        return <CourseList type={CoursesTab.All} {...commonProps} />;
      case CoursesTab.Pending:
        return <CourseList type={CourseStatus.PENDING} {...commonProps} />;
      case CoursesTab.Ongoing:
        return <CourseList type={CourseStatus.IN_PROGRESS} {...commonProps} />;
      case CoursesTab.Finished:
        return <CourseList type={CourseStatus.FINISHED} {...commonProps} />;
      default:
        return null;
    }
  };

  let amountOfFilters = 0;
  if (filterType && sortingOption) {
    amountOfFilters = 2;
  } else if (filterType || sortingOption) {
    amountOfFilters = 1;
  }

  const onSelectChip = (category: CourseCategory) => () => {
    const isActivelySelected =
      activeSelectionRootId !== undefined &&
      selectedByRootId[activeSelectionRootId]?.id === category.id;

    const rootIdWithThisSubcategory = Object.keys(selectedByRootId).find(
      rootId => selectedByRootId[Number(rootId)]?.id === category.id,
    );

    const rootCategoryToUse = rootIdWithThisSubcategory
      ? categories.find(
          categoryItem => categoryItem.id === Number(rootIdWithThisSubcategory),
        )
      : categories.find(categoryItem => categoryItem.id === category.id);

    if (isActivelySelected && rootCategoryToUse?.children.length === 0) {
      clearSelectionForRoot(activeSelectionRootId);
      return;
    }

    if (!rootCategoryToUse) return;

    if (rootCategoryToUse.children.length > 0) {
      openDialog(rootCategoryToUse);
    } else {
      setLeafCategorySelection(rootCategoryToUse);
      promoteAndSelect(category.id);
    }
  };

  const onCategorySelected = (category: CourseCategory) => {
    setSubCategoryForCurrentRoot(category);
  };

  const renderCategories = () => {
    if (categories?.length <= 1) {
      return null;
    }
    const shouldAnimate = !hasAnimatedRef.current;
    const isLastItem = (index: number) =>
      index === firstFiveCategories.length - 1;

    return firstFiveCategories.map((category, index) => {
      const isSelected =
        category.id === ALL_CATEGORIES_ID
          ? activeSelectionRootId === ALL_CATEGORIES_ID ||
            activeSelectionRootId === undefined
          : activeSelectionRootId !== undefined &&
            selectedByRootId[activeSelectionRootId]?.id === category.id;

      const rootIdWithThisSubcategory = Object.keys(selectedByRootId).find(
        rootId => selectedByRootId[Number(rootId)]?.id === category.id,
      );

      const rootCategoryToUse = rootIdWithThisSubcategory
        ? categories.find(
            categoryItem =>
              categoryItem.id === Number(rootIdWithThisSubcategory),
          )
        : categories.find(categoryItem => categoryItem.id === category.id);

      const hasDialog =
        category.children.length > 0 ||
        (rootCategoryToUse && rootCategoryToUse.children.length > 0);

      const chipText = getCroppedText({
        body: category.name,
        limit: 20,
      });

      const onLayout = () => {
        if (shouldAnimate && isLastItem(index)) {
          hasAnimatedRef.current = true;
        }
      };
      // TODO: get back animation for android in the future
      const enteringAnimation =
        shouldAnimate && !isAndroid
          ? FadeInRight.delay(
              ANIMATION_INITIAL_DELAY_MS + index * ANIMATION_STAGGER_MS,
            ).duration(250)
          : undefined;

      return (
        <Animated.View
          key={category.id}
          entering={enteringAnimation}
          onLayout={onLayout}>
          <Button
            text={chipText}
            variant={isSelected ? 'secondaryActive' : 'secondary'}
            size="sm"
            IconRight={hasDialog ? IconChevronDown : undefined}
            onPress={onSelectChip(category)}
          />
        </Animated.View>
      );
    });
  };

  const renderSeeMoreButton = useMemo(() => {
    if (remainingCategories.length === 0) {
      return null;
    }

    return (
      <Button
        text={t('general.see_more')}
        variant="tertiary"
        size="sm"
        onPress={() => setIsSeeMoreModalVisible(true)}
      />
    );
  }, [remainingCategories, t]);

  const onSelectCategoryForSeeMoreModal = (category: CourseCategory) => {
    setIsSeeMoreModalVisible(false);
    promoteAndSelect(category.id);
    categoriesScrollViewRef.current?.scrollTo({x: 0, animated: true});
  };

  return (
    <View
      style={[
        styles.container,
        {backgroundColor: theme.background.layout.tertiary},
      ]}>
      {loadingCategories ? (
        <CategoryChipsSk />
      ) : (
        <View>
          {!!categories?.length && (
            <ScrollView
              ref={categoriesScrollViewRef}
              horizontal
              showsHorizontalScrollIndicator={false}
              contentContainerStyle={styles.chips}>
              {renderCategories()}
              {renderSeeMoreButton}
            </ScrollView>
          )}
        </View>
      )}
      <SearchHeader
        searchValue={searchText}
        onSearch={setSearchText}
        onFilter={onShowFilters}
        placeholder={t('learning.course.search')}
        amountOfFilters={amountOfFilters}
        style={!!categories?.length && styles.withCategories}
      />
      <Tabs ref={tabsRef} routes={routes} renderScene={renderScene} />
      <Filters
        isVisible={isFiltersOpen}
        setIsVisible={setIsFiltersOpen}
        onPress={applyFilter}
        selectedOrder={sortingOption}
        selectedStatus={filterType}
      />
      <CategoriesDialog
        categories={categories}
        onSelectCategory={onCategorySelected}
      />
      <SeeMoreModal
        isVisible={isSeeMoreModalVisible}
        categories={remainingCategories}
        onClose={() => setIsSeeMoreModalVisible(false)}
        onSelectCategory={onSelectCategoryForSeeMoreModal}
      />
    </View>
  );
}

export default Courses;
