import dayjs from 'dayjs';

import ChallengeProgressCard from '@/components/challenges/ChallengeProgressCard';
import { Colors } from '@/constants/Colors';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useColorScheme } from '@/hooks/useColorScheme';
import {
  fetchChallenges,
  selectChallengeCards,
  selectChallengesListError,
  selectChallengesListStatus,
  type ChallengeCardViewModel,
} from '@/store/challengesSlice';
import { Image } from 'expo-image';
import { LinearGradient } from 'expo-linear-gradient';
import { useRouter } from 'expo-router';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import {
  ActivityIndicator,
  Animated,
  FlatList,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  useWindowDimensions
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const AVATAR_SIZE = 36;
const CARD_IMAGE_WIDTH = 132;
const CARD_IMAGE_HEIGHT = 96;
const STATUS_LABELS: Record<'upcoming' | 'ongoing' | 'expired', string> = {
  upcoming: '即将开始',
  ongoing: '进行中',
  expired: '已结束',
};

const CAROUSEL_ITEM_SPACING = 16;
const MIN_CAROUSEL_CARD_WIDTH = 280;
const DOT_BASE_SIZE = 6;

export default function ChallengesScreen() {
  const theme = (useColorScheme() ?? 'light') as 'light' | 'dark';
  const insets = useSafeAreaInsets();

  const colorTokens = Colors[theme];
  const router = useRouter();
  const dispatch = useAppDispatch();
  const challenges = useAppSelector(selectChallengeCards);
  const listStatus = useAppSelector(selectChallengesListStatus);
  const listError = useAppSelector(selectChallengesListError);
  const ongoingChallenges = useMemo(() => {
    const now = dayjs();
    return challenges.filter((challenge) => {
      if (challenge.status !== 'ongoing' || !challenge.isJoined || !challenge.progress) {
        return false;
      }

      if (challenge.endAt) {
        const endDate = dayjs(challenge.endAt);
        if (endDate.isValid() && endDate.isBefore(now)) {
          return false;
        }
      }

      return true;
    });
  }, [challenges]);
  const progressTrackColor = theme === 'dark' ? 'rgba(255, 255, 255, 0.08)' : '#eceffa';
  const progressInactiveColor = theme === 'dark' ? 'rgba(255, 255, 255, 0.24)' : '#dfe4f6';

  useEffect(() => {
    if (listStatus === 'idle') {
      dispatch(fetchChallenges());
    }
  }, [dispatch, listStatus]);

  const gradientColors: [string, string] =
    theme === 'dark'
      ? ['#1f2230', '#10131e']
      : [colorTokens.backgroundGradientStart, colorTokens.backgroundGradientEnd];

  const renderChallenges = () => {
    if (listStatus === 'loading' && challenges.length === 0) {
      return (
        <View style={styles.stateContainer}>
          <ActivityIndicator color={colorTokens.primary} />
          <Text style={[styles.stateText, { color: colorTokens.textSecondary }]}>加载挑战中…</Text>
        </View>
      );
    }

    if (listStatus === 'failed' && challenges.length === 0) {
      return (
        <View style={styles.stateContainer}>
          <Text style={[styles.stateText, { color: colorTokens.textSecondary }]}>
            {listError ?? '加载挑战失败，请稍后重试'}
          </Text>
          <TouchableOpacity
            style={[styles.retryButton, { borderColor: colorTokens.primary }]}
            activeOpacity={0.9}
            onPress={() => dispatch(fetchChallenges())}
          >
            <Text style={[styles.retryText, { color: colorTokens.primary }]}>重新加载</Text>
          </TouchableOpacity>
        </View>
      );
    }

    if (challenges.length === 0) {
      return (
        <View style={styles.stateContainer}>
          <Text style={[styles.stateText, { color: colorTokens.textSecondary }]}>暂无挑战，稍后再来探索。</Text>
        </View>
      );
    }

    return challenges.map((challenge) => (
      <ChallengeCard
        key={challenge.id}
        challenge={challenge}
        surfaceColor={colorTokens.surface}
        textColor={colorTokens.text}
        mutedColor={colorTokens.textSecondary}
        onPress={() =>
          router.push({ pathname: '/challenges/[id]', params: { id: challenge.id } })
        }
      />
    ));
  };

  return (
    <View style={[styles.screen, { backgroundColor: colorTokens.pageBackgroundEmphasis }]}>
      <LinearGradient colors={gradientColors} style={StyleSheet.absoluteFillObject} />
      <ScrollView
        contentContainerStyle={[styles.scrollContent, {
          paddingTop: insets.top,
        }]}
        showsVerticalScrollIndicator={false}
        bounces
      >
        <View style={styles.headerRow}>
          <View>
            <Text style={[styles.title, { color: colorTokens.text }]}>挑战</Text>
            <Text style={[styles.subtitle, { color: colorTokens.textSecondary }]}>参与精选活动，保持每日动力</Text>
          </View>
          {/* <TouchableOpacity activeOpacity={0.9} style={styles.giftShadow}>
              <LinearGradient
                colors={[colorTokens.primary, colorTokens.accentPurple]}
                start={{ x: 0, y: 0 }}
                end={{ x: 1, y: 1 }}
                style={styles.giftButton}
              >
                <IconSymbol name="gift.fill" size={18} color={colorTokens.onPrimary} />
              </LinearGradient>
            </TouchableOpacity> */}
        </View>

        {ongoingChallenges.length ? (
          <OngoingChallengesCarousel
            challenges={ongoingChallenges}
            colorTokens={colorTokens}
            trackColor={progressTrackColor}
            inactiveColor={progressInactiveColor}
            onPress={(challenge) =>
              router.push({ pathname: '/challenges/[id]', params: { id: challenge.id } })
            }
          />
        ) : null}

        <View style={styles.cardsContainer}>{renderChallenges()}</View>
      </ScrollView>
    </View>
  );
}

type ChallengeCardProps = {
  challenge: ChallengeCardViewModel;
  surfaceColor: string;
  textColor: string;
  mutedColor: string;
  onPress: () => void;
};

function ChallengeCard({ challenge, surfaceColor, textColor, mutedColor, onPress }: ChallengeCardProps) {
  const statusLabel = STATUS_LABELS[challenge.status] ?? challenge.status;

  return (
    <TouchableOpacity
      activeOpacity={0.92}
      onPress={onPress}
      style={[
        styles.card,
        {
          backgroundColor: surfaceColor,
          shadowColor: 'rgba(15, 23, 42, 0.18)',
        },
      ]}
    >
      <View style={styles.cardInner}>
        <View style={styles.cardMedia}>
          <Image
            source={{ uri: challenge.image }}
            style={styles.cardImage}
            cachePolicy={'memory-disk'}
          />

          <>
            <LinearGradient
              pointerEvents="none"
              colors={['rgba(17, 21, 32, 0.05)', 'rgba(13, 17, 28, 0.4)']}
              style={styles.cardImageOverlay}
            />
            <View style={styles.expiredBadge}>
              <Text style={styles.expiredBadgeText}>{statusLabel}</Text>
            </View>
          </>
        </View>

        <View style={styles.cardContent}>
          <Text
            style={[styles.cardTitle, { color: textColor }]}
            numberOfLines={1}
          >
            {challenge.title}
          </Text>
          <Text
            style={[styles.cardDate, { color: mutedColor }]}
          >
            {challenge.dateRange}
          </Text>
          <Text
            style={[styles.cardParticipants, { color: mutedColor }]}
          >
            {challenge.participantsLabel}
            {challenge.isJoined ? ' · 已加入' : ''}
          </Text>
          {challenge.avatars.length ? (
            <AvatarStack avatars={challenge.avatars} borderColor={surfaceColor} />
          ) : null}
        </View>
      </View>

    </TouchableOpacity>
  );
}

type ThemeColorTokens = (typeof Colors)['light'] | (typeof Colors)['dark'];

type OngoingChallengesCarouselProps = {
  challenges: ChallengeCardViewModel[];
  colorTokens: ThemeColorTokens;
  trackColor: string;
  inactiveColor: string;
  onPress: (challenge: ChallengeCardViewModel) => void;
};

function OngoingChallengesCarousel({
  challenges,
  colorTokens,
  trackColor,
  inactiveColor,
  onPress,
}: OngoingChallengesCarouselProps) {
  const { width } = useWindowDimensions();
  const cardWidth = Math.max(width - 40, MIN_CAROUSEL_CARD_WIDTH);
  const snapInterval = cardWidth + CAROUSEL_ITEM_SPACING;
  const scrollX = useRef(new Animated.Value(0)).current;
  const listRef = useRef<FlatList<ChallengeCardViewModel> | null>(null);

  useEffect(() => {
    scrollX.setValue(0);
    listRef.current?.scrollToOffset({ offset: 0, animated: false });
  }, [scrollX, challenges.length]);

  const onScroll = useMemo(
    () =>
      Animated.event(
        [
          {
            nativeEvent: {
              contentOffset: { x: scrollX },
            },
          },
        ],
        { useNativeDriver: true }
      ),
    [scrollX]
  );

  const renderItem = useCallback(
    ({ item, index }: { item: ChallengeCardViewModel; index: number }) => {
      const inputRange = [
        (index - 1) * snapInterval,
        index * snapInterval,
        (index + 1) * snapInterval,
      ];
      const scale = scrollX.interpolate({
        inputRange,
        outputRange: [0.94, 1, 0.94],
        extrapolate: 'clamp',
      });
      const translateY = scrollX.interpolate({
        inputRange,
        outputRange: [10, 0, 10],
        extrapolate: 'clamp',
      });

      return (
        <Animated.View
          style={[
            styles.carouselCard,
            {
              width: cardWidth,
              transform: [{ scale }, { translateY }],
            },
          ]}
        >
          <TouchableOpacity
            activeOpacity={0.92}
            style={styles.carouselTouchable}
            onPress={() => onPress(item)}
          >
            <ChallengeProgressCard
              title={item.title}
              endAt={item.endAt}
              progress={item.progress}
              style={styles.carouselProgressCard}
              backgroundColors={[colorTokens.card, colorTokens.card]}
              titleColor={colorTokens.text}
              subtitleColor={colorTokens.textSecondary}
              metaColor={colorTokens.primary}
              metaSuffixColor={colorTokens.textSecondary}
              accentColor={colorTokens.primary}
              trackColor={trackColor}
              inactiveColor={inactiveColor}
            />
          </TouchableOpacity>
        </Animated.View>
      );
    },
    [cardWidth, colorTokens, inactiveColor, onPress, scrollX, snapInterval, trackColor]
  );

  return (
    <View style={styles.carouselContainer}>
      <Animated.FlatList
        ref={listRef}
        data={challenges}
        keyExtractor={(item) => item.id}
        horizontal
        showsHorizontalScrollIndicator={false}
        bounces
        decelerationRate="fast"
        snapToAlignment="start"
        snapToInterval={snapInterval}

        ItemSeparatorComponent={() => <View style={{ width: CAROUSEL_ITEM_SPACING }} />}
        onScroll={onScroll}
        scrollEventThrottle={16}
        overScrollMode="never"
        renderItem={renderItem}
      />

      {challenges.length > 1 ? (
        <View style={styles.carouselIndicators}>
          {challenges.map((challenge, index) => {
            const inputRange = [
              (index - 1) * snapInterval,
              index * snapInterval,
              (index + 1) * snapInterval,
            ];
            const scaleX = scrollX.interpolate({
              inputRange,
              outputRange: [1, 2.6, 1],
              extrapolate: 'clamp',
            });
            const dotOpacity = scrollX.interpolate({
              inputRange,
              outputRange: [0.35, 1, 0.35],
              extrapolate: 'clamp',
            });

            return (
              <Animated.View
                key={challenge.id}
                style={[
                  styles.carouselDot,
                  {
                    opacity: dotOpacity,
                    backgroundColor: colorTokens.primary,
                    transform: [{ scaleX }],
                  },
                ]}
              />
            );
          })}
        </View>
      ) : null}
    </View>
  );
}

type AvatarStackProps = {
  avatars: string[];
  borderColor: string;
};

function AvatarStack({ avatars, borderColor }: AvatarStackProps) {
  return (
    <View style={styles.avatarRow}>
      {avatars
        .filter(Boolean)
        .map((avatar, index) => (
          <Image
            key={`${avatar}-${index}`}
            source={{ uri: avatar }}
            style={[
              styles.avatar,
              { borderColor },
              index === 0 ? null : styles.avatarOffset,
            ]}
          />
        ))}
    </View>
  );
}

const styles = StyleSheet.create({
  screen: {
    flex: 1,
  },
  safeArea: {
    flex: 1,
  },
  scrollContent: {
    paddingHorizontal: 20,
    paddingBottom: 120,
  },
  headerRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginTop: 8,
    marginBottom: 26,
  },
  title: {
    fontSize: 32,
    fontWeight: '700',
    letterSpacing: 1,
  },
  subtitle: {
    marginTop: 6,
    fontSize: 14,
    fontWeight: '500',
    opacity: 0.8,
  },
  giftShadow: {
    shadowColor: 'rgba(94, 62, 199, 0.45)',
    shadowOffset: { width: 0, height: 8 },
    shadowOpacity: 0.35,
    shadowRadius: 12,
    elevation: 8,
    borderRadius: 26,
  },
  giftButton: {
    width: 32,
    height: 32,
    borderRadius: 26,
    alignItems: 'center',
    justifyContent: 'center',
  },
  cardsContainer: {
    gap: 18,
  },
  carouselContainer: {
    marginBottom: 24,
  },
  carouselCard: {
    width: '100%',
  },
  carouselTouchable: {
    flex: 1,
  },
  carouselProgressCard: {
    width: '100%',
  },
  carouselIndicators: {
    marginTop: 18,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  carouselDot: {
    width: DOT_BASE_SIZE,
    height: DOT_BASE_SIZE,
    borderRadius: DOT_BASE_SIZE / 2,
    marginHorizontal: 4,
    backgroundColor: 'transparent',
  },
  stateContainer: {
    alignItems: 'center',
    justifyContent: 'center',
    paddingVertical: 40,
    paddingHorizontal: 20,
  },
  stateText: {
    marginTop: 12,
    fontSize: 14,
    textAlign: 'center',
    lineHeight: 20,
  },
  retryButton: {
    marginTop: 16,
    paddingHorizontal: 18,
    paddingVertical: 8,
    borderRadius: 18,
    borderWidth: StyleSheet.hairlineWidth,
  },
  retryText: {
    fontSize: 13,
    fontWeight: '600',
  },
  card: {
    borderRadius: 28,
    padding: 18,
    shadowOffset: { width: 0, height: 16 },
    shadowOpacity: 0.18,
    shadowRadius: 24,
    elevation: 6,
    position: 'relative',
    overflow: 'hidden',
  },
  cardInner: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  cardImage: {
    width: CARD_IMAGE_WIDTH,
    height: CARD_IMAGE_HEIGHT,
    borderRadius: 22,
  },
  cardMedia: {
    borderRadius: 22,
    overflow: 'hidden',
    position: 'relative',
  },
  cardContent: {
    flex: 1,
    marginLeft: 16,
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: '700',
    marginBottom: 4,
  },

  cardDate: {
    fontSize: 13,
    fontWeight: '500',
    marginBottom: 4,
  },
  cardParticipants: {
    fontSize: 13,
    fontWeight: '500',
  },
  cardExpired: {
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: 'rgba(148, 163, 184, 0.22)',
  },
  cardExpiredText: {
    opacity: 0.7,
  },
  cardDimOverlay: {
    ...StyleSheet.absoluteFillObject,
    borderRadius: 28,
  },
  cardImageOverlay: {
    ...StyleSheet.absoluteFillObject,
  },
  expiredBadge: {
    position: 'absolute',
    left: 12,
    bottom: 12,
    paddingHorizontal: 10,
    paddingVertical: 4,
    borderRadius: 12,
    backgroundColor: 'rgba(12, 16, 28, 0.45)',
  },
  expiredBadgeText: {
    fontSize: 12,
    fontWeight: '600',
    color: '#f7f9ff',
    letterSpacing: 0.3,
  },
  cardProgress: {
    marginTop: 8,
    fontSize: 13,
    fontWeight: '600',
  },
  avatarRow: {
    flexDirection: 'row',
    marginTop: 16,
    alignItems: 'center',
  },
  avatar: {
    width: AVATAR_SIZE,
    height: AVATAR_SIZE,
    borderRadius: AVATAR_SIZE / 2,
    borderWidth: 2,
  },
  avatarOffset: {
    marginLeft: -12,
  },
});
