import { useCallback, useEffect, useRef, useState } from "react";

const IDLE_THRESHOLD_MS = 30_000; // 30 seconds of inactivity = idle
const TICK_INTERVAL_MS = 1_000; // Update display every second

const ACTIVITY_EVENTS = [
  "mousemove",
  "mousedown",
  "keydown",
  "scroll",
  "touchstart",
] as const;

export function useActiveTimer() {
  const [activeMs, setActiveMs] = useState(0);
  const [totalMs, setTotalMs] = useState(0);
  const [isIdle, setIsIdle] = useState(false);

  // Refs for values that change frequently but shouldn't trigger re-renders
  const activeMsRef = useRef(0);
  const totalMsRef = useRef(0);
  const lastActivityRef = useRef(Date.now());
  const lastTickRef = useRef(Date.now());
  const idleRef = useRef(false);
  const startedRef = useRef(Date.now());

  const reset = useCallback(() => {
    const now = Date.now();
    activeMsRef.current = 0;
    totalMsRef.current = 0;
    lastActivityRef.current = now;
    lastTickRef.current = now;
    startedRef.current = now;
    idleRef.current = false;
    setActiveMs(0);
    setTotalMs(0);
    setIsIdle(false);
  }, []);

  // Mark activity on user interaction
  useEffect(() => {
    function onActivity() {
      lastActivityRef.current = Date.now();
      if (idleRef.current) {
        idleRef.current = false;
        setIsIdle(false);
        // Reset the tick baseline so we don't count the idle gap as active
        lastTickRef.current = Date.now();
      }
    }

    for (const event of ACTIVITY_EVENTS) {
      window.addEventListener(event, onActivity, { passive: true });
    }
    // Also track when the tab regains focus
    window.addEventListener("focus", onActivity);

    return () => {
      for (const event of ACTIVITY_EVENTS) {
        window.removeEventListener(event, onActivity);
      }
      window.removeEventListener("focus", onActivity);
    };
  }, []);

  // Tick loop: accumulate active time and detect idle transitions
  useEffect(() => {
    const interval = setInterval(() => {
      const now = Date.now();
      const elapsed = now - lastTickRef.current;
      lastTickRef.current = now;

      // Always accumulate wall-clock time
      totalMsRef.current = now - startedRef.current;
      setTotalMs(totalMsRef.current);

      const timeSinceActivity = now - lastActivityRef.current;

      if (timeSinceActivity >= IDLE_THRESHOLD_MS) {
        // User is idle — don't accumulate active time
        if (!idleRef.current) {
          idleRef.current = true;
          setIsIdle(true);
        }
      } else {
        // User is active — accumulate
        activeMsRef.current += elapsed;
        setActiveMs(activeMsRef.current);
      }
    }, TICK_INTERVAL_MS);

    return () => clearInterval(interval);
  }, []);

  return {
    /** Milliseconds the user was actively engaged (idle time excluded) */
    activeMs,
    /** Total wall-clock milliseconds since last reset */
    totalMs,
    /** Whether the user is currently idle */
    isIdle,
    /** Reset both counters (call when loading a new paragraph) */
    reset,
  };
}
