import { UserSolution } from "@/interfaces/exam";
import useExamStore from "@/stores/exam";
import axios from "axios";
import { useEffect, useRef } from "react";
import { useRouter } from "next/router";

const useEvaluationPolling = (sessionIds: string[], mode: "exam" | "records", userId: string) => {
  const { setUserSolutions, userSolutions } = useExamStore();
  const pollingTimeoutsRef = useRef<Map<string, NodeJS.Timeout>>(new Map());
  const router = useRouter();

  const poll = async (sessionId: string) => {
    try {
      const { data: statusData } = await axios.get('/api/evaluate/status', {
        params: { op: 'pending', userId, sessionId }
      });

      if (!statusData.hasPendingEvaluation) {

        let solutionsOrStats = userSolutions;

        if (mode === "records") {
          const res = await axios.get(`/api/stats/session/${sessionId}`)
          solutionsOrStats = res.data;
        }
        const { data: completedSolutions } = await axios.post('/api/evaluate/fetchSolutions?op=session', {
          sessionId,
          userId,
          stats: solutionsOrStats,
        });

        await axios.post('/api/stats/disabled', {
          sessionId,
          userId,
          solutions: completedSolutions,
        });

        const timeout = pollingTimeoutsRef.current.get(sessionId);
        if (timeout) clearTimeout(timeout);
        pollingTimeoutsRef.current.delete(sessionId);

        if (mode === "exam") {
          const updatedSolutions = userSolutions.map(solution => {
            const completed = completedSolutions.find(
              (c: UserSolution) => c.exercise === solution.exercise
            );
            return completed || solution;
          });

          setUserSolutions(updatedSolutions);
        } else {
          router.reload();
        }
      } else {
        if (pollingTimeoutsRef.current.has(sessionId)) {
          clearTimeout(pollingTimeoutsRef.current.get(sessionId));
        }
        pollingTimeoutsRef.current.set(
          sessionId,
          setTimeout(() => poll(sessionId), 5000)
        );
      }
    } catch (error) {
      if (pollingTimeoutsRef.current.has(sessionId)) {
        clearTimeout(pollingTimeoutsRef.current.get(sessionId));
      }
      pollingTimeoutsRef.current.set(
        sessionId,
        setTimeout(() => poll(sessionId), 5000)
      );
    }
  };

  useEffect(() => {
    if (mode === "exam") {
      const hasDisabledSolutions = userSolutions.some(s => s.isDisabled);

      if (hasDisabledSolutions && sessionIds.length > 0) {
        poll(sessionIds[0]);
      } else {
        pollingTimeoutsRef.current.forEach((timeout) => {
          clearTimeout(timeout);
        });
        pollingTimeoutsRef.current.clear();
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mode, sessionIds, userSolutions]);

  useEffect(() => {
    if (mode === "records" && sessionIds.length > 0) {
      sessionIds.forEach(sessionId => {
        poll(sessionId);
      });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mode, sessionIds]);

  useEffect(() => {
    const timeouts = pollingTimeoutsRef.current;
    return () => {
      timeouts.forEach((timeout) => {
        clearTimeout(timeout);
      });
      timeouts.clear();
    };
  }, []);

  return {
    isPolling: pollingTimeoutsRef.current.size > 0
  };
};

export default useEvaluationPolling;
