import dayjs from 'dayjs';
import { LinearGradient } from 'expo-linear-gradient';
import React, { useEffect, useMemo, useRef } from 'react';
import { Animated, Easing, StyleSheet, Text, View, type StyleProp, type ViewStyle } from 'react-native';

import type { ChallengeProgress } from '@/store/challengesSlice';

type ChallengeProgressCardProps = {
  title: string;
  endAt?: string;
  progress?: ChallengeProgress;
  style?: StyleProp<ViewStyle>;
  backgroundColors?: [string, string];
  titleColor?: string;
  subtitleColor?: string;
  metaColor?: string;
  metaSuffixColor?: string;
  accentColor?: string;
  trackColor?: string;
  inactiveColor?: string;
};

const DEFAULT_BACKGROUND: [string, string] = ['#ffffff', '#ffffff'];
const DEFAULT_TITLE_COLOR = '#1c1f3a';
const DEFAULT_SUBTITLE_COLOR = '#707baf';
const DEFAULT_META_COLOR = '#4F5BD5';
const DEFAULT_META_SUFFIX_COLOR = '#7a86bb';
const DEFAULT_ACCENT_COLOR = '#5E8BFF';
const DEFAULT_TRACK_COLOR = '#eceffa';
const DEFAULT_INACTIVE_COLOR = '#dfe4f6';

const clampSegments = (target: number, completed: number) => {
  const segmentsCount = Math.max(1, Math.min(target, 18));
  const completedSegments = Math.min(
    segmentsCount,
    Math.round((completed / Math.max(target, 1)) * segmentsCount)
  );
  return { segmentsCount, completedSegments };
};

const calculateRemainingDays = (endAt?: string) => {
  if (!endAt) return 0;
  const endDate = dayjs(endAt);
  if (!endDate.isValid()) return 0;
  return Math.max(0, endDate.diff(dayjs(), 'd'));
};

export const ChallengeProgressCard: React.FC<ChallengeProgressCardProps> = ({
  title,
  endAt,
  progress,
  style,
  backgroundColors = DEFAULT_BACKGROUND,
  titleColor = DEFAULT_TITLE_COLOR,
  subtitleColor = DEFAULT_SUBTITLE_COLOR,
  metaColor = DEFAULT_META_COLOR,
  metaSuffixColor = DEFAULT_META_SUFFIX_COLOR,
  accentColor = DEFAULT_ACCENT_COLOR,
  trackColor = DEFAULT_TRACK_COLOR,
  inactiveColor = DEFAULT_INACTIVE_COLOR,
}) => {
  const hasValidProgress = Boolean(progress && progress.target && progress.target > 0);
  const segmentAnimations = useRef<Animated.Value[]>([]);

  const segments = useMemo(() => {
    if (!hasValidProgress || !progress) return undefined;
    return clampSegments(progress.target, progress.completed);
  }, [hasValidProgress, progress]);

  if (segments) {
    if (segmentAnimations.current.length < segments.segmentsCount) {
      const additional = Array.from(
        { length: segments.segmentsCount - segmentAnimations.current.length },
        () => new Animated.Value(0)
      );
      segmentAnimations.current = [...segmentAnimations.current, ...additional];
    } else if (segmentAnimations.current.length > segments.segmentsCount) {
      segmentAnimations.current = segmentAnimations.current.slice(0, segments.segmentsCount);
    }
  } else if (segmentAnimations.current.length) {
    segmentAnimations.current = [];
  }

  useEffect(() => {
    if (!segments) return;

    segmentAnimations.current.forEach((animation, index) => {
      const isComplete = index < segments.completedSegments;
      Animated.timing(animation, {
        toValue: isComplete ? 1 : 0,
        duration: isComplete ? 460 : 240,
        delay: isComplete ? index * 55 : 0,
        easing: isComplete ? Easing.out(Easing.cubic) : Easing.out(Easing.quad),
        useNativeDriver: true,
      }).start();
    });
  }, [segments?.completedSegments, segments?.segmentsCount]);

  const remainingDays = useMemo(() => calculateRemainingDays(endAt), [endAt]);

  if (!hasValidProgress || !progress || !segments) {
    return null;
  }

  return (
    <View style={[styles.shadow, style]}>
      <LinearGradient colors={backgroundColors} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={styles.card}>
        <View style={styles.headerRow}>
          <View style={styles.headline}>
            <Text style={[styles.title, { color: titleColor }]} numberOfLines={1}>
              {title}
            </Text>
          </View>
          <Text style={[styles.remaining, { color: subtitleColor }]}>挑战剩余 {remainingDays} 天</Text>
        </View>

        <View style={styles.metaRow}>
          <Text style={[styles.metaValue, { color: metaColor }]}>
            {progress.completed} / {progress.target}
            <Text style={[styles.metaSuffix, { color: metaSuffixColor }]}> 天</Text>
          </Text>
        </View>

        <View style={[styles.track, { backgroundColor: trackColor }]}>
          {Array.from({ length: segments.segmentsCount }).map((_, index) => {
            const isFirst = index === 0;
            const isLast = index === segments.segmentsCount - 1;
            const animation = segmentAnimations.current[index];

            if (!animation) {
              return null;
            }

            const scaleY = animation.interpolate({
              inputRange: [0, 1],
              outputRange: [0.55, 1],
            });
            const scaleX = animation.interpolate({
              inputRange: [0, 1],
              outputRange: [0.7, 1],
            });
            const opacity = animation.interpolate({
              inputRange: [0, 1],
              outputRange: [0.25, 1],
            });

            return (
              <View
                key={`progress-segment-${index}`}
                style={[
                  styles.segment,
                  { backgroundColor: inactiveColor },
                  isFirst && styles.segmentFirst,
                  isLast && styles.segmentLast,
                ]}
              >
                <Animated.View
                  style={[
                    styles.segmentFill,
                    {
                      backgroundColor: accentColor,
                      opacity,
                      transform: [{ scaleX }, { scaleY }],
                    },
                  ]}
                />
              </View>
            );
          })}
        </View>
      </LinearGradient>
    </View>
  );
};

const styles = StyleSheet.create({
  shadow: {
    borderRadius: 28,
    shadowColor: 'rgba(104, 119, 255, 0.25)',
    shadowOffset: { width: 0, height: 16 },
    shadowOpacity: 0.24,
    shadowRadius: 28,
    elevation: 12,
  },
  card: {
    borderRadius: 28,
    paddingVertical: 24,
    paddingHorizontal: 22,
  },
  headerRow: {
    flexDirection: 'row',
    alignItems: 'flex-start',
  },
  headline: {
    flex: 1,
  },
  title: {
    fontSize: 18,
    fontWeight: '700',
  },
  remaining: {
    fontSize: 11,
    fontWeight: '600',
    alignSelf: 'flex-start',
  },
  metaRow: {
    marginTop: 12,
  },
  metaValue: {
    fontSize: 14,
    fontWeight: '700',
  },
  metaSuffix: {
    fontSize: 13,
    fontWeight: '500',
  },
  track: {
    marginTop: 12,
    flexDirection: 'row',
    alignItems: 'center',
    borderRadius: 12,
    paddingHorizontal: 6,
    paddingVertical: 4,
  },
  segment: {
    flex: 1,
    height: 4,
    borderRadius: 4,
    marginHorizontal: 3,
    overflow: 'hidden',
  },
  segmentFirst: {
    marginLeft: 0,
  },
  segmentLast: {
    marginRight: 0,
  },
  segmentFill: {
    flex: 1,
    borderRadius: 4,
  },
});

export default ChallengeProgressCard;
