import {
  createContext,
  useContext,
  useState,
  useCallback,
  useEffect,
  useRef,
  type ReactNode,
} from 'react';
import { useIsMutating } from '@tanstack/react-query';
import { useSettings } from '@/hooks/useSettings';
import api from '@/lib/api';

interface LockContextValue {
  isLocked: boolean;
  lock: () => void;
  unlock: (password: string) => Promise<void>;
}

const LockContext = createContext<LockContextValue | null>(null);

const ACTIVITY_EVENTS = ['mousemove', 'keydown', 'click', 'scroll', 'touchstart'] as const;
const THROTTLE_MS = 5_000; // only reset timer every 5s of activity

export function LockProvider({ children }: { children: ReactNode }) {
  const [isLocked, setIsLocked] = useState(false);
  const { settings } = useSettings();
  const activeMutations = useIsMutating();

  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const lastActivityRef = useRef<number>(Date.now());
  const activeMutationsRef = useRef(activeMutations);
  activeMutationsRef.current = activeMutations;

  const lock = useCallback(() => {
    setIsLocked(true);
  }, []);

  const unlock = useCallback(async (password: string) => {
    const { data } = await api.post<{ verified: boolean }>('/auth/verify-password', { password });
    if (data.verified) {
      setIsLocked(false);
      lastActivityRef.current = Date.now();
    }
  }, []);

  // Auto-lock idle timer
  useEffect(() => {
    const enabled = settings?.auto_lock_enabled ?? false;
    const minutes = settings?.auto_lock_minutes ?? 5;

    if (!enabled || isLocked) {
      // Clear any existing timer when disabled or already locked
      if (timerRef.current) {
        clearTimeout(timerRef.current);
        timerRef.current = null;
      }
      return;
    }

    const timeoutMs = minutes * 60_000;

    const resetTimer = () => {
      // Don't lock while TanStack mutations are in flight
      if (activeMutationsRef.current > 0) return;

      if (timerRef.current) clearTimeout(timerRef.current);
      timerRef.current = setTimeout(() => {
        lock();
      }, timeoutMs);
    };

    const handleActivity = () => {
      const now = Date.now();
      if (now - lastActivityRef.current < THROTTLE_MS) return;
      lastActivityRef.current = now;
      resetTimer();
    };

    // Start the initial timer
    resetTimer();

    // Attach throttled listeners
    for (const event of ACTIVITY_EVENTS) {
      document.addEventListener(event, handleActivity, { passive: true });
    }

    return () => {
      for (const event of ACTIVITY_EVENTS) {
        document.removeEventListener(event, handleActivity);
      }
      if (timerRef.current) {
        clearTimeout(timerRef.current);
        timerRef.current = null;
      }
    };
  }, [settings?.auto_lock_enabled, settings?.auto_lock_minutes, isLocked, lock]);

  return (
    <LockContext.Provider value={{ isLocked, lock, unlock }}>
      {children}
    </LockContext.Provider>
  );
}

export function useLock(): LockContextValue {
  const ctx = useContext(LockContext);
  if (!ctx) throw new Error('useLock must be used within a LockProvider');
  return ctx;
}
