import React, { useState, useEffect, useContext } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Form, InputGroup } from "react-bootstrap";
import { UserContext } from "../contexts/userContext";
import { FiPlus } from "react-icons/fi";
import { FaSignInAlt } from "react-icons/fa";
import { GiSandsOfTime } from "react-icons/gi";
import { CgEnter } from "react-icons/cg";
import Dialog from "./UI/Dialog";
import {
  chatActions,
  fetchChatRoomsAsync,
  fetchSupportRoomsAsync,
} from "../store/chat-slice";
import { createChatRoomAsync } from "../store/chat-slice";
import { createJoinRequestAsync, requestActions } from "../store/request-slice";
import { fetchRequestsAsync } from "../store/request-slice";
import { HubConnectionBuilder } from "@microsoft/signalr";
import { loadNotifications } from "../store/chat-slice";
import { readNotificationsAsync } from "../store/chat-slice";

// Ovde ce biti dostupne grupe i razgovori
const ChatList = () => {
  const [createChat, setCreateChat] = useState(false);
  const [chatName, setChatName] = useState("");
  const [requestedRooms, setRequestedRooms] = useState([]);
  const {
    rooms,
    status: chatStatus,
    error,
    notifications,
    activeRoom,
  } = useSelector((state) => state.chat);
  const {
    chosenRoom,
    status: requestsStatus,
    requests,
  } = useSelector((state) => state.requests);
  const [showModal, setShowModal] = useState(false);
  const [loadedNotification, setLoadedNotification] = useState(false);
  const { user } = useContext(UserContext);
  const [myConnection, setMyConnection] = useState(null);
  const [chatMessage, setChatMessage] = useState(null);
  const [notificationRoom, setNotificationRoom] = useState(null);
  const dispatch = useDispatch();

  useEffect(() => {
    if (user && !loadedNotification) {
      dispatch(loadNotifications(user.id));
      setLoadedNotification((oldState) => !oldState);
    }
  }, [user, dispatch, loadedNotification]);

  // Maybe don't work
  useEffect(() => {
    user !== null && user.roles.includes("Support")
      ? dispatch(fetchSupportRoomsAsync(user.id))
      : user !== null && dispatch(fetchChatRoomsAsync(user.id));
    dispatch(fetchRequestsAsync());
  }, [dispatch]);

  useEffect(() => {
    if (requests && rooms) {
      const userRequests = requests
        .filter((request) => request.senderId === user.id)
        .map((request) => request.roomId);

      setRequestedRooms(userRequests);
    }
  }, [requests, rooms, user]);

  const addChatSubmitHandler = (e) => {
    e.preventDefault();
    alert(`Chat ${chatName} has been created`);
    dispatch(createChatRoomAsync({ name: chatName, createdBy: user.id }));
    setCreateChat(false);
    setChatName("");
  };

  const showRoomMessagesHandler = (n) => {
    dispatch(chatActions.readNotifications(n.id));
    dispatch(chatActions.setRoom(n));
  };

  const joinRoom = async (n) => {
    try {
      const connection = new HubConnectionBuilder()
        .withUrl("http://localhost:5116/chatHub", {
          accessTokenFactory: () => user.token,
        })
        .withAutomaticReconnect()
        .build();

      connection.on("ReceiveMessage", (data) => {
        // When user enter room first time after login, generated Context.ConnectionId will be saved in redux
        if (data.connId) {
          dispatch(
            chatActions.saveContextId({ connId: data.connId, userId: user.id })
          );
          setChatMessage(data);
        }
      });

      connection.on("ViewTyping", (data) => {
        dispatch(chatActions.addTyping(data));
      });

      connection.on("ReceiveNotifications", (userId, roomId) => {
        if (user.id !== userId) {
          dispatch(chatActions.addNotification(roomId));
          setNotificationRoom(roomId);
        }
      });
      // When user changed room, array with messages from previous room will be deleted from redux
      dispatch(chatActions.newMessage({ changedRoom: true }));

      connection.onclose((e) => {
        // On close connection
      });

      await connection.start();
      await connection.invoke("JoinRoom", {
        userId: user.id,
        username: user.username,
        roomId: n.id,
      });
      dispatch(chatActions.setRoom(n));
      dispatch(chatActions.setConnection(connection));
      setMyConnection(connection);
    } catch (e) {
      console.log(e);
    }
  };

  // Maybe don't work
  useEffect(() => {
    if (myConnection) {
      myConnection.on("ReceiveMessage", (data) => {
        // When user enter room first time after login, generated Context.ConnectionId will be saved in redux
        if (data.connId) {
          dispatch(
            chatActions.saveContextId({ connId: data.connId, userId: user.id })
          );
        }
        setChatMessage(data);
      });
    }
  }, [myConnection, dispatch]);

  // Maybe don't work
  useEffect(() => {
    if (chatMessage && activeRoom.id === chatMessage.roomId) {
      dispatch(
        chatActions.newMessage({
          content: chatMessage.message,
          createdAtUtc: new Date(),
          deletedAtUtc: null,
          id: null,
          senderId: chatMessage.userId,
          updatedAtUtc: null,
          username: user.username,
          isAccessMessage: chatMessage.isAccessMessage,
        })
      );
    }
  }, [chatMessage, dispatch]);

  // Maybe don't work
  useEffect(() => {
    if (notificationRoom && activeRoom) {
      if (notificationRoom === activeRoom.id) {
        dispatch(chatActions.readNotifications(activeRoom.id));
        dispatch(
          readNotificationsAsync({ userId: user.id, roomId: activeRoom.id })
        );
      }
    }
    setNotificationRoom(null);
  }, [notificationRoom, dispatch]);

  const openModal = (n) => {
    setShowModal(true);
    dispatch(requestActions.chooseRoom(n));
  };

  const dialogHandler = () => {
    dispatch(
      createJoinRequestAsync({
        senderId: user.id,
        senderUsername: user.username,
        roomId: chosenRoom.id,
        roomName: chosenRoom.name,
      })
    );
  };

  const notificationCounter = (room) => {
    for (let i = 0; i < notifications.length; i++) {
      if (notifications[i].roomId === room.id) {
        return notifications[i].notificationCount;
      }
    }

    return null;
  };

  useEffect(() => {
    if (requestsStatus === "idle") {
      setShowModal(false);
    }
  }, [requestsStatus]);

  const getView = () => {
    let acceptedRequests = [];
    let pendingRequests = [];
    let availableRequests = [];
    for (let i = 0; i < rooms.length; i++) {
      if (rooms[i].customers.some((x) => x.customerId === user.id)) {
        acceptedRequests.push(rooms[i]);
      } else {
        if (requestedRooms.includes(rooms[i].id)) {
          pendingRequests.push(rooms[i]);
        } else {
          availableRequests.push(rooms[i]);
        }
      }
    }
    return user !== null && user.roles.includes("Support") ? (
      <div>
        {rooms.map((room, index) => (
          <div
            className="border-bottom roomsBtn d-flex bg-light"
            key={index}
            onClick={() => joinRoom(room)}
          >
            <button
              className="text-start w-100 py-2 px-3 btn btn-light h-100"
              onClick={showRoomMessagesHandler.bind(this, room)}
            >
              {room.name}
            </button>
          </div>
        ))}
      </div>
    ) : (
      <div>
        {acceptedRequests.length > 0 && (
          <div>
            <h5 className="text-start w-100 ps-3 text-light py-2 pt-3">
              Accepted Rooms
            </h5>
            {acceptedRequests.map((n, index) => (
              <div
                className="border-bottom roomsBtn d-flex bg-light"
                key={index}
                onClick={() => joinRoom(n)}
              >
                {notificationCounter(n) && (
                  <div className="notification rounded-circle my-auto ms-3">
                    {notificationCounter(n)}
                  </div>
                )}
                <button
                  className="text-start w-100 py-2 px-3 btn btn-light h-100"
                  onClick={showRoomMessagesHandler.bind(this, n)}
                >
                  {n.name}
                </button>
                <button className="btn btn-light">
                  <CgEnter />
                </button>
              </div>
            ))}
          </div>
        )}
        {pendingRequests.length > 0 && (
          <div>
            <h5 className="text-start w-100 ps-3 text-light py-2 pt-3">
              Pending Requests
            </h5>
            {pendingRequests.map((n, index) => (
              <div
                className="border-bottom roomsBtn bg-light d-flex"
                key={index}
              >
                <button className="text-start w-100 py-2 px-3 btn btn-light h-100">
                  {n.name}
                </button>
                <button className="btn btn-light">
                  <GiSandsOfTime />
                </button>
              </div>
            ))}
          </div>
        )}
        {availableRequests.length > 0 && (
          <div>
            <h5 className="text-start w-100 ps-3 text-light py-2 pt-3">
              Available Rooms
            </h5>
            {availableRequests.map((n, index) => (
              <div
                onClick={(e) => openModal(n)}
                className="border-bottom roomsBtn bg-light d-flex"
                key={index}
              >
                <button className="text-start w-100 py-2 px-3 btn btn-light h-100">
                  {n.name}
                </button>
                <button className="btn btn-light">
                  <FaSignInAlt />
                </button>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  };

  return (
    <>
      <Dialog
        changeModalVisibility={() => setShowModal(false)}
        open={showModal}
        acceptHandler={dialogHandler}
      />
      <div className="p-0 h-100-auto-overflow overflow-x">
        <div className="pe-4 bg-transparent w-100 mb-3 p-0 border-bottom border-light d-flex justify-content-between align-items-center">
          <h4 className="p-0 m-0 py-3 w-100 text-start ps-3 text-light bg-transparent">
            Chat Rooms
          </h4>
          {user?.roles[0] === "Support" && (
            <button
              className="btn p-0 m-0 btn-light pt-0 mt-0 px-3 pb-2 pt-1"
              onClick={(e) => setCreateChat(true)}
            >
              <FiPlus className="m-0 p-0" />
            </button>
          )}
        </div>
        {createChat && (
          <div className="w-100 d-flex align-items-center justify-content-center pb-3 border-bottom">
            <Form onSubmit={addChatSubmitHandler} className="w-100">
              <InputGroup className="w-100 px-2">
                <input
                  type="text"
                  className="border-1 px-2 w-75"
                  value={chatName}
                  onChange={(e) => setChatName(e.target.value)}
                />
                <input
                  type="submit"
                  className="w-25 btn btn-dark"
                  value={"Add"}
                />
              </InputGroup>
            </Form>
          </div>
        )}

        {/* ovo ce biti zamenjeno konkretnim podacima */}
        {(!error && requestedRooms && chatStatus === "pendingFetchRooms") ||
        chatStatus === "pendingAddRoom" ? (
          <div className="spinner-border mt-3" role="status">
            <span className="visually-hidden">Loading...</span>
          </div>
        ) : (
          getView()
        )}
        {error && <p>REJECTED</p>}
        <div className="pt-5"></div>
      </div>
    </>
  );
};

export default ChatList;
