import { useEffect, useState, useCallback } from 'react';

/**
 * Custom hook for managing Chromecast functionality
 * Supports both audio and video casting
 */
export const useChromecast = () => {
  const [castAvailable, setCastAvailable] = useState(false);
  const [casting, setCasting] = useState(false);
  const [castSession, setCastSession] = useState(null);
  const [currentMedia, setCurrentMedia] = useState(null);
  const [initialized, setInitialized] = useState(false);

  // Initialize Cast API
  useEffect(() => {
    const initializeCast = () => {
      try {
        console.log('[Chromecast] Initializing Cast API...');
        
        if (!window.chrome?.cast?.isAvailable) {
          console.log('[Chromecast] Cast API not yet available');
          return;
        }

        const castContext = window.cast.framework.CastContext.getInstance();
        
        // Set Cast options
        castContext.setOptions({
          receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,
          autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED,
          resumeSavedSession: true
        });

        console.log('[Chromecast] Cast options set');

        // Listen for Cast state changes
        castContext.addEventListener(
          window.cast.framework.CastContextEventType.CAST_STATE_CHANGED,
          (event) => {
            console.log('[Chromecast] Cast state changed:', event.castState);
            const isConnected = event.castState === window.cast.framework.CastState.CONNECTED;
            setCasting(isConnected);
            
            // Always show button once initialized, regardless of device availability
            setCastAvailable(true);
            
            if (isConnected) {
              const session = castContext.getCurrentSession();
              setCastSession(session);
            } else {
              setCastSession(null);
              setCurrentMedia(null);
            }
          }
        );

        // Always make cast available once SDK is loaded (button will handle device selection)
        setCastAvailable(true);
        
        const currentState = castContext.getCastState();
        console.log('[Chromecast] Current cast state:', currentState);
        
        const isConnected = currentState === window.cast.framework.CastState.CONNECTED;
        setCasting(isConnected);
        
        if (isConnected) {
          setCastSession(castContext.getCurrentSession());
        }

        setInitialized(true);
        console.log('[Chromecast] Initialization complete');
      } catch (error) {
        console.error('[Chromecast] Initialization error:', error);
      }
    };

    // Wait for Cast API to load
    let checkInterval = null;
    let checkCount = 0;
    const maxChecks = 10;
    
    const checkCastAvailability = () => {
      checkCount++;
      if (window.chrome?.cast?.isAvailable) {
        console.log('[Chromecast] Cast SDK loaded');
        if (checkInterval) {
          clearInterval(checkInterval);
          checkInterval = null;
        }
        initializeCast();
      } else if (checkCount >= maxChecks) {
        console.log('[Chromecast] Cast SDK not available after max attempts');
        if (checkInterval) {
          clearInterval(checkInterval);
          checkInterval = null;
        }
      }
    };

    // Try immediately
    checkCastAvailability();

    // Set up callback for when SDK loads
    window['__onGCastApiAvailable'] = (isAvailable) => {
      console.log('[Chromecast] SDK availability callback:', isAvailable);
      if (isAvailable) {
        if (checkInterval) {
          clearInterval(checkInterval);
          checkInterval = null;
        }
        initializeCast();
      }
    };

    // Check periodically but with limit
    if (!window.chrome?.cast?.isAvailable) {
      checkInterval = setInterval(checkCastAvailability, 1000);
    }

    return () => {
      if (checkInterval) {
        clearInterval(checkInterval);
      }
    };
  }, []);

  /**
   * Cast media to Chromecast device
   * @param {Object} options - Media options
   * @param {string} options.url - Media URL
   * @param {string} options.title - Media title
   * @param {string} options.subtitle - Media subtitle (optional)
   * @param {string} options.contentType - MIME type (e.g., 'audio/mpeg', 'video/mp4', 'application/x-mpegURL')
   * @param {string} options.imageUrl - Thumbnail image URL (optional)
   * @param {boolean} options.isLive - Whether the stream is live (default: true)
   */
  const castMedia = useCallback(async (options) => {
    if (!initialized) {
      console.warn('[Chromecast] Cast not initialized');
      return false;
    }

    const {
      url,
      title,
      subtitle = '',
      contentType = 'application/x-mpegURL',
      imageUrl = '',
      isLive = true
    } = options;

    console.log('[Chromecast] castMedia called with:', { url, title, contentType, isLive });

    try {
      const castContext = window.cast.framework.CastContext.getInstance();
      let session = castContext.getCurrentSession();
      
      // If no session, request one first
      if (!session) {
        console.log('[Chromecast] No active session, requesting session...');
        try {
          await castContext.requestSession();
          session = castContext.getCurrentSession();
          
          if (!session) {
            console.error('[Chromecast] Failed to get session after request');
            return false;
          }
          
          console.log('[Chromecast] Session established');
          setCastSession(session);
        } catch (sessionError) {
          console.error('[Chromecast] Session request failed:', sessionError);
          return false;
        }
      }

      console.log('[Chromecast] Creating media info for URL:', url);
      
      const mediaInfo = new window.chrome.cast.media.MediaInfo(url, contentType);
      
      // Set metadata
      const metadata = new window.chrome.cast.media.GenericMediaMetadata();
      metadata.title = title;
      
      if (subtitle) {
        metadata.subtitle = subtitle;
      }
      
      if (imageUrl) {
        metadata.images = [new window.chrome.cast.Image(imageUrl)];
      }
      
      mediaInfo.metadata = metadata;
      mediaInfo.streamType = isLive 
        ? window.chrome.cast.media.StreamType.LIVE
        : window.chrome.cast.media.StreamType.BUFFERED;

      console.log('[Chromecast] Media info created:', {
        url: mediaInfo.contentId,
        contentType: mediaInfo.contentType,
        streamType: mediaInfo.streamType
      });

      // Create load request
      const request = new window.chrome.cast.media.LoadRequest(mediaInfo);
      request.autoplay = true;
      request.currentTime = 0;
      
      // Set adaptive bitrate settings for better streaming
      if (isLive) {
        // For live streams, optimize for lower latency
        request.customData = {
          lowLatency: true
        };
      }

      console.log('[Chromecast] Loading media...');
      
      // Load media
      const loadResult = await session.loadMedia(request);
      
      console.log('[Chromecast] Media loaded successfully:', loadResult);
      
      // Listen for media status updates
      const mediaSession = session.getMediaSession();
      if (mediaSession) {
        mediaSession.addUpdateListener((isAlive) => {
          if (isAlive) {
            const state = mediaSession.playerState;
            console.log('[Chromecast] Player state:', state);
            
            if (state === window.chrome.cast.media.PlayerState.BUFFERING) {
              console.log('[Chromecast] Buffering...');
            } else if (state === window.chrome.cast.media.PlayerState.PLAYING) {
              console.log('[Chromecast] Playing');
            }
          }
        });
      }
      
      // Store current media info
      setCurrentMedia({
        title,
        subtitle,
        url,
        contentType,
        isLive
      });

      return true;
    } catch (error) {
      console.error('[Chromecast] Error casting media:', error);
      console.error('[Chromecast] Error details:', {
        message: error.message,
        code: error.code,
        description: error.description
      });
      return false;
    }
  }, [initialized, castSession]);

  /**
   * Stop casting and disconnect
   */
  const stopCasting = useCallback(() => {
    if (!initialized) {
      console.warn('[Chromecast] Cannot stop - not initialized');
      return;
    }

    try {
      console.log('[Chromecast] Stopping cast...');
      const castContext = window.cast.framework.CastContext.getInstance();
      const session = castContext.getCurrentSession();
      
      if (session) {
        console.log('[Chromecast] Ending session...');
        // Stop media first
        const media = session.getMediaSession();
        if (media) {
          console.log('[Chromecast] Stopping media...');
          media.stop(new window.chrome.cast.media.StopRequest(), 
            () => console.log('[Chromecast] Media stopped'),
            (error) => console.error('[Chromecast] Media stop error:', error)
          );
        }
        
        // Then end the session
        session.endSession(true);
        console.log('[Chromecast] Session ended');
      } else {
        console.log('[Chromecast] No active session to stop');
      }
      
      setCasting(false);
      setCastSession(null);
      setCurrentMedia(null);
    } catch (error) {
      console.error('[Chromecast] Error stopping cast:', error);
      // Force reset state even on error
      setCasting(false);
      setCastSession(null);
      setCurrentMedia(null);
    }
  }, [initialized]);

  /**
   * Open cast dialog to select device
   */
  const openCastDialog = useCallback(() => {
    if (!initialized) return;

    try {
      const castContext = window.cast.framework.CastContext.getInstance();
      castContext.requestSession();
    } catch (error) {
      console.error('Error opening cast dialog:', error);
    }
  }, [initialized]);

  /**
   * Control playback (play/pause)
   */
  const togglePlayback = useCallback(async () => {
    if (!castSession) return;

    try {
      const mediaSession = castSession.getMediaSession();
      if (!mediaSession) return;

      if (mediaSession.playerState === window.chrome.cast.media.PlayerState.PLAYING) {
        await mediaSession.pause();
      } else {
        await mediaSession.play();
      }
    } catch (error) {
      console.error('Error toggling playback:', error);
    }
  }, [castSession]);

  /**
   * Set volume on cast device
   * @param {number} volume - Volume level (0-1)
   */
  const setCastVolume = useCallback(async (volume) => {
    if (!castSession) return;

    try {
      await castSession.setVolume(volume);
    } catch (error) {
      console.error('Error setting volume:', error);
    }
  }, [castSession]);

  /**
   * Mute/unmute cast device
   * @param {boolean} muted - Mute state
   */
  const setCastMuted = useCallback(async (muted) => {
    if (!castSession) return;

    try {
      await castSession.setMute(muted);
    } catch (error) {
      console.error('Error setting mute:', error);
    }
  }, [castSession]);

  return {
    // State
    castAvailable,
    casting,
    currentMedia,
    initialized,
    
    // Actions
    castMedia,
    stopCasting,
    openCastDialog,
    togglePlayback,
    setCastVolume,
    setCastMuted
  };
};

export default useChromecast;
