import React, { createContext, useContext, useState, useEffect, useRef, useCallback } from 'react';
import {
  FormTiming,
  MouseMovement,
  validateAntibotData,
  checkRateLimit,
  checkRateLimitStatus,
  clearRateLimit,
  getFingerprintHash,
  type AntibotValidationResult,
} from '../../../shared/utils/antibot';

interface AntibotContextType {
  timing: FormTiming;
  fingerprintHash: string;
  startFormTracking: () => void;
  stopFormTracking: () => void;
  validateForm: (
    honeypotValue: string,
    recaptchaToken: string | null,
    options?: {
      minTimeOnPage?: number;
      minTimeToFill?: number;
      requireRecaptcha?: boolean;
      checkMouseMovements?: boolean;
    }
  ) => AntibotValidationResult;
  checkActionRateLimit: (action: string, maxAttempts?: number) => {
    allowed: boolean;
    remainingAttempts: number;
    resetTime: number;
  };
  checkActionRateLimitStatus: (action: string, maxAttempts?: number) => {
    allowed: boolean;
    remainingAttempts: number;
    resetTime: number;
  };
  clearActionRateLimit: (action: string) => void;
  recordMouseMovement: (x: number, y: number) => void;
  recordClick: () => void;
  recordKeyPress: () => void;
  reset: () => void;
}

const AntibotContext = createContext<AntibotContextType | undefined>(undefined);

export const useAntibot = () => {
  const context = useContext(AntibotContext);
  if (!context) {
    throw new Error('useAntibot must be used within an AntibotProvider');
  }
  return context;
};

interface AntibotProviderProps {
  children: React.ReactNode;
}

export const AntibotProvider: React.FC<AntibotProviderProps> = ({ children }) => {
  const [timing, setTiming] = useState<FormTiming>({
    pageLoadTime: Date.now(),
    formStartTime: null,
    formSubmitTime: null,
    timeOnPage: 0,
    timeToFill: null,
    mouseMovements: [],
    clickCount: 0,
    keyPressCount: 0,
  });
  
  const [fingerprintHash] = useState<string>(() => getFingerprintHash());
  const pageLoadTimeRef = useRef<number>(Date.now());
  const formStartTimeRef = useRef<number | null>(null);
  const mouseMovementsRef = useRef<MouseMovement[]>([]);
  const clickCountRef = useRef<number>(0);
  const keyPressCountRef = useRef<number>(0);
  const updateIntervalRef = useRef<number | null>(null);

  // Update time on page periodically
  useEffect(() => {
    updateIntervalRef.current = window.setInterval(() => {
      setTiming((prev) => ({
        ...prev,
        timeOnPage: Date.now() - pageLoadTimeRef.current,
      }));
    }, 1000);

    return () => {
      if (updateIntervalRef.current !== null) {
        clearInterval(updateIntervalRef.current);
      }
    };
  }, []);

  // Track mouse movements
  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      recordMouseMovement(e.clientX, e.clientY);
    };

    window.addEventListener('mousemove', handleMouseMove);
    return () => window.removeEventListener('mousemove', handleMouseMove);
  }, []);

  // Track clicks
  useEffect(() => {
    const handleClick = () => {
      recordClick();
    };

    window.addEventListener('click', handleClick);
    return () => window.removeEventListener('click', handleClick);
  }, []);

  // Track key presses
  useEffect(() => {
    const handleKeyPress = () => {
      recordKeyPress();
    };

    window.addEventListener('keypress', handleKeyPress);
    return () => window.removeEventListener('keypress', handleKeyPress);
  }, []);

  const recordMouseMovement = useCallback((x: number, y: number) => {
    const movement: MouseMovement = {
      x,
      y,
      timestamp: Date.now(),
    };
    
    mouseMovementsRef.current.push(movement);
    
    // Keep only last 50 movements to avoid memory issues
    if (mouseMovementsRef.current.length > 50) {
      mouseMovementsRef.current = mouseMovementsRef.current.slice(-50);
    }
    
    setTiming((prev) => ({
      ...prev,
      mouseMovements: [...mouseMovementsRef.current],
    }));
  }, []);

  const recordClick = useCallback(() => {
    clickCountRef.current += 1;
    setTiming((prev) => ({
      ...prev,
      clickCount: clickCountRef.current,
    }));
  }, []);

  const recordKeyPress = useCallback(() => {
    keyPressCountRef.current += 1;
    setTiming((prev) => ({
      ...prev,
      keyPressCount: keyPressCountRef.current,
    }));
  }, []);

  const startFormTracking = useCallback(() => {
    formStartTimeRef.current = Date.now();
    setTiming((prev) => ({
      ...prev,
      formStartTime: formStartTimeRef.current,
    }));
  }, []);

  const stopFormTracking = useCallback(() => {
    if (formStartTimeRef.current !== null) {
      const formSubmitTime = Date.now();
      const timeToFill = formSubmitTime - formStartTimeRef.current;
      
      setTiming((prev) => ({
        ...prev,
        formSubmitTime,
        timeToFill,
      }));
    }
  }, []);

  const validateForm = useCallback((
    honeypotValue: string,
    recaptchaToken: string | null,
    options?: {
      minTimeOnPage?: number;
      minTimeToFill?: number;
      requireRecaptcha?: boolean;
      checkMouseMovements?: boolean;
    }
  ): AntibotValidationResult => {
    return validateAntibotData(timing, honeypotValue, recaptchaToken, options);
  }, [timing]);

  const checkActionRateLimit = useCallback((action: string, maxAttempts: number = 5) => {
    return checkRateLimit(action, maxAttempts);
  }, []);

  const checkActionRateLimitStatus = useCallback((action: string, maxAttempts: number = 5) => {
    return checkRateLimitStatus(action, maxAttempts);
  }, []);

  const clearActionRateLimit = useCallback((action: string) => {
    clearRateLimit(action);
  }, []);

  const reset = useCallback(() => {
    pageLoadTimeRef.current = Date.now();
    formStartTimeRef.current = null;
    mouseMovementsRef.current = [];
    clickCountRef.current = 0;
    keyPressCountRef.current = 0;
    
    setTiming({
      pageLoadTime: pageLoadTimeRef.current,
      formStartTime: null,
      formSubmitTime: null,
      timeOnPage: 0,
      timeToFill: null,
      mouseMovements: [],
      clickCount: 0,
      keyPressCount: 0,
    });
  }, []);

  const value: AntibotContextType = {
    timing,
    fingerprintHash,
    startFormTracking,
    stopFormTracking,
    validateForm,
    checkActionRateLimit,
    checkActionRateLimitStatus,
    clearActionRateLimit,
    recordMouseMovement,
    recordClick,
    recordKeyPress,
    reset,
  };

  return (
    <AntibotContext.Provider value={value}>
      {children}
    </AntibotContext.Provider>
  );
};

