import { useState, useRef, useMemo, useCallback, Dispatch, SetStateAction } from "react";
import {
  View,
  Text,
  StyleSheet,
  PanResponder,
  Animated,
  Dimensions,
  FlatList,
  ViewStyle,
} from "react-native";
import { Mutation } from "@tanstack/react-query";
import MutationButton from "./MutationButton";
import MutationInformation from "./MutationInformation";
import useAllMutations from "../../hooks/useAllMutations";
import { gameUIColors } from "@react-buoy/shared-ui";

interface Props {
  selectedMutation: Mutation | undefined;
  setSelectedMutation: Dispatch<
    SetStateAction<Mutation | undefined>
  >;
  activeFilter?: string | null;
  hideInfoPanel?: boolean;
  contentContainerStyle?: ViewStyle;
  searchText?: string;
}

/**
 * Virtualized list of mutations with filtering and selection support for the mutation browser.
 */
export default function MutationsList({
  selectedMutation,
  setSelectedMutation,
  activeFilter,
  hideInfoPanel = false,
  contentContainerStyle,
  searchText = "",
}: Props) {
  const { mutations: allmutations } = useAllMutations();

  // Helper function to get mutation status for filtering
  const getMutationStatus = (mutation: Mutation) => {
    if (mutation.state.isPaused) return "paused";
    const status = mutation.state.status;
    return status; // 'idle', 'pending', 'success', 'error'
  };

  // Filter mutations based on active filter and search text
  const filteredMutations = useMemo(() => {
    let filtered = allmutations;

    // Apply status filter
    if (activeFilter) {
      filtered = filtered.filter((mutation) => {
        const status = getMutationStatus(mutation);
        return status === activeFilter;
      });
    }

    // Apply search filter on mutation keys
    if (searchText) {
      const searchLower = searchText.toLowerCase();
      filtered = filtered.filter((mutation) => {
        const mutationKey = mutation.options.mutationKey;
        if (!mutationKey) return false;

        const keys = Array.isArray(mutationKey) ? mutationKey : [mutationKey];
        const keyString = keys
          .filter((k) => k != null)
          .map((k) => String(k))
          .join(" ")
          .toLowerCase();
        return keyString.includes(searchLower);
      });
    }

    return filtered;
  }, [allmutations, activeFilter, searchText]);

  // Height management for resizable mutation information panel
  const screenHeight = Dimensions.get("window").height;
  const defaultInfoHeight = screenHeight * 0.4; // 40% of screen height
  const minInfoHeight = 150;
  const maxInfoHeight = screenHeight * 0.7; // 70% of screen height

  const infoHeightAnim = useRef(new Animated.Value(defaultInfoHeight)).current;
  const [, setCurrentInfoHeight] = useState(defaultInfoHeight);
  const currentInfoHeightRef = useRef(defaultInfoHeight);

  // Pan responder for dragging the mutation information panel
  const infoPanResponder = useRef(
    PanResponder.create({
      onMoveShouldSetPanResponder: (evt, gestureState) => {
        return (
          Math.abs(gestureState.dy) > Math.abs(gestureState.dx) &&
          Math.abs(gestureState.dy) > 10
        );
      },
      onPanResponderGrant: () => {
        infoHeightAnim.stopAnimation((value) => {
          setCurrentInfoHeight(value);
          currentInfoHeightRef.current = value;
          infoHeightAnim.setValue(value);
        });
      },
      onPanResponderMove: (evt, gestureState) => {
        // Use the ref value which is always current
        const newHeight = currentInfoHeightRef.current - gestureState.dy;
        const clampedHeight = Math.max(
          minInfoHeight,
          Math.min(maxInfoHeight, newHeight),
        );
        infoHeightAnim.setValue(clampedHeight);
      },
      onPanResponderRelease: (evt, gestureState) => {
        const finalHeight = Math.max(
          minInfoHeight,
          Math.min(
            maxInfoHeight,
            currentInfoHeightRef.current - gestureState.dy,
          ),
        );
        setCurrentInfoHeight(finalHeight);
        currentInfoHeightRef.current = finalHeight;

        Animated.timing(infoHeightAnim, {
          toValue: finalHeight,
          duration: 200,
          useNativeDriver: false,
        }).start(() => {
          // Ensure the animated value and state are perfectly synced after animation
          infoHeightAnim.setValue(finalHeight);
          setCurrentInfoHeight(finalHeight);
          currentInfoHeightRef.current = finalHeight;
        });
      },
    }),
  ).current;

  // Optimize FlatList performance - memoize renderItem to prevent re-renders
  const renderMutation = useCallback(({ item }: { item: Mutation }) => (
    <MutationButton
      selected={selectedMutation}
      setSelectedMutation={setSelectedMutation}
      mutation={item}
    />
  ), [selectedMutation, setSelectedMutation]);

  return (
    <View style={styles.container}>
      {filteredMutations.length > 0 ? (
        <View style={styles.listWrapper}>
          <FlatList
            sentry-label="ignore devtools mutations list"
            data={filteredMutations}
            renderItem={renderMutation}
            keyExtractor={(item, index) => `${item.mutationId}-${item.state.submittedAt}-${item.state.status}-${index}`}
            showsVerticalScrollIndicator
            removeClippedSubviews
            contentContainerStyle={contentContainerStyle || styles.listContent}
            initialNumToRender={10}
            maxToRenderPerBatch={10}
            windowSize={10}
            scrollEnabled={false}
          />
        </View>
      ) : (
        <View style={styles.emptyContainer}>
          <Text style={styles.emptyText}>
            {activeFilter
              ? `No ${activeFilter} mutations found`
              : "No mutations found"}
          </Text>
        </View>
      )}
      {selectedMutation && !hideInfoPanel && (
        <Animated.View
          style={[styles.mutationInfo, { height: infoHeightAnim }]}
        >
          {/* Drag handle for resizing */}
          <View style={styles.dragHandle} {...infoPanResponder.panHandlers}>
            <View style={styles.dragIndicator} />
          </View>
          <View style={styles.mutationInfoContent}>
            <MutationInformation selectedMutation={selectedMutation} />
          </View>
        </Animated.View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: gameUIColors.background,
  },
  listWrapper: {
    flex: 1,
  },
  listContent: {
    backgroundColor: gameUIColors.background,
    paddingHorizontal: 8,
    paddingTop: 8,
  },
  mutationInfo: {
    borderTopWidth: 1,
    borderTopColor: gameUIColors.border + "40",
    backgroundColor: gameUIColors.background,
  },
  dragHandle: {
    height: 20,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: gameUIColors.panel,
    borderBottomWidth: 1,
    borderBottomColor: gameUIColors.border + "40",
  },
  dragIndicator: {
    width: 40,
    height: 4,
    backgroundColor: gameUIColors.border,
    borderRadius: 2,
  },
  mutationInfoContent: {
    flex: 1,
    backgroundColor: gameUIColors.background,
  },
  emptyContainer: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    padding: 32,
    backgroundColor: gameUIColors.panel,
    margin: 16,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: gameUIColors.border + "40",
  },
  emptyText: {
    color: gameUIColors.muted,
    fontSize: 14,
    textAlign: "center",
    fontFamily: "monospace",
    letterSpacing: 0.5,
  },
});
