import { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Navigate, Outlet, useNavigate } from "react-router-dom";
import LoadingSpinner from "../components/Spinners/LoadingSpinner";
import usersService from "../services/UsersService";
import { commonHeadBanner } from "../store/CommonHeadBanner";
import { recentActivitiesData } from "../store/RecentActivitiesData";
import { updateUserDetails } from "../store/UserDetails";
import { updateJobs } from "../store/jobLists";
import { updateNotifications } from "../store/notifications";
import { updateUserJobList } from "../store/userJobList";
import { updateWalletDetails } from "../store/walletDetails";
import { formattedDate } from "../lib";

const AuthRoute = ({ redirectPath = "/login", children }) => {
  const apiCall = useMemo(() => new usersService(), []);
  const dispatch = useDispatch();
  const [lastActivityTime, setLastActivityTime] = useState(Date.now());
  const [isLogin, setIsLogin] = useState({ loading: true, status: false });
  const [loadProfileDetails, setLoadProfileDetails] = useState([]);
  const navigate = useNavigate();

  const { jobListTable, walletTable } = useSelector((state) => state.tableReload);

  const {
    userDetails: { username, uid, session },
  } = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active

  let loggedIn = username && session && uid ? true : false; // variable to determine if user is logged in

  useEffect(() => {
    //Removing Data stored at localStorage after session expires
    const expireSession = () => {
      localStorage.removeItem("uid");
      localStorage.removeItem("member_id");
      localStorage.removeItem("session_token");
      navigate("/login", { replace: true }); // redirects user to login page after session expires
    };

    const checkInactivity = setInterval(() => {
      let { account_type } = loadProfileDetails;
      if (account_type === "FAMILY") {
        if (
          Date.now() - lastActivityTime >
          process.env.REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY
        ) {
          expireSession();
        }
      } else {
        if (
          Date.now() - lastActivityTime >
          process.env.REACT_APP_SESSION_EXPIRE_MINUTES
        ) {
          expireSession();
        }
      }
    }, process.env.REACT_APP_SESSION_EXPIRE_CHECKER); // Checks for inactivity every minute

    // cleaning up listeners
    return () => {
      clearInterval(checkInactivity);
    };
  }, [lastActivityTime, navigate]);

  // Reset last activity time on user input
  const resetTime = useCallback(() => {
    setLastActivityTime(Date.now());
  }, []);

  useEffect(() => {
    window.addEventListener("mousemove", resetTime);
    window.addEventListener("keydown", resetTime);

    return () => {
      window.removeEventListener("mousemove", resetTime);
      window.removeEventListener("keydown", resetTime);
    };
  }, [resetTime]);

  useEffect(() => {
    if (!loggedIn) {
      const loadProfile = () => {
        // function to load user profile
        setIsLogin({ loading: true, status: false });
        apiCall
          .loadProfile()
          .then((res) => {
            if (res.data.internal_return < 0) {
              setIsLogin({ loading: false, status: false });
              return;
            }
            setLoadProfileDetails(res.data);
            dispatch(updateUserDetails({ ...res.data }));
            setIsLogin({ loading: false, status: true });
          })
          .catch((error) => {
            setIsLogin({ loading: false, status: false });
          });
      };
      loadProfile();
    }
  }, []);

  useEffect(() => {
    const getNotifications = () => {
      // function to load user notification
      dispatch(updateNotifications({ loading: true }));
      apiCall
        .getMyNotifications()
        .then((res) => {
          if (res.data.internal_return < 0) {
            dispatch(updateNotifications({ loading: false, data: null }));
            return;
          }
          setLoadProfileDetails(res.data);

          const _raw = res.data?.result_list;

          //Sort the notifications in ascending order based on the API time
          const _sorted = _raw?.sort((a, b) => {
            const timeA = new Date(a?.date)?.getTime();
            const timeB = new Date(b?.date)?.getTime();
            return timeA - timeB;
          });

          // header component
          const _header = _sorted?.slice(0, 5);
          // Notification Layout
          const _today = _sorted?.slice(0, 7);

          const _days = () => {
            const sevenDaysAgo = new Date();
            sevenDaysAgo.setDate(new Date() - 7);
            return _sorted?.filter((notification) => {
              const notificationDate = new Date(
                formattedDate(notification?.date)
              );
              return notificationDate >= sevenDaysAgo;
            });
          };

          // Dispatch all notifications, sorted, and recent based on their filter type
          dispatch(
            updateNotifications({
              loading: false,
              // data: {
              //   raw: _raw,
              //   today: _today,
              //   // days: _days(),
              //   sort: _sorted,
              //   header: _header,
              // },
              data: _sorted,
            })
          );
        })
        .catch((error) => {
          dispatch(updateNotifications({ loading: false, data: null }));
        });
    };
    getNotifications();
  }, []);

  useEffect(() => {
    const getMyJobList = async () => {
      dispatch(updateUserJobList({ loading: true, data: [] }));
      try {
        const res = await apiCall.getMyJobList();
        // setMyJobList({loading: false, data:res.data})
        // setMyJobList(res.data);
        dispatch(updateUserJobList({ loading: false, data: res.data }));
      } catch (error) {
        dispatch(updateUserJobList({ loading: false, data: [] }));
        // setMyJobList({loading: false, data:[]})
        console.log("Error getting mode");
      }
    };
    getMyJobList();
  }, [jobListTable]);

  useEffect(() => {
    const getMyWalletList = async () => {
      dispatch(updateWalletDetails({ loading: true, data:[] }));
      try {
        const res = await apiCall.getUserWallets();
        console.log("wallet - >", res.data);
        dispatch(updateWalletDetails({ loading: false, data:res.data?.result_list }));
      } catch (error) {
        dispatch(updateWalletDetails({ loading: false, data:[] }));
        console.log("Error getting mode");
      }
    };
    getMyWalletList();
  }, [walletTable]);

  useEffect(() => {
    // Getting market data
    const getMarketActiveJobList = async () => {
      try {
        const res = await apiCall.getActiveJobList();
        dispatch(updateJobs(res.data));
      } catch (error) {
        console.log("Error getting mode");
      }
    };
    getMarketActiveJobList();
  }, [apiCall, dispatch]);

  //FUNCTION TO GET COMMON HEAD DATA
  useEffect(() => {
    apiCall
      .getHeroJBanners()
      .then((res) => {
        if (res.data.internal_return < 0) {
          return;
        }
        dispatch(commonHeadBanner(res.data));
      })
      .catch((error) => {
        console.log("ERROR ", error);
      });
  }, []);
  //
  //FUNCTION TO GET COMMON HEAD DATA
  useEffect(() => {
    apiCall
      .getRecentActivitiedData()
      .then((res) => {
        //   debugger;
        if (res?.data?.internal_return < 0) {
          return;
        }
        dispatch(recentActivitiesData(res.data));
      })
      .catch((error) => {
        console.log("ERROR ", error);
      });
  }, []);

  // useEffect(() => {
  //   apiCall
  //     .getHeroJBanners()
  //     .then((res) => {
  //       if (res.data.internal_return < 0) {
  //         return;
  //       }
  //       dispatch(commonHeadBanner(res.data));
  //     })
  //     .catch((error) => {
  //       console.log("ERROR ", error);
  //     });
  // }, []);
  //

  return isLogin.loading && !loggedIn ? (
    <LoadingSpinner size="32" color="sky-blue" height="h-screen" />
  ) : !isLogin.status && !loggedIn ? (
    <Navigate to={redirectPath} replace />
  ) : (
    children || <Outlet />
  );
};

export default AuthRoute;
