import { View, Text, ScrollView, StyleSheet, Dimensions } from "react-native";
import React, { useEffect, useMemo, useState } from "react";
import Animated, {
  runOnJS,
  useAnimatedGestureHandler,
  useAnimatedStyle,
  useSharedValue,
  withSpring,
} from "react-native-reanimated";
import { PanGestureHandler } from "react-native-gesture-handler";

const { width } = Dimensions.get("window");

// Child component to respect Rules of Hooks (no hooks in loops)
const DraggableItem = ({ item, gestureHandler, draggingItem, translateX, translateY, onActivate }) => {
  const style = useAnimatedStyle(() => ({
    transform: [
      { translateX: draggingItem.value === item.id ? translateX.value : 0 },
      { translateY: draggingItem.value === item.id ? translateY.value : 0 },
    ],
    zIndex: draggingItem.value === item.id ? 10 : 0,
  }));

  return (
    <PanGestureHandler
      onGestureEvent={gestureHandler}
      onHandlerStateChange={() => onActivate(item.id)}
    >
      <Animated.View style={[styles.item, style]}>
        <Text style={styles.text}>{item.label ?? String(item)}</Text>
      </Animated.View>
    </PanGestureHandler>
  );
};

// Props:
// - sourceItems: array of { id, label, value } or strings
// - initialSelected: array of ids to prefill right side (optional)
// - onChange: callback with array of values (or strings) in right order
const SongStructureDragDrop = ({ sourceItems, initialSelected, onChange }) => {
  const normalize = (arr = []) =>
    arr.map((item, idx) =>
      typeof item === "string"
        ? { id: `${item}-${idx}`, label: item, value: item }
        : item,
    );

  const normalizedSource = useMemo(
    () => normalize(sourceItems || []),
    [sourceItems],
  );

  const [leftItems, setLeftItems] = useState(normalizedSource);
  const [rightItems, setRightItems] = useState([]);

  // Compare arrays by item id and order to avoid unnecessary state churn
  const sameById = (a = [], b = []) => {
    if (a === b) return true;
    if (!a || !b) return false;
    if (a.length !== b.length) return false;
    for (let idx = 0; idx < a.length; idx++) {
      if (a[idx]?.id !== b[idx]?.id) return false;
    }
    return true;
  };

  useEffect(() => {
    const selected = Array.isArray(initialSelected) ? initialSelected : [];
    const selectedSet = new Set(selected);
    const right = normalizedSource.filter((i) => selectedSet.has(i.id));
    const left = normalizedSource.filter((i) => !selectedSet.has(i.id));

    setLeftItems((prev) => (sameById(prev, left) ? prev : left));
    setRightItems((prev) => (sameById(prev, right) ? prev : right));
  }, [normalizedSource, initialSelected]);

  const draggingItem = useSharedValue(null);
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  const onActivate = (id) => {
    draggingItem.value = id;
  };

  const moveItem = (itemId) => {
    setLeftItems((items) => {
      const found = items.find((i) => i.id === itemId);
      if (!found) return items;
      setRightItems((r) => {
        const next = [...r, found];
        onChange?.(next.map((i) => i.value ?? i.label));
        return next;
      });
      return items.filter((i) => i.id !== itemId);
    });
  };

  const gestureHandler = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startX = translateX.value;
      ctx.startY = translateY.value;
    },
    onActive: (event, ctx) => {
      translateX.value = ctx.startX + event.translationX;
      translateY.value = ctx.startY + event.translationY;
    },
    onEnd: () => {
      if (translateX.value > width / 2) {
        runOnJS(moveItem)(draggingItem.value);
      }
      translateX.value = withSpring(0);
      translateY.value = withSpring(0);
      draggingItem.value = null;
    },
  });

  return (
    <View style={styles.scrollWrapper}>
      <ScrollView style={{ ...styles.scroll, zIndex: 2 }}>
        <Text style={styles.title}>Left</Text>
        {leftItems.map((item) => (
          <DraggableItem
            key={item.id}
            item={item}
            gestureHandler={gestureHandler}
            draggingItem={draggingItem}
            translateX={translateX}
            translateY={translateY}
            onActivate={onActivate}
          />
        ))}
      </ScrollView>

      <ScrollView style={{ ...styles.scroll, zIndex: -1 }}>
        <Text style={styles.title}>Right</Text>
        {rightItems.map((item) => (
          <View key={item.id} style={[styles.item, { backgroundColor: "#bdf" }]}>
            <Text style={styles.text}>{item.label ?? String(item)}</Text>
          </View>
        ))}
      </ScrollView>
    </View>
  );
};

export default SongStructureDragDrop;

const styles = StyleSheet.create({
  scrollWrapper: {
    flexDirection: "row",
    justifyContent: "space-around",
  },
  scroll: {
    width: width / 2.2,
    height: "90%",
    backgroundColor: "#f0f0f0",
    borderRadius: 10,
    margin: 5,
    padding: 10,
  },
  title: {
    fontWeight: "bold",
    fontSize: 16,
    marginBottom: 10,
  },
  item: {
    backgroundColor: "#aaf",
    padding: 15,
    marginVertical: 5,
    borderRadius: 10,
  },
  text: {
    color: "#333",
    textAlign: "center",
  },
});
