import { useEffect, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  runOnJS,
} from "react-native-reanimated";
import { LinearGradient } from "./LinearGradient/LinearGradient";
import { Palette, Style } from "../styles";
import { FONT_FAMILY } from "../styles/Fonts";

const INITIAL_BOX_SIZE = 6;

export default ({ value, maxValue, progress, onSeek, onSeekStart, onSeekEnd, seekEnabled = false }) => {
  const offset = useSharedValue(0);
  const boxWidth = useSharedValue(INITIAL_BOX_SIZE);
  const [layout, setLayout] = useState(null);

  const SLIDER_WIDTH = layout?.width;
  const MAX_VALUE = SLIDER_WIDTH - INITIAL_BOX_SIZE;

  const pan = Gesture.Pan()
    .enabled(seekEnabled)
    .onBegin(() => {
      if (seekEnabled && typeof onSeekStart === 'function') {
        // Notify JS thread that user started seeking (e.g., pause audio)
        runOnJS(onSeekStart)();
      }
    })
    .onChange((event) => {
      offset.value =
        Math.abs(offset.value) <= MAX_VALUE
          ? offset.value + event.changeX <= 0
            ? 0
            : offset.value + event.changeX >= MAX_VALUE
            ? MAX_VALUE
            : offset.value + event.changeX
          : offset.value;

      const newWidth = INITIAL_BOX_SIZE + offset.value;
      boxWidth.value = newWidth;
    })
    .onEnd(() => {
      if (!seekEnabled || !onSeek || !MAX_VALUE) return;
      const ratio = MAX_VALUE > 0 ? Math.min(1, Math.max(0, offset.value / MAX_VALUE)) : 0;
      // Reanimated -> JS thread bridge
      runOnJS(onSeek)(ratio);
    })
    .onFinalize(() => {
      if (seekEnabled && typeof onSeekEnd === 'function') {
        runOnJS(onSeekEnd)();
      }
    });

  // Reflect external progress into the slider UI
  useEffect(() => {
    if (typeof progress === "number" && layout?.width) {
      const max = layout.width - INITIAL_BOX_SIZE;
      const clamped = Math.max(0, Math.min(1, progress));
      const newOffset = clamped * max;
      offset.value = newOffset;
      boxWidth.value = INITIAL_BOX_SIZE + newOffset;
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [progress, layout?.width]);

  const boxStyle = useAnimatedStyle(() => {
    return {
      width: INITIAL_BOX_SIZE + offset.value,
    };
  });

  const sliderStyle = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: offset.value }],
    };
  });

  return (
    <View onLayout={(e) => setLayout(e.nativeEvent.layout)}>
      <View style={{ ...styles.sliderTrack, width: SLIDER_WIDTH }}>
        <Animated.View style={[styles.box, boxStyle]}>
          <LinearGradient
            colors={["#F94697", "#7023F7"]}
            start={{ x: 0, y: 0 }}
            end={{ x: 1, y: 0 }}
            style={{ flex: 1, borderRadius: 20 }}
          />
        </Animated.View>
        <GestureDetector gesture={pan}>
          <Animated.View style={[styles.sliderHandle, sliderStyle]} />
        </GestureDetector>
      </View>
      <View style={{ ...Style.containerSpaceBetween, marginTop: 10 }}>
        <Text style={styles.time}>{value}</Text>
        <Text style={styles.time}>{maxValue}</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  box: {
    height: INITIAL_BOX_SIZE,
    borderRadius: 20,
    position: "absolute",
    zIndex: 1,
  },
  sliderHandle: {
    width: 20,
    height: 20,
    backgroundColor: "#f8f9ff",
    borderRadius: 25,
    position: "absolute",
    zIndex: 2,
    borderWidth: 4,
    borderColor: "#9B4DFF",
    shadowColor: "#8951FC",
    shadowOffset: {
      width: 0,
      height: 3,
    },
    shadowOpacity: 0.17,
    shadowRadius: 3.05,
    elevation: 4,
  },
  sliderTrack: {
    height: 6,
    backgroundColor: "#0F0C19",
    borderRadius: 25,
    justifyContent: "center",
  },
  time: {
    fontSize: 14,
    color: Palette.white,
    fontFamily: FONT_FAMILY.InterRegular,
  },
});
