import React, { useState, useEffect, useCallback } from 'react';
import { ref, onValue, get, set, remove } from 'firebase/database';
import { realtimeDb } from '../../services/firebase';
import VotingBoard from '../VotingBoard/VotingBoard';
import BoardCard from '../BoardCard/BoardCard';
import Results from '../Results/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 { auth } from '../../services/firebase';
import ProfileMenuButton from '../ProfileMenuButton';

const VotingTable = ({ userId }) => {
  const [users, setUsers] = useState([]);
  const [votes, setVotes] = useState({});
  const [, setVotedUsers] = useState(0);
  const [allVoted, setAllVoted] = useState(false);
  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]);

  function handleLogout() {
    handleDropUser(currentUID);
  }

  const handleDropUser = async (userId) => {
    const userVoteRef = ref(
      realtimeDb,
      `sessions/${sessionId}/votes/${userId}`
    );
    const userRef = ref(realtimeDb, `sessions/${sessionId}/users/${userId}`);

    await remove(userVoteRef);
    await remove(userRef);

    const sessionRef = ref(realtimeDb, `sessions/${sessionId}`);
    const snapshot = await get(sessionRef);

    if (snapshot.exists()) {
      const sessionData = snapshot.val() || {};

      if (typeof sessionData.users === 'undefined') {
        sessionData.users = {};
      }
      if (typeof sessionData.votes === 'undefined') {
        sessionData.votes = {};
      }

      const userList = Object.entries(sessionData.users).reduce(
        (res, [uid, userInfo]) => {
          res[uid] = {
            uid,
            username: userInfo.username,
          };
          return res;
        },
        {}
      );

      if (sessionData.votes && sessionData.votes[userId]) {
        delete sessionData.votes[userId];
      }

      // Update the session data
      await set(sessionRef, {
        ...sessionData,
        votedUsers: Object.entries(sessionData.votes).reduce(
          (res, [uid, vote]) => (userId !== uid && vote >= 0 ? res + 1 : res),
          0
        ),
        users: userList,
      });

      // Redirect the dropped user to the lobby
      const userLobbyRef = ref(realtimeDb, `users/${userId}`);
      await set(userLobbyRef, {
        currentSessionId: `lobby/${sessionId}`,
      });
    }
  };

  const handleFinalizeVoting = async () => {
    const sessionRef = ref(realtimeDb, `sessions/${sessionId}`);
    const snapshot = await get(sessionRef);
    if (snapshot.exists()) {
      const sessionData = snapshot.val() || {};

      await set(sessionRef, {
        ...sessionData,
        isFinal: true,
      });
      setIsFinal(true);
    }
  };

  const handleResetVoting = async () => {
    const sessionRef = ref(realtimeDb, `sessions/${sessionId}`);

    // Get the current session data
    const snapshot = await get(sessionRef);
    if (snapshot.exists()) {
      const sessionData = snapshot.val() || {};

      // Reset the votes while retaining users
      const resetVotes = Object.keys(sessionData.votes).reduce((acc, user) => {
        acc[user] = -1;
        return acc;
      }, {});

      // Update the session in the database with reset votes and reset isFinal
      await set(sessionRef, {
        ...sessionData,
        votes: resetVotes,
        votedUsers: 0,
        isFinal: false,
      });

      // Update the component state
      setVotes(resetVotes);
      setVotedUsers(0);
      setIsFinal(false);
      setAllVoted(false);
    }
  };

  useEffect(() => {
    const user = auth.currentUser;

    if (!user) {
      goToLobby();
      return;
    }

    setCurrentUID(user.uid);

    const sessionRef = ref(realtimeDb, `sessions/${sessionId}`);

    get(sessionRef).then((snapshot) => {
      if (!snapshot.exists()) {
        // Initialize the session if it doesn't exist
        set(sessionRef, {
          votes: {},
          maxUsers: maxUsers,
          votedUsers: 0,
          isFinal: false,
          users: {},
        });
      } else {
        // If the session exists, ensure all necessary fields are set
        const sessionData = snapshot.val() || {};

        // Check and add missing fields
        if (!sessionData.maxUsers) {
          sessionData.maxUsers = maxUsers;
        }
        if (!sessionData.votedUsers) {
          sessionData.votedUsers = 0;
        }
        if (!sessionData.isFinal) {
          sessionData.isFinal = false;
        }
        if (typeof sessionData.votes === 'undefined') {
          sessionData.votes = {};
        }
        if (typeof sessionData.users === 'undefined') {
          sessionData.users = {};
        }

        // Update the session with missing fields if needed
        set(sessionRef, sessionData);

        const userList = Object.entries(sessionData.users).map(
          ([uid, userInfo]) => ({
            uid,
            username: userInfo.username, // Ensure username is passed
          })
        );

        // Load the data into the state
        setUsers(userList);
        setVotes(sessionData.votes);
        setVotedUsers(sessionData.votedUsers);
        setIsFinal(sessionData.isFinal);
      }
    });

    // Listen for changes to the session data
    const unsubscribe = onValue(sessionRef, (snapshot) => {
      const sessionData = snapshot.val();
      if (!sessionData) return;

      if (typeof sessionData.users === 'undefined') {
        sessionData.users = {};
      }
      if (typeof sessionData.votes === 'undefined') {
        sessionData.votes = {};
      }

      const userList = Object.entries(sessionData.users).map(
        ([uid, userInfo]) => ({
          uid,
          username: userInfo.username,
        })
      );

      setUsers(userList);
      setVotes(sessionData.votes || {});
      setVotedUsers(sessionData.votedUsers || 0);
      setIsFinal(sessionData.isFinal || false);

      // Check if all users have voted
      setAllVoted(
        sessionData.votedUsers ===
          Object.keys(sessionData.votes || {}).length &&
          Object.keys(sessionData.votes || {}).length > 0
      );
    });

    return () => {
      unsubscribe();
    };
  }, [sessionId, maxUsers, navigate, setCurrentUID, goToLobby]);

  return (
    <div className={styles.votingTable}>
      {/* <ExitIcon
        className={styles.logout}
        onClick={() => handleDropUser(currentUID)}
        title="Logout"
      /> */}
      <ProfileMenuButton username={username} onLogout={handleLogout} />
      <img className={styles.titleCard} src={titleCardSrc} alt="round-table" />
      <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={() => 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;
