import React, { useState, useEffect, useCallback } from 'react';
import VotingBoard from '../VotingBoard';
import BoardCard from '../BoardCard';
import Results from '../Results';
import styles from './VotingTable.module.css';
import titleCardSrc from '../../assets/images/titlecard.png';
import { ReactComponent as ExitIcon } from '../../assets/images/exit.svg';
import { useNavigate, useParams } from 'react-router-dom';
import ProfileMenuButton from '../ProfileMenuButton';
import api from '../../services/api';

const VotingTable = ({ userId }) => {
  const [users, setUsers] = useState([]);
  const [votes, setVotes] = useState({});
  const [, setVotedUsers] = useState(0);
  const [isFinal, setIsFinal] = useState(false);
  const { sessionId } = useParams();
  const [currentUID, setCurrentUID] = useState('');
  const navigate = useNavigate();

  const maxUsers = 32;
  const username =
    users.find((user) => user.uid === currentUID)?.username || '';

  const goToLobby = useCallback(() => {
    navigate(`/lobby/${sessionId}`);
  }, [sessionId, navigate]);

  async function handleLogout() {
    await handleDropUser(currentUID);
  }

  async function handleInvite() {
    try {
      navigator.clipboard.writeText(window.location.href);
    } catch (err) {
      console.error('Failed to copy invite link: ', err);
    }
  }

  const handleDropUser = async (userId) => {
    try {
      // Remove user vote and user from session via API calls
      await api.delete(`/api/session/${sessionId}/votes/${userId}`);
      await api.delete(`/api/session/${sessionId}/users/${userId}`);

      // Fetch updated session data after user removal
      const sessionResponse = await api.get(`/api/session/${sessionId}`);
      const sessionData = sessionResponse.data;

      if (!sessionData) return;

      // Update state with the new session data
      const userList = Object.entries(sessionData.users || {}).map(
        ([uid, userInfo]) => ({
          uid,
          username: userInfo.username,
        })
      );

      setUsers(userList);
      setVotes(sessionData.votes || {});

      // Redirect the dropped user to the lobby
      await api.post(`/api/users/${userId}`, {
        currentSessionId: `lobby/${sessionId}`,
      });
    } catch (error) {
      console.error('Error removing user:', error);
    }
  };

  const handleFinalizeVoting = async () => {
    try {
      // Finalize voting by setting the isFinal flag in the session via API call
      await api.post(`/api/session/${sessionId}/finalize`, {
        isFinal: true,
      });
      setIsFinal(true);
    } catch (error) {
      console.error('Error finalizing voting:', error);
    }
  };

  const handleResetVoting = async () => {
    try {
      // Reset the session's votes and isFinal flag via API call
      await api.post(`/api/session/${sessionId}/reset`, {
        votes: {},
        isFinal: false,
      });
      setVotes({});
      setVotedUsers(0);
      setIsFinal(false);
    } catch (error) {
      console.error('Error resetting voting:', error);
    }
  };

  useEffect(() => {
    const fetchSessionData = async () => {
      try {
        // Fetch session data from the API
        const sessionResponse = await api.get(`/api/session/${sessionId}`);
        const sessionData = sessionResponse.data;

        if (!sessionData) {
          // Initialize the session if it doesn't exist
          await api.post(`/api/session/${sessionId}`, {
            votes: {},
            maxUsers: maxUsers,
            isFinal: false,
            users: {},
          });
        } else {
          // Load the existing session data
          const userList = Object.entries(sessionData.users || {}).map(
            ([uid, userInfo]) => ({
              uid,
              username: userInfo.username,
            })
          );
          setUsers(userList);
          setVotes(sessionData.votes || {});
          setIsFinal(sessionData.isFinal || false);
        }
      } catch (error) {
        console.error('Error fetching session data:', error);
        goToLobby(); // Redirect to lobby if the session doesn't exist
      }
    };

    fetchSessionData();

    // Polling or WebSocket could be used to listen for real-time updates
    const intervalId = setInterval(fetchSessionData, 5000); // Poll every 5 seconds
    return () => clearInterval(intervalId); // Clean up the interval
  }, [sessionId, maxUsers, navigate, setCurrentUID, goToLobby]);

  const allVoted = Object.values(votes).every((v) => v >= 0);

  return (
    <div className={styles.votingTable}>
      <ProfileMenuButton
        username={username}
        onLogout={handleLogout}
        onInvite={handleInvite}
      />
      <img className={styles.titleCard} src={titleCardSrc} alt="title-card" />
      <div className={styles.tableCards}>
        {users.map(({ uid, username }) => (
          <div key={uid} className={styles.userCardWrapper}>
            <BoardCard
              username={username}
              vote={votes[uid]}
              isRevealed={isFinal && votes[uid] !== -1}
              isDimmed={votes[uid] === -1}
              isHighlighted={currentUID === uid}
            />
            {
              <ExitIcon
                className={styles.dropButton}
                onClick={
                  uid === currentUID ? handleLogout : () => handleDropUser(uid)
                }
                title="Drop User"
              />
            }
          </div>
        ))}
      </div>
      <div className={styles.form}>
        {allVoted && !isFinal && (
          <div
            className={`${styles.reveal} ${styles.button}`}
            onClick={handleFinalizeVoting}
          >
            Reveal Votes
          </div>
        )}
        {isFinal && (
          <div
            className={`${styles.restart} ${styles.button}`}
            onClick={handleResetVoting}
          >
            Restart Voting
          </div>
        )}
      </div>
      {!isFinal ? (
        <VotingBoard
          sessionId={sessionId}
          userId={userId}
          maxUsers={maxUsers}
        />
      ) : (
        <Results votes={votes} />
      )}
    </div>
  );
};

export default VotingTable;
