import React, { useState, useEffect, useRef, useCallback } from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  Image,
  Platform,
  TouchableHighlight,
  AppState,
  AppStateStatus
} from 'react-native';
import {
  AvatarWithInitials,
  HorizontalTabView,
  Input,
  PageWrapper,
  WarningModal
} from 'src/components';
import { NAVIGATION_PAGES } from 'src/types';
import { useFocusEffect, useNavigation } from '@react-navigation/native';

import AddChatIcon from 'assets/icons/messages/chat-plus.svg';
import { API_HOST, WEBSOCKET_URL } from 'src/constants';
import { Colors } from 'src/theme';
import SwipeableRow from './Components/SwipeableRow';
import { FlashList } from '@shopify/flash-list';

import ReadIcon from 'assets/icons/messages/check-read.svg';
import UnreadIcon from 'assets/icons/messages/check-unread.svg';
import SearchModal from './Components/SearchUsersModal';
import { SheetManager } from 'react-native-actions-sheet';
import MoreModal from './Components/MoreModal';
import SearchIcon from 'assets/icons/search.svg';
import { storage, StoreType } from 'src/storage';
import { usePostGetBlockedQuery, usePostGetChatsListQuery } from '@api/chat';
import { Blocked, Chat } from './types';

import PinIcon from 'assets/icons/messages/pin.svg';
import { formatDate } from './utils';
import { routes } from './constants';
import { styles } from './styles';
import { useChatStore } from 'src/stores/chatStore';
import BellSlashIcon from 'assets/icons/messages/bell-slash.svg';
import BanIcon from 'assets/icons/messages/ban.svg';
import SwipeableBlockedRow from './Components/SwipeableBlockedRow';
import { useMessagesStore } from 'src/stores/unreadMessagesStore';

const TypingIndicator = () => {
  const [dots, setDots] = useState('');

  useEffect(() => {
    const interval = setInterval(() => {
      setDots((prevDots) => {
        if (prevDots.length >= 3) {
          return '';
        }
        return prevDots + '.';
      });
    }, 500);

    return () => clearInterval(interval);
  }, []);

  return <Text style={styles.typingText}>Typing{dots}</Text>;
};

const MessagesScreen = () => {
  const navigation = useNavigation();
  const token = storage.get('token', StoreType.STRING) as string;
  const [chats, setChats] = useState<Chat[]>([]);
  const [index, setIndex] = useState(0);
  const { data: chatsData, refetch } = usePostGetChatsListQuery(token, index === 2 ? 1 : 0, true);
  const { data: blockedData, refetch: refetchBlocked } = usePostGetBlockedQuery(token, true);
  const [blocked, setBlocked] = useState<Blocked[]>([]);
  const updateUnreadMessagesCount = useMessagesStore((state) => state.updateUnreadMessagesCount);

  const [filteredChats, setFilteredChats] = useState<{
    all: Chat[];
    unread: Chat[];
    archived: Chat[];
    blocked: Blocked[];
  }>({ all: [], unread: [], archived: [], blocked: [] });
  const [search, setSearch] = useState('');
  const openRowRef = useRef<any>(null);
  const { isWarningModalVisible, setIsWarningModalVisible } = useChatStore();
  const [typingUsers, setTypingUsers] = useState<{ [key: string]: boolean }>({});

  const appState = useRef(AppState.currentState);

  const socket = useRef<WebSocket | null>(null);

  const initializeSocket = () => {
    if (socket.current) {
      socket.current.close();
    }

    setTimeout(() => {
      socket.current = new WebSocket(WEBSOCKET_URL);

      socket.current.onopen = () => {
        socket.current?.send(JSON.stringify({ token }));
      };

      socket.current.onmessage = (event) => {
        const data = JSON.parse(event.data);
        handleWebSocketMessage(data);
      };

      socket.current.onclose = () => {
        console.log('WebSocket connection closed');
      };
    }, 500);
  };

  useEffect(() => {
    const handleAppStateChange = (nextAppState: AppStateStatus) => {
      if (appState.current.match(/inactive|background/) && nextAppState === 'active') {
        if (!socket.current || socket.current.readyState === WebSocket.CLOSED) {
          socket.current = new WebSocket(WEBSOCKET_URL);
          socket.current.onopen = () => {
            socket.current?.send(JSON.stringify({ token }));
          };
          socket.current.onmessage = (event) => {
            const data = JSON.parse(event.data);
            handleWebSocketMessage(data);
          };
        }
      }
    };

    const subscription = AppState.addEventListener('change', handleAppStateChange);

    return () => {
      subscription.remove();
      if (socket.current) {
        socket.current.close();
        socket.current = null;
      }
    };
  }, [token]);

  useEffect(() => {
    const pingInterval = setInterval(() => {
      if (socket.current && socket.current.readyState === WebSocket.OPEN) {
        socket.current.send(JSON.stringify({ action: 'ping', conversation_with: 0 }));
      } else {
        initializeSocket();

        return () => {
          if (socket.current) {
            socket.current.close();
            socket.current = null;
          }
        };
      }
    }, 50000);

    return () => clearInterval(pingInterval);
  }, []);

  const handleWebSocketMessage = (data: any) => {
    switch (data.action) {
      case 'new_message':
      case 'messages_read':
        refetch();
        break;
      case 'is_typing':
        if (data.conversation_with) {
          setTypingUsers((prev) => ({
            ...prev,
            [data.conversation_with]: true
          }));
        }
        break;
      case 'stopped_typing':
        if (data.conversation_with) {
          setTypingUsers((prev) => ({
            ...prev,
            [data.conversation_with]: false
          }));
        }
        break;
      default:
        break;
    }
  };

  const handleRowOpen = (ref: any) => {
    if (openRowRef.current && openRowRef.current !== ref) {
      openRowRef.current.close();
    }
    openRowRef.current = ref;
  };

  useFocusEffect(() => {
    navigation.getParent()?.setOptions({
      tabBarStyle: {
        display: 'flex',
        ...Platform.select({
          android: {
            height: 58
          }
        })
      }
    });
  });

  useEffect(() => {
    if (chatsData && chatsData.conversations) {
      setChats(chatsData.conversations);
    }
  }, [chatsData]);

  useEffect(() => {
    if (blockedData && blockedData.blocked) {
      setBlocked(blockedData.blocked);
    }
  }, [blockedData]);

  useFocusEffect(
    useCallback(() => {
      refetch();
      initializeSocket();
      updateUnreadMessagesCount();

      return () => {
        if (socket.current) {
          socket.current.close();
          socket.current = null;
        }
      };
    }, [token])
  );

  const filterChatsByTab = () => {
    let filteredList = chats;

    if (index === 3) {
      setFilteredChats((prev) => ({ ...prev, blocked }));
      return;
    }

    if (index === 1) {
      filteredList = chats.filter((chat) => chat.unread_count > 0);
    }

    filteredList.sort((a, b) => {
      if (b.pin - a.pin !== 0) {
        return b.pin - a.pin;
      }
      if (b.pin_order - a.pin_order !== 0) {
        return b.pin_order - a.pin_order;
      }

      return new Date(b.updated).getTime() - new Date(a.updated).getTime();
    });
    setFilteredChats((prev) => ({ ...prev, [routes[index].key]: filteredList }));
  };

  useEffect(() => {
    filterChatsByTab();
  }, [chats, index, blocked]);

  const searchFilter = (text: string) => {
    if (text) {
      const newData =
        chats?.filter((item: Chat) => {
          const itemData = item.short ? item.short.toLowerCase() : ''.toLowerCase();
          const textData = text.toLowerCase();
          return itemData.indexOf(textData) > -1;
        }) ?? [];
      setFilteredChats((prev) => ({ ...prev, [routes[index].key]: newData }));
      setSearch(text);
    } else {
      filterChatsByTab();
      setSearch(text);
    }
  };

  const renderChatItem = ({ item }: { item: Chat }) => {
    return (
      <SwipeableRow
        chat={{
          uid: item.uid,
          name: item.name,
          avatar: item.avatar,
          pin: item.pin,
          archive: item.archive,
          muted: item.muted
        }}
        token={token}
        onRowOpen={handleRowOpen}
        refetch={refetch}
        refetchBlocked={refetchBlocked}
      >
        <TouchableHighlight
          key={`${item.uid}-${typingUsers[item.uid]}`}
          activeOpacity={0.8}
          onPress={() =>
            navigation.navigate(
              ...([
                NAVIGATION_PAGES.CHAT,
                {
                  id: item.uid,
                  name: item.name,
                  avatar: item.avatar
                }
              ] as never)
            )
          }
          underlayColor={Colors.FILL_LIGHT}
        >
          <View style={styles.chatItem}>
            {item.avatar ? (
              <Image source={{ uri: API_HOST + item.avatar }} style={styles.avatar} />
            ) : (
              <AvatarWithInitials
                text={
                  item.name
                    .split(/ (.+)/)
                    .map((n) => n[0])
                    .join('') ?? ''
                }
                flag={API_HOST + item?.flag}
                size={54}
              />
            )}

            <View style={{ flex: 1, gap: 6 }}>
              <View style={[styles.rowContainer, { alignItems: 'center' }]}>
                <Text style={styles.chatName}>{item.name}</Text>

                <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
                  {item.pin === 1 ? <PinIcon height={12} fill={Colors.DARK_BLUE} /> : null}
                  {item.muted === 1 ? <BellSlashIcon height={12} fill={Colors.DARK_BLUE} /> : null}

                  {item.sent_by !== item.uid && item.status === 3 ? (
                    <ReadIcon fill={Colors.DARK_BLUE} />
                  ) : item.sent_by !== item.uid && (item.status === 2 || item.status === 1) ? (
                    <UnreadIcon fill={Colors.LIGHT_GRAY} />
                  ) : null}
                  <Text style={styles.chatTime}>{formatDate(item.updated)}</Text>
                </View>
              </View>

              <View style={[styles.rowContainer, { flex: 1, gap: 6 }]}>
                {typingUsers[item.uid] ? (
                  <TypingIndicator />
                ) : (
                  <Text numberOfLines={2} style={styles.chatMessage}>
                    {item.short}
                  </Text>
                )}

                {item.unread_count > 0 ? (
                  <View style={styles.unreadBadge}>
                    <Text style={styles.unreadText}>
                      {item.unread_count > 99 ? '99+' : item.unread_count}
                    </Text>
                  </View>
                ) : null}
              </View>
            </View>
          </View>
        </TouchableHighlight>
      </SwipeableRow>
    );
  };

  const renderBlockedItem = ({ item }: { item: Blocked }) => {
    return (
      <SwipeableBlockedRow
        data={{
          id: item.id,
          first_name: item.first_name,
          last_name: item.last_name,
          avatar: item.avatar
        }}
        token={token}
        onRowOpen={handleRowOpen}
        refetchBlocked={refetchBlocked}
      >
        <TouchableHighlight
          activeOpacity={0.8}
          onPress={() =>
            navigation.navigate(
              ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.id }] as never)
            )
          }
          underlayColor={Colors.FILL_LIGHT}
        >
          <View style={[styles.chatItem, { alignItems: 'center' }]}>
            {item.avatar ? (
              <Image
                source={{ uri: API_HOST + item.avatar }}
                style={[styles.avatar, { width: 30, height: 30, borderRadius: 15 }]}
              />
            ) : (
              <AvatarWithInitials
                text={item.first_name[0] + item.last_name[0]}
                flag={API_HOST + item?.flag}
                size={32}
                fontSize={12}
              />
            )}

            <View style={{ flex: 1, gap: 6 }}>
              <View style={[styles.rowContainer, { alignItems: 'center' }]}>
                <Text style={styles.chatName}>{item.first_name + ' ' + item.last_name}</Text>

                <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
                  <BanIcon height={12} fill={Colors.RED} />
                </View>
              </View>
            </View>
          </View>
        </TouchableHighlight>
      </SwipeableBlockedRow>
    );
  };

  return (
    <PageWrapper style={{ flex: 1, marginLeft: 0, marginRight: 0, gap: 12 }}>
      <View style={styles.header}>
        <View style={{ width: 30 }} />
        <Text style={styles.title}>Messages</Text>
        <TouchableOpacity
          onPress={() => SheetManager.show('search-modal')}
          style={{ width: 30, alignItems: 'flex-end' }}
        >
          <AddChatIcon />
        </TouchableOpacity>
      </View>

      {/* <View style={[{ paddingHorizontal: '4%' }]}>
        <Input
          inputMode={'search'}
          placeholder={'Search'}
          onChange={(text) => searchFilter(text)}
          value={search}
          icon={<SearchIcon fill={'#C8C8C8'} width={14} height={14} />}
          height={38}
        />
      </View> */}

      <HorizontalTabView
        index={index}
        setIndex={setIndex}
        routes={routes}
        tabBarStyle={{ paddingHorizontal: '4%' }}
        renderScene={({ route }: { route: { key: keyof typeof filteredChats } }) =>
          route.key === 'blocked' ? (
            <FlashList
              viewabilityConfig={{
                waitForInteraction: true,
                itemVisiblePercentThreshold: 50,
                minimumViewTime: 1000
              }}
              data={filteredChats[route.key]}
              renderItem={renderBlockedItem}
              keyExtractor={(item, index) => `${item.id}-${index}`}
              estimatedItemSize={50}
            />
          ) : (
            <FlashList
              viewabilityConfig={{
                waitForInteraction: true,
                itemVisiblePercentThreshold: 50,
                minimumViewTime: 1000
              }}
              data={filteredChats[route.key]}
              renderItem={renderChatItem}
              keyExtractor={(item, index) => `${item.uid}-${index}`}
              estimatedItemSize={78}
              extraData={typingUsers}
            />
          )
        }
      />

      <SearchModal />
      <MoreModal />
      <WarningModal
        type={'delete'}
        buttonTitle={isWarningModalVisible?.buttonTitle ?? 'Delete'}
        isVisible={!!isWarningModalVisible}
        onClose={() => setIsWarningModalVisible(null)}
        title={isWarningModalVisible?.title}
        message={isWarningModalVisible?.message}
        action={isWarningModalVisible?.action}
      />
    </PageWrapper>
  );
};

export default MessagesScreen;
