import React, {useCallback, useMemo, useState} from 'react';
import {ListRenderItem, View} from 'react-native';
import {NavigationProp, useNavigation} from '@react-navigation/native';
import {List} from '@components/_HuGo/List';
import {useModalHandler} from '@hooks/useModalHandler';
import {useRanking} from '@modules/prodev2/hooks/useRanking';
import {RankingEntry} from '@modules/prodev2/interfaces';
import {ProdeV2StackParamList} from '@modules/prodev2/navigation/interfaces';
import {
  getCompetition,
  getTournamentPrediction,
  getUserRanking,
} from '@modules/prodev2/services';
import {MAX_STAGGER_INDEX, prodeKeys} from '@modules/prodev2/constants';
import {useUserId} from '@redux/selectors';
import {useQuery} from '@shared/hooks/queries-v5/useQuery';
import {Screens} from '@shared/constants';
import {useTheme} from '@shared/theme';

import {AnimatedCardEntrance} from '../AnimatedCardEntrance';
import {PodiumPreviewContent} from '../PodiumPreviewContent';
import {RankingRow} from '../RankingRow';
import {RankingTableSkeleton} from '../RankingRow/Skeletons';
import {UserStatsDialog} from '../UserStatsDialog';
import {RankingListEmpty} from './components/RankingListEmpty';
import {
  RankingListHeader,
  RANKING_HEADER_ITEM_COUNT,
} from './components/RankingListHeader';
import {styles} from './styles';

interface Props {
  competitionId: number;
}

const keyExtractor = (item: RankingEntry) => String(item.userId);

export function RankingTab({competitionId}: Props) {
  const userId = useUserId();
  const {theme} = useTheme();
  const navigation = useNavigation<NavigationProp<ProdeV2StackParamList>>();

  const [selectedEntry, setSelectedEntry] =
    useState<Nullable<RankingEntry>>(null);

  const {
    isVisible: isPodiumPreviewOpen,
    onOpenModal: onOpenPodiumPreview,
    onCloseModal: onClosePodiumPreview,
  } = useModalHandler();

  const {data: competition} = useQuery(
    prodeKeys.competition(competitionId),
    () => getCompetition(competitionId),
    {enabled: !!competitionId},
  );
  const {data: userRanking, isFetching: isUserRankingFetching} = useQuery(
    prodeKeys.userRanking(competitionId),
    () => getUserRanking(competitionId),
    {enabled: !!competitionId},
  );
  const {data: tournamentPrediction, isFetching: isTournamentFetching} =
    useQuery(
      prodeKeys.tournamentPrediction(competitionId),
      () => getTournamentPrediction(competitionId),
      {enabled: !!competitionId},
    );
  const {
    data: rankingEntries,
    getNextPage,
    hasNextPage,
    isFetchingNextPage,
    isLoading: isRankingLoading,
    isRefreshing,
    refresh,
  } = useRanking(competitionId);

  const hasTournamentStarted =
    competition?.status === 'ACTIVE' || competition?.status === 'FINISHED';
  const canModifyPodium =
    !!tournamentPrediction?.isOpen && !hasTournamentStarted;

  const deadline = useMemo(() => {
    if (!competition?.startDate) return undefined;
    try {
      const date = new Date(competition.startDate);
      return date.toLocaleDateString(undefined, {
        day: '2-digit',
        month: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        hour12: false,
      });
    } catch {
      return undefined;
    }
  }, [competition?.startDate]);

  const onModifyPodium = useCallback(() => {
    onClosePodiumPreview();
    navigation.navigate(Screens.PRODEV2_PODIUM, {competitionId});
  }, [competitionId, navigation, onClosePodiumPreview]);

  const onCloseUserStatsDialog = useCallback(() => setSelectedEntry(null), []);

  const renderItem: ListRenderItem<RankingEntry> = useCallback(
    ({item, index}) => {
      // Delay continues the header's sequence; the cap uses the row's own index
      // so several rows cascade (not just the 1-2 that fit under the header).
      const staggerIndex = RANKING_HEADER_ITEM_COUNT + index;
      return (
        <AnimatedCardEntrance
          index={staggerIndex}
          disabled={index > MAX_STAGGER_INDEX}>
          <RankingRow
            entry={item}
            isHighlighted={item.userId === userId}
            isLast={index === (rankingEntries.length ?? 0) - 1}
            onPress={setSelectedEntry}
          />
        </AnimatedCardEntrance>
      );
    },
    [rankingEntries.length, userId],
  );

  const isInitialLoading = isUserRankingFetching && !userRanking;

  return (
    <>
      <View
        style={[
          styles.list,
          {backgroundColor: theme.background.layout.default},
        ]}>
        <List<RankingEntry>
          data={rankingEntries}
          keyExtractor={keyExtractor}
          renderItem={renderItem}
          isLoading={isInitialLoading || isRankingLoading}
          isFetchingNextPage={isFetchingNextPage}
          hasNextPage={hasNextPage}
          onNextPage={getNextPage}
          isRefreshing={isRefreshing}
          onRefresh={refresh}
          ListHeaderComponent={
            userRanking ? (
              <RankingListHeader
                userRanking={userRanking}
                tournamentPrediction={tournamentPrediction}
                isTournamentFetching={isTournamentFetching}
                deadline={deadline}
                onOpenPodiumPreview={onOpenPodiumPreview}
              />
            ) : null
          }
          ListEmptyComponent={
            isInitialLoading || isRankingLoading ? (
              <RankingTableSkeleton />
            ) : (
              <RankingListEmpty />
            )
          }
          style={styles.listContent}
        />
      </View>
      {isPodiumPreviewOpen && tournamentPrediction?.prediction && (
        <PodiumPreviewContent
          isVisible={isPodiumPreviewOpen}
          onClose={onClosePodiumPreview}
          prediction={tournamentPrediction.prediction}
          deadline={deadline}
          isOpen={canModifyPodium}
          onModify={onModifyPodium}
        />
      )}
      <UserStatsDialog
        isOpen={!!selectedEntry}
        onClose={onCloseUserStatsDialog}
        competitionId={competitionId}
        entry={selectedEntry}
      />
    </>
  );
}
