import { useEffect } from 'react';
import { Text, View } from 'react-native';

import Animated, {
  Easing,
  cancelAnimation,
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';

interface PlaybackPageIndicatorProps {
  total: number;
  current: number;
  /** 0–1 progress for the active segment. Source ticks at ~100ms. */
  progress: number;
  paused: boolean;
}

const SEGMENT_GAP = 3;
const SEGMENT_HEIGHT = 2.5;
const SMOOTHING_MS = 300;
const PAGE_SIZE = 10;
const STUB_WIDTH = 8;

/**
 * Snapchat-style segmented progress bar. Past segments full, future empty,
 * active segment animated. The 300ms linear smoothing absorbs the 100ms
 * tick from the particle view source so motion looks continuous at 60fps.
 *
 * Caps the visible window at PAGE_SIZE segments. When more particles exist
 * before/after the window, a short dim "ghost stub" appears on that side using
 * the same track vocabulary. Non-interactive on mobile — the window slides
 * automatically as `current` crosses page boundaries.
 */
export function PlaybackPageIndicator({
  total,
  current,
  progress,
  paused,
}: PlaybackPageIndicatorProps) {
  if (total === 0) return null;

  const paginated = total > PAGE_SIZE;
  const safeCurrent = current < 0 ? 0 : current;
  const pageStart = paginated
    ? Math.floor(safeCurrent / PAGE_SIZE) * PAGE_SIZE
    : 0;
  const visibleCount = paginated
    ? Math.min(PAGE_SIZE, total - pageStart)
    : total;
  const hasPrevPage = paginated && pageStart > 0;
  const hasNextPage = paginated && pageStart + PAGE_SIZE < total;

  return (
    <View className="items-stretch">
      <View className="flex-row items-stretch" style={{ gap: SEGMENT_GAP }}>
        {paginated && <GhostStub visible={hasPrevPage} />}
        <View
          className="flex-1 flex-row items-stretch"
          style={{ gap: SEGMENT_GAP }}
        >
          {Array.from({ length: visibleCount }).map((_, j) => {
            const i = pageStart + j;
            return (
              <Segment
                key={i}
                isActive={i === current}
                isPast={i < current}
                progress={progress}
                paused={paused}
              />
            );
          })}
        </View>
        {paginated && <GhostStub visible={hasNextPage} />}
      </View>
      {paginated && current >= 0 && (
        <Text
          className="pt-1 text-center font-medium text-white/40"
          style={{ fontSize: 10, fontVariant: ['tabular-nums'] }}
        >
          {current + 1} / {total}
        </Text>
      )}
    </View>
  );
}

function GhostStub({ visible }: { visible: boolean }) {
  // Always reserve width so segments don't shift when stubs appear/disappear.
  if (!visible) {
    return <View style={{ width: STUB_WIDTH }} />;
  }
  return (
    <View
      className="overflow-hidden rounded-full bg-white/15"
      style={{
        width: STUB_WIDTH,
        height: SEGMENT_HEIGHT,
        alignSelf: 'flex-end',
      }}
    />
  );
}

interface SegmentProps {
  isActive: boolean;
  isPast: boolean;
  progress: number;
  paused: boolean;
}

function Segment({ isActive, isPast, progress, paused }: SegmentProps) {
  // Each segment owns its own width animation. Past = 1, future = 0,
  // active = animated toward `progress`. Reanimated keeps the tween on the
  // UI thread so JS thread stalls (e.g. the 100ms text tick re-render)
  // can't drop frames here.
  const fill = useSharedValue(isPast ? 1 : 0);

  useEffect(() => {
    if (isPast) {
      cancelAnimation(fill);
      fill.value = withTiming(1, {
        duration: 120,
        easing: Easing.out(Easing.cubic),
      });
      return;
    }
    if (!isActive) {
      cancelAnimation(fill);
      fill.value = 0;
      return;
    }
    if (paused) {
      cancelAnimation(fill);
      return;
    }
    fill.value = withTiming(progress, {
      duration: SMOOTHING_MS,
      easing: Easing.linear,
    });
  }, [isPast, isActive, progress, paused, fill]);

  const fillStyle = useAnimatedStyle(() => ({
    width: `${Math.min(Math.max(fill.value, 0), 1) * 100}%`,
  }));

  return (
    <View
      className="flex-1 overflow-hidden rounded-full bg-white/30"
      style={{ height: SEGMENT_HEIGHT }}
    >
      <Animated.View
        className="h-full bg-white/95 rounded-full"
        style={fillStyle}
      />
    </View>
  );
}
