import React, { useState, useEffect, useCallback, useRef } from 'react';
import {
  Animated,
  StyleSheet,
  FlatList,
  TouchableOpacity,
  RefreshControl,
  ActivityIndicator,
  AppState,
  AppStateStatus,
  Platform,
} from 'react-native';
import { supabase } from '@/lib/supabase';
import { ThemedView, ThemedText } from '@/components/theme';
import { formatDistanceToNow } from 'date-fns';
import StatusCard from './StatusCard';
import ProfileAvatar from '@/components/auth/Profile_Avatar';
import { useIsFocused } from '@react-navigation/native';
import { RealtimeChannel } from '@supabase/supabase-js';
import { UserStatus } from '@/constants/Types';
import debounce from 'lodash/debounce';
import NetInfo from '@react-native-community/netinfo';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';

const StatusList = () => {
  const scheme = useColorScheme() ?? 'dark';

  const [statuses, setStatuses] = useState<UserStatus[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [selectedUser, setSelectedUser] = useState<UserStatus | null>(null);
  const [showStatusCard, setShowStatusCard] = useState(false);
  const [recentlyUpdatedIds, setRecentlyUpdatedIds] = useState<Set<string>>(new Set());
  const [isConnected, setIsConnected] = useState(true);
  const [lastFetchTime, setLastFetchTime] = useState<Date | null>(null);
  
  const fadeAnimation = useRef(new Animated.Value(0)).current;
  const isFocused = useIsFocused();
  const subscriptionRef = useRef<RealtimeChannel | null>(null);
  const appStateRef = useRef(AppState.currentState);
  const pendingUpdatesRef = useRef<Set<string>>(new Set());
  
  // Debounced version of the status update handler
  const debouncedHandleStatusUpdates = useRef(
    debounce(() => {
      if (pendingUpdatesRef.current.size > 0) {
        const statusesToFetch = Array.from(pendingUpdatesRef.current);
        pendingUpdatesRef.current.clear();
        
        // Fetch all pending status updates in a single query
        fetchMultipleStatuses(statusesToFetch);
      }
    }, 500)
  ).current;
  
  // Fetch multiple statuses at once
  const fetchMultipleStatuses = async (statusIds: string[]) => {
    if (statusIds.length === 0) return;
    
    try {
      const { data, error } = await supabase
        .from('statuses')
        .select(`
          id,
          user_id,
          status,
          created_at,
          profiles:profiles(full_name, avatar_url)
        `)
        .in('id', statusIds);
        
      if (error) throw error;
      
      if (data && data.length > 0) {
        // Transform the data
        const transformedData = data.map(item => ({
          ...item,
          profiles: Array.isArray(item.profiles) ? item.profiles[0] : item.profiles
        }));
        
        // Update statuses
        setStatuses(prevStatuses => {
          const newStatuses = [...prevStatuses];
          const updatedIds = new Set<string>();
          
          // Process each new status
          transformedData.forEach(newStatus => {
            const existingIndex = newStatuses.findIndex(s => s.user_id === newStatus.user_id);
            
            if (existingIndex !== -1) {
              // If the new status is more recent, replace the existing one
              if (new Date(newStatus.created_at) > new Date(newStatuses[existingIndex].created_at)) {
                newStatuses[existingIndex] = newStatus;
                updatedIds.add(newStatus.id);
              }
            } else {
              // If this is a new user, add to the array
              newStatuses.push(newStatus);
              updatedIds.add(newStatus.id);
            }
          });
          
          // Sort by most recent
          newStatuses.sort((a, b) =>
            new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
          );
          
          // Mark updated statuses for highlighting
          if (updatedIds.size > 0) {
            setRecentlyUpdatedIds(prev => {
              const newSet = new Set(prev);
              updatedIds.forEach(id => newSet.add(id));
              
              // Schedule removal of highlights
              setTimeout(() => {
                setRecentlyUpdatedIds(current => {
                  const updatedSet = new Set(current);
                  updatedIds.forEach(id => updatedSet.delete(id));
                  return updatedSet;
                });
              }, 3000);
              
              return newSet;
            });
            
            // Animate the fade-in
            Animated.sequence([
              Animated.timing(fadeAnimation, {
                toValue: 1,
                duration: 300,
                useNativeDriver: true,
              }),
              Animated.timing(fadeAnimation, {
                toValue: 0,
                duration: 300,
                delay: 2000,
                useNativeDriver: true,
              }),
            ]).start();
          }
          
          return newStatuses;
        });
      }
    } catch (error) {
      console.error('Error fetching multiple statuses:', error);
    }
  };
  
  // Fetch statuses with time filtering
  const fetchStatuses = useCallback(async (forceRefresh = false) => {
    try {
      if (!isConnected) {
        console.log('Skipping fetch - device is offline');
        setLoading(false);
        setRefreshing(false);
        return;
      }
      
      // Get current time
      const now = new Date();
      setLastFetchTime(now);
      
      // Calculate time filter - only get statuses from the last week
      // unless it's a force refresh
      let query = supabase
        .from('statuses')
        .select(`
          id,
          user_id,
          status,
          created_at,
          profiles:profiles(full_name, avatar_url)
        `)
        .order('created_at', { ascending: false });
      
      if (!forceRefresh) {
        const oneWeekAgo = new Date();
        oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
        query = query.gte('created_at', oneWeekAgo.toISOString());
      }
      
      const { data, error } = await query;
      
      if (error) throw error;
      
      if (data) {
        // Transform the data to match our expected type
        const transformedData = data.map(item => ({
          ...item,
          profiles: Array.isArray(item.profiles) ? item.profiles[0] : item.profiles
        }));
        
        // Get unique users with their latest status
        const userMap = new Map();
        transformedData.forEach(status => {
          if (!userMap.has(status.user_id) ||
              new Date(status.created_at) > new Date(userMap.get(status.user_id).created_at)) {
            userMap.set(status.user_id, status);
          }
        });
        
        // Convert map to array and sort by most recent
        const latestUserStatuses = Array.from(userMap.values());
        latestUserStatuses.sort((a, b) =>
          new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
        );
        
        setStatuses(latestUserStatuses);
      }
    } catch (error) {
      console.error('Error fetching statuses:', error);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  }, [isConnected]);
  
  // Handle individual status update
  const handleNewStatus = useCallback((statusId: string) => {
    // Add to pending updates
    pendingUpdatesRef.current.add(statusId);
    
    // Trigger the debounced handler
    debouncedHandleStatusUpdates();
  }, [debouncedHandleStatusUpdates]);
  
  // Set up network connectivity listener
  useEffect(() => {
    const unsubscribe = NetInfo.addEventListener(state => {
      setIsConnected(state.isConnected ?? false);
      
      // If we're coming back online and we have a last fetch time
      // that's more than 1 minute old, refresh the data
      if (state.isConnected && lastFetchTime) {
        const now = new Date();
        const timeDiff = now.getTime() - lastFetchTime.getTime();
        if (timeDiff > 60000) { // 1 minute
          fetchStatuses();
        }
      }
    });
    
    return () => {
      unsubscribe();
    };
  }, [fetchStatuses, lastFetchTime]);
  
  // Set up AppState listener for background/foreground transitions
  useEffect(() => {
    const handleAppStateChange = (nextAppState: AppStateStatus) => {
      if (
        appStateRef.current.match(/inactive|background/) &&
        nextAppState === 'active'
      ) {
        console.log('App has come to the foreground!');
        // Refresh data if we've been in the background for a while
        if (lastFetchTime) {
          const now = new Date();
          const timeDiff = now.getTime() - lastFetchTime.getTime();
          if (timeDiff > 60000) { // 1 minute
            fetchStatuses();
          }
        }
        
        // Reconnect to realtime if needed
        if (!subscriptionRef.current && isFocused) {
          setupRealtimeSubscription();
        }
      }
      
      appStateRef.current = nextAppState;
    };
    
    const subscription = AppState.addEventListener('change', handleAppStateChange);
    
    return () => {
      subscription.remove();
    };
  }, [fetchStatuses, isFocused, lastFetchTime]);
  
  // Set up realtime subscription
  const setupRealtimeSubscription = useCallback(() => {
    // Get only statuses from the last week to reduce payload
    const oneWeekAgo = new Date();
    oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
    
    const subscription = supabase
      .channel('status_changes')
      .on('postgres_changes',
        {
          event: 'INSERT',
          schema: 'public',
          table: 'statuses',
          filter: `created_at>gt.${oneWeekAgo.toISOString()}`
        },
        (payload) => {
          console.log('New status received:', payload);
          handleNewStatus(payload.new.id);
        }
      )
      .subscribe((status) => {
        console.log('Realtime subscription status:', status);
      });
    
    subscriptionRef.current = subscription;
    return subscription;
  }, [handleNewStatus]);
  
  // Set up real-time subscription when component is focused
  useEffect(() => {
    if (isFocused && isConnected) {
      // Initial fetch
      fetchStatuses();
      
      // Set up real-time subscription
      const subscription = setupRealtimeSubscription();
      
      // Clean up subscription when component unmounts or loses focus
      return () => {
        if (subscription) {
          supabase.removeChannel(subscription);
          subscriptionRef.current = null;
        }
      };
    }
  }, [isFocused, isConnected, fetchStatuses, setupRealtimeSubscription]);
  
  // Handle refresh
  const onRefresh = useCallback(() => {
    setRefreshing(true);
    fetchStatuses(true); // Force refresh to get all statuses
  }, [fetchStatuses]);
  
  const handleUserSelect = useCallback((user: UserStatus) => {
    setSelectedUser(user);
    setShowStatusCard(true);
  }, []);
  
  const handleStatusUpdate = useCallback(() => {
    setShowStatusCard(false);
    // No need to manually fetch statuses here since the real-time subscription will handle it
  }, []);
  
  const formatDate = useCallback((dateString: string) => {
    const date = new Date(dateString);
    return {
      time: date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
      date: date.toLocaleDateString([], { month: 'short', day: 'numeric' }),
      relative: formatDistanceToNow(date, { addSuffix: true })
    };
  }, []);
  
  // Memoize the list item renderer for better performance
  const renderItem = useCallback(({ item }: { item: UserStatus }) => {
    const formattedDate = formatDate(item.created_at);
    
    return (
      <TouchableOpacity
        style={[
          styles.statusItem,
          recentlyUpdatedIds.has(item.id) && styles.recentlyUpdated,
          {backgroundColor: Colors[scheme].card},
        ]}
        onPress={() => handleUserSelect(item)}
        activeOpacity={0.7}
      >
        <ThemedView style={styles.contentContainer}>
          <ThemedView style={styles.topRow}>
            <ThemedView style={styles.userContainer}>
              <ThemedView style={styles.avatarContainer}>
                <ProfileAvatar
                  url={item.profiles.avatar_url}
                  size={30}
                  disabled={true}
                />
              </ThemedView>
              <ThemedText
                type='custom'
                fontSize={24}
                fontWeight='bold'
              >
                {item.profiles.full_name}
              </ThemedText>
            </ThemedView>
          </ThemedView>
          <ThemedView style={styles.bottomRow}>
            <ThemedText type='custom' fontSize={18} style={styles.statusText}>
              {item.status}
            </ThemedText>
          </ThemedView>
        </ThemedView>
        <ThemedView style={styles.timeContainer}>
          <ThemedText type='custom' fontSize={20} fontWeight='semibold'>
            {formattedDate.time}
          </ThemedText>
          <ThemedText type='custom' fontSize={20} fontWeight='500'>
            {formattedDate.date}
          </ThemedText>
        </ThemedView>
      </TouchableOpacity>
    );
  }, [formatDate, handleUserSelect, recentlyUpdatedIds]);
  
  // Empty list component
  const ListEmptyComponent = useCallback(() => (
    <ThemedView style={styles.emptyContainer}>
      <ThemedText style={styles.emptyText}>
        {isConnected ? 'No statuses available' : 'You are offline'}
      </ThemedText>
    </ThemedView>
  ), [isConnected]);
  
  if (loading) {
    return (
      <ThemedView style={styles.loadingContainer}>
        <ActivityIndicator size="large" />
      </ThemedView>
    );
  }
  
  return (
    <ThemedView style={styles.container}>
      {!isConnected && (
        <ThemedView style={styles.offlineBar}>
          <ThemedText style={styles.offlineText}>You are offline</ThemedText>
        </ThemedView>
      )}
      
      <FlatList
        data={statuses}
        keyExtractor={(item) => item.id}
        refreshControl={
          <RefreshControl 
            refreshing={refreshing} 
            onRefresh={onRefresh}
            enabled={isConnected}
          />
        }
        renderItem={renderItem}
        ListEmptyComponent={ListEmptyComponent}
        initialNumToRender={10}
        maxToRenderPerBatch={10}
        windowSize={10}
        removeClippedSubviews={Platform.OS !== 'web'}
        getItemLayout={(data, index) => (
          {length: 120, offset: 120 * index, index}
        )}
      />
      
      {selectedUser && (
        <StatusCard
          visible={showStatusCard}
          user={selectedUser}
          onClose={() => setShowStatusCard(false)}
          onUpdate={handleStatusUpdate}
        />
      )}
    </ThemedView>
  );
};

export default React.memo(StatusList);

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  statusItem: {
    flexDirection: 'row',
    padding: 16,
    borderRadius: 12,
    marginHorizontal: 16,
    marginVertical: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
    elevation: 2,
    height: 104, // Fixed height for getItemLayout optimization
  },
  recentlyUpdated: {
    backgroundColor: 'rgba(100, 200, 255, 0.1)',
    borderLeftWidth: 3,
    borderLeftColor: '#4C9EFF',
  },
  userContainer: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'transparent',
  },
  avatarContainer: {
    marginRight: 4,
    backgroundColor: 'transparent',
  },
  contentContainer: {
    flex: 1,
    justifyContent: 'space-between',
    backgroundColor: 'transparent',
  },
  topRow: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'transparent',
  },
  timeContainer: {
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'transparent',
  },
  bottomRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    backgroundColor: 'transparent',
  },
  statusText: {
    flex: 1,
    marginLeft: 8,
    marginRight: 4,
  },
  emptyContainer: {
    padding: 20,
    alignItems: 'center',
  },
  emptyText: {
    fontSize: 16,
    opacity: 0.6,
  },
  offlineBar: {
    backgroundColor: '#FF3B30',
    padding: 8,
    alignItems: 'center',
  },
  offlineText: {
    color: 'white',
    fontWeight: 'bold',
  },
});
