import { useEffect, useRef, useState, useCallback } from 'react';
import type { DetectionConfig, DetectionResult, DetectionMetrics } from './types';
import { DetectionEngine } from './detection-engine';

interface UseDetectionOptions {
  modelVariant?: 'quantized' | 'standard' | 'full';
  enableContinuous?: boolean;
  enableTrigger?: boolean;
  onDetection?: (detection: DetectionResult | null) => void;
  onError?: (error: Error) => void;
}

interface UseDetectionReturn {
  // State
  isLoading: boolean;
  isDetecting: boolean;
  currentDetection: DetectionResult | null;
  metrics: DetectionMetrics | null;
  error: string | null;
  
  // Actions
  initialize: (videoElement: HTMLVideoElement) => Promise<void>;
  startContinuous: () => void;
  stopContinuous: () => void;
  triggerDetection: () => Promise<DetectionResult | null>;
  updateConfig: (config: Partial<DetectionConfig>) => Promise<void>;
  
  // Config
  config: DetectionConfig | null;
}

/**
 * React hook for shoe detection functionality
 */
export function useDetection(options: UseDetectionOptions = {}): UseDetectionReturn {
  const {
    modelVariant = 'standard',
    enableContinuous = true,
    enableTrigger = true,
    onDetection,
    onError
  } = options;

  // State
  const [isLoading, setIsLoading] = useState(false);
  const [isDetecting, setIsDetecting] = useState(false);
  const [currentDetection, setCurrentDetection] = useState<DetectionResult | null>(null);
  const [metrics, setMetrics] = useState<DetectionMetrics | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [config, setConfig] = useState<DetectionConfig | null>(null);

  // Refs
  const detectionEngineRef = useRef<DetectionEngine | null>(null);
  const videoElementRef = useRef<HTMLVideoElement | null>(null);
  const initializationPromiseRef = useRef<Promise<void> | null>(null);

  // Initialize detection engine
  const initialize = useCallback(async (videoElement: HTMLVideoElement): Promise<void> => {
    console.log('🚀 useDetection.initialize called:', { videoElement: !!videoElement });
    
    // Prevent multiple initializations
    if (initializationPromiseRef.current) {
      console.log('⚠️ Initialization already in progress, returning existing promise');
      return initializationPromiseRef.current;
    }

    setIsLoading(true);
    setError(null);

    const initPromise = (async () => {
      try {
        console.log('🏗️ Creating detection engine...');
        // Create detection engine
        const engine = new DetectionEngine();
        detectionEngineRef.current = engine;
        videoElementRef.current = videoElement;

        // Set up event listeners
        engine.onDetection((detection) => {
          setCurrentDetection(detection);
          onDetection?.(detection);
        });

        engine.onMetrics((newMetrics) => {
          setMetrics(newMetrics);
        });

        // Initialize with progress tracking
        await engine.initialize(modelVariant, (progress) => {
          // You could add progress state here if needed
          console.log(`Model loading: ${progress.toFixed(1)}%`);
        });

        // Get initial configuration
        const initialConfig = engine.getConfig();
        setConfig(initialConfig);

        console.log('Detection hook initialized successfully');

      } catch (err) {
        const error = err instanceof Error ? err : new Error('Unknown initialization error');
        console.error('Detection initialization failed:', error);
        setError(error.message);
        onError?.(error);
        throw error;
      } finally {
        setIsLoading(false);
      }
    })();

    initializationPromiseRef.current = initPromise;
    return initPromise;
  }, [modelVariant, onDetection, onError]);

  // Start continuous detection
  const startContinuous = useCallback(() => {
    console.log('🔄 useDetection.startContinuous called:', {
      hasEngine: !!detectionEngineRef.current,
      hasVideo: !!videoElementRef.current,
      enableContinuous
    });
    
    if (!detectionEngineRef.current || !videoElementRef.current) {
      console.warn('Detection engine or video element not available');
      return;
    }

    if (!enableContinuous) {
      console.warn('Continuous detection is disabled');
      return;
    }

    try {
      console.log('🚀 Starting continuous detection...');
      detectionEngineRef.current.startContinuousDetection(videoElementRef.current);
      setIsDetecting(true);
      setError(null);
      console.log('✅ Continuous detection started successfully');
    } catch (err) {
      const error = err instanceof Error ? err : new Error('Failed to start continuous detection');
      console.error('❌ Start continuous detection failed:', error);
      setError(error.message);
      onError?.(error);
    }
  }, [enableContinuous, onError]);

  // Stop continuous detection
  const stopContinuous = useCallback(() => {
    if (!detectionEngineRef.current) {
      return;
    }

    try {
      detectionEngineRef.current.stopContinuousDetection();
      setIsDetecting(false);
      setCurrentDetection(null);
    } catch (err) {
      console.error('Stop continuous detection failed:', err);
    }
  }, []);

  // Trigger single detection
  const triggerDetection = useCallback(async (): Promise<DetectionResult | null> => {
    if (!detectionEngineRef.current || !videoElementRef.current) {
      throw new Error('Detection engine or video element not available');
    }

    if (!enableTrigger) {
      throw new Error('Trigger detection is disabled');
    }

    try {
      setError(null);
      const detection = await detectionEngineRef.current.triggerDetection(videoElementRef.current);
      
      // Update current detection state
      setCurrentDetection(detection);
      onDetection?.(detection);
      
      return detection;
    } catch (err) {
      const error = err instanceof Error ? err : new Error('Trigger detection failed');
      console.error('Trigger detection failed:', error);
      setError(error.message);
      onError?.(error);
      throw error;
    }
  }, [enableTrigger, onDetection, onError]);

  // Update configuration
  const updateConfig = useCallback(async (newConfig: Partial<DetectionConfig>): Promise<void> => {
    if (!detectionEngineRef.current) {
      throw new Error('Detection engine not available');
    }

    try {
      await detectionEngineRef.current.updateConfig(newConfig);
      const updatedConfig = detectionEngineRef.current.getConfig();
      setConfig(updatedConfig);
      setError(null);
    } catch (err) {
      const error = err instanceof Error ? err : new Error('Failed to update configuration');
      console.error('Update config failed:', error);
      setError(error.message);
      onError?.(error);
      throw error;
    }
  }, [onError]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (detectionEngineRef.current) {
        detectionEngineRef.current.destroy();
        detectionEngineRef.current = null;
      }
      initializationPromiseRef.current = null;
      videoElementRef.current = null;
    };
  }, []);

  return {
    // State
    isLoading,
    isDetecting,
    currentDetection,
    metrics,
    error,
    
    // Actions
    initialize,
    startContinuous,
    stopContinuous,
    triggerDetection,
    updateConfig,
    
    // Config
    config
  };
}

/**
 * Hook for detection metrics monitoring
 */
export function useDetectionMetrics(detectionEngine: DetectionEngine | null) {
  const [metrics, setMetrics] = useState<DetectionMetrics | null>(null);

  useEffect(() => {
    if (!detectionEngine) return;

    detectionEngine.onMetrics(setMetrics);

    // Get initial metrics
    const initialMetrics = detectionEngine.getMetrics();
    setMetrics(initialMetrics);
  }, [detectionEngine]);

  return metrics;
}

/**
 * Hook for performance monitoring and adjustments
 */
export function usePerformanceOptimization(detectionEngine: DetectionEngine | null) {
  const [recommendations, setRecommendations] = useState<string[]>([]);

  useEffect(() => {
    if (!detectionEngine) return;

    const interval = setInterval(() => {
      const metrics = detectionEngine.getMetrics();
      const newRecommendations: string[] = [];

      if (metrics.fps < 15) {
        newRecommendations.push('Consider increasing frame skip or switching to a lighter model');
      }

      if (metrics.inferenceTime > 100) {
        newRecommendations.push('Inference time is high, consider switching to quantized model');
      }

      if (metrics.memoryUsage > 100) {
        newRecommendations.push('High memory usage detected');
      }

      setRecommendations(newRecommendations);
    }, 5000); // Check every 5 seconds

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

  return recommendations;
}