import React, { useState, useRef, useCallback, useEffect, useMemo } from 'react';
import './styles.scss';
import { ListItemAvatar, ListItemText, Avatar } from '@mui/material';
import { ScrollSync, List as VirtualizedList, AutoSizer } from 'react-virtualized';
import 'react-virtualized/styles.css';
import { Input } from '../../../components/Input';
import { PanelListProps, User } from '../types';
import { CustomListItem } from './CustomListItem';
import { Checkbox } from '../../../components/Checkbox';

// Add custom styles for this specific use
const customCheckboxStyle = {
  '.cb-gtc-rc:before': {
    color: '#4CAF50'
  }
};

export const PanelList = (props: PanelListProps) => {
  const { 
    usersList = [], 
    selectedUsers = [], 
    onSelectUsers, 
    className = '', 
    isShowVisible = false,
    fetchMoreUsers,
    searchUsers,
    placeholderInputSearch = 'Search user',
    messageLoading = 'Loading more users...'
  } = props;

  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const [searchValue, setSearchValue] = useState('');
  const [debouncedSearchValue, setDebouncedSearchValue] = useState('');
  const [filteredUsers, setFilteredUsers] = useState<User[]>([]);
  const observer = useRef<IntersectionObserver | null>(null);
  const debounceTimeout = useRef<NodeJS.Timeout | null>(null);
  const selectedUsersContainerRef = useRef<HTMLDivElement>(null);

  // Last element ref for infinite scrolling
  const lastUserElementRef = useCallback((node: HTMLDivElement | null) => {
    if (loading || !hasMore) return;
    
    if (observer.current) observer.current.disconnect();
    
    observer.current = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting && hasMore) {
        setLoading(true);
        
        if (debouncedSearchValue && searchUsers) {
          // Si hay un término de búsqueda, usar searchUsers para cargar más resultados
          searchUsers(debouncedSearchValue)
            .then(result => {
              // Evitar duplicados mediante Set de IDs
              setFilteredUsers(prev => {
                const existingIds = new Set(prev.map(user => user.id));
                const newUsers = result.users.filter(user => !existingIds.has(user.id));
                return [...prev, ...newUsers];
              });
              setHasMore(result.hasMore);
              setLoading(false);
            })
            .catch(err => {
              console.error("Error loading more search results:", err);
              setLoading(false);
            });
        } else if (fetchMoreUsers) {
          // Si no hay término de búsqueda, usar fetchMoreUsers para cargar más usuarios
          fetchMoreUsers()
            .then(result => {
              // Evitar duplicados al cargar más usuarios
              setFilteredUsers(prev => {
                const existingIds = new Set(prev.map(user => user.id));
                const newUsers = result.users.filter(user => !existingIds.has(user.id));
                return [...prev, ...newUsers];
              });
              setHasMore(result.hasMore);
              setLoading(false);
            })
            .catch(err => {
              console.error("Error loading more users:", err);
              setLoading(false);
            });
        }
      }
    });
    
    if (node) observer.current.observe(node);
  }, [loading, hasMore, fetchMoreUsers, searchUsers, debouncedSearchValue]);

  // Handle user selection toggle
  const handleToggle = (user: User) => {
    const currentIndex = selectedUsers.findIndex(selectedUser => selectedUser.id === user.id);
    const newChecked = [...selectedUsers];

    if (currentIndex === -1) {
      newChecked.push(user);
    } else {
      newChecked.splice(currentIndex, 1);
    }

    onSelectUsers(newChecked);
  };

  

  // Filter selected users from the main list
  const displayUsers = useMemo(() => {
    const usersToFilter = filteredUsers.length > 0 ? filteredUsers : usersList;
    return usersToFilter.filter(user => 
      !selectedUsers.some(selectedUser => selectedUser.id === user.id)
    );
  }, [usersList, filteredUsers, selectedUsers]);

  // Renderer for virtualized list item
  const rowRenderer = ({ index, key, style }: { index: any; key: string; style: React.CSSProperties }) => {
    const usersToRender = displayUsers;
    
    if (index >= usersToRender.length) {
      if (loading) {
        return (
          <div key={key} style={style} className="loading-row">
            <CustomListItem>
              <ListItemText primary={messageLoading} />
            </CustomListItem>
          </div>
        );
      }
      return null;
    }

    const user = usersToRender[index];
    const isLast = index === usersToRender.length - 1;
    
    return (
      <div 
        key={key} 
        style={style} 
        ref={isLast ? lastUserElementRef : null}
      >
        <CustomListItem
          onClick={() => handleToggle(user)}
        >
          <ListItemAvatar>
            <Avatar
              alt={user.name}
              src={user.avatar}
              style={{ 
                width: 32, 
                height: 32,
                opacity: user.isActive === false ? 0.5 : 1,
                fontWeight: user.isActive === false ? 'normal' : 'bold'
              }}
            />
          </ListItemAvatar>
          <ListItemText 
            primary={<span className="user-name-ellipsis">{user.name}</span>} 
          />
          <div onClick={(e: React.MouseEvent) => e.stopPropagation()}>
            <Checkbox
              checked={selectedUsers.some(selectedUser => selectedUser.id === user.id)}
              onChange={() => handleToggle(user)}
            />
          </div>
        </CustomListItem>
      </div>
    );
  };

  // Render a selected user
  const renderSelectedUser = (user: User) => {
    return (
      <div key={user.id}>
        <CustomListItem
          onClick={() => handleToggle(user)}
        >
          <ListItemAvatar>
            <Avatar
              alt={user.name}
              src={user.avatar}
              className="selected-avatar"
              style={{ 
                width: 32, 
                height: 32,
              }}
            />
          </ListItemAvatar>
          <ListItemText 
            primary={<span className="user-name-wrap">{user.name}</span>} 
          />
          <div onClick={(e: React.MouseEvent) => e.stopPropagation()}>
            <Checkbox
              checked={selectedUsers.some(selectedUser => selectedUser.id === user.id)}
              onChange={() => handleToggle(user)}
            />
          </div>
        </CustomListItem>
      </div>
    );
  };

  // Load filtered users when component mounts
  useEffect(() => {
    // Initialize filteredUsers with all users
    setFilteredUsers(usersList);
  }, [usersList]);  

  // Debounce for search
  useEffect(() => {
    // Clear previous timeout if exists
    if (debounceTimeout.current) {
      clearTimeout(debounceTimeout.current);
    }

    // Set a new timeout (300ms is a good default value)
    debounceTimeout.current = setTimeout(() => {
      setDebouncedSearchValue(searchValue);
    }, 300);

    // Clear timeout when unmounting or when searchValue changes
    return () => {
      if (debounceTimeout.current) {
        clearTimeout(debounceTimeout.current);
      }
    };
  }, [searchValue]);

  // Execute search when debounced value changes
  useEffect(() => {
    if (debouncedSearchValue) {
      handleSearch(debouncedSearchValue);
    } else {
      setFilteredUsers([]);
      setHasMore(true);
    }
  }, [debouncedSearchValue, usersList]);

  const handleSearch = async (value: string) => {
    if (!value.trim()) {
      setFilteredUsers(usersList);
      setHasMore(true);
      return;
    }

    // Si tenemos searchUsers, siempre usarlo para búsqueda
    if (searchUsers) {
      try {
        const result = await searchUsers(value);
        if (!result || !result.users || result.users.length === 0) {
          setFilteredUsers([]);
          setHasMore(false);
          return;
        }
        setFilteredUsers(result.users);
        setHasMore(result.hasMore);
      } catch (error) {
        console.error("Error searching users:", error);
        setFilteredUsers([]);
        setHasMore(false);
      }
    } else {
      // Solo buscar localmente si no tenemos searchUsers
      const localResults = usersList.filter(user => 
        user.name.toLowerCase().includes(value.toLowerCase()) || 
        (user.email && user.email.toLowerCase().includes(value.toLowerCase()))
      );
      setFilteredUsers(localResults);
      setHasMore(false);
    }
  }

  // Scroll to bottom when a new selected user is added
  useEffect(() => {
    if (selectedUsersContainerRef.current && selectedUsers.length > 0) {
      const container = selectedUsersContainerRef.current;
      // Increase timeout to ensure DOM has fully updated
      setTimeout(() => {
        container.scrollTo({
          top: container.scrollHeight,
          behavior: 'smooth'
        });
      }, 50);
    }
  }, [selectedUsers]);

  // Check if component should be shown after defining all hooks
  if (!isShowVisible) {
    return null;
  }

  // Render with virtualization
  return (
    <div className={`panel-list ${className}`}>
      <div className="search-container">
        <Input 
          type="text" 
          placeholder={placeholderInputSearch}
          value={searchValue} 
          onChange={(value) => {
            setSearchValue(value);
          }}
        />
      </div>
      {selectedUsers.length > 0 && (
        <div className="user-selected">
          <div 
            className="user-selected-list" 
            ref={selectedUsersContainerRef}
            style={{ maxHeight: '200px', overflowY: 'auto' }}
          >
            {selectedUsers.map(user => renderSelectedUser(user))}
          </div>
        </div>
      )}
      <div style={{ height: '350px', width: '100%', marginTop: '10px' }}>
        <ScrollSync>
          {({ onScroll, scrollTop }) => (
            <AutoSizer>
              {({ height, width }) => (
                <VirtualizedList
                  height={height * 1.6}
                  rowCount={displayUsers.length + (loading ? 1 : 0)}
                  rowHeight={60}
                  rowRenderer={rowRenderer}
                  scrollTop={scrollTop}
                  width={width}
                  onScroll={onScroll}
                  overscanRowCount={25}
                />
              )}
            </AutoSizer>
          )}
        </ScrollSync>
      </div>
    </div>
  );
}
