import { ref, onMounted, onUnmounted } from 'vue'

export interface PollingOptions {
  interval?: number // milliseconds
  immediate?: boolean // whether to execute immediately on start
  maxRetries?: number // maximum number of retries on error
  retryDelay?: number // delay between retries in milliseconds
  onError?: (error: Error) => void // error handler
}

export interface PollingState {
  isPolling: boolean
  isFetching: boolean
  error: string | null
  retryCount: number
  lastFetchTime: Date | null
}

/**
 * Composable for implementing polling/real-time updates
 * 
 * @param callback - Function to execute on each poll
 * @param options - Polling configuration options
 * @returns Polling controls and state
 */
export const usePolling = <T>(
  callback: () => Promise<T> | T,
  options: PollingOptions = {}
) => {
  const {
    interval = 3000, // 3 seconds default
    immediate = true,
    maxRetries = 3,
    retryDelay = 1000,
    onError
  } = options

  // State
  const state = ref<PollingState>({
    isPolling: false,
    isFetching: false,
    error: null,
    retryCount: 0,
    lastFetchTime: null
  })

  // Polling interval reference
  let pollInterval: NodeJS.Timeout | null = null
  let retryTimeout: NodeJS.Timeout | null = null

  // Execute the polling callback
  const executePoll = async (): Promise<T | null> => {
    if (state.value.isFetching) {
      return null // Skip if already fetching
    }

    state.value.isFetching = true
    state.value.error = null

    try {
      const result = await callback()
      state.value.lastFetchTime = new Date()
      state.value.retryCount = 0 // Reset retry count on success
      return result
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      state.value.error = errorMessage
      state.value.retryCount++

      // Call error handler if provided
      if (onError) {
        onError(error instanceof Error ? error : new Error(errorMessage))
      }

      // Handle retries
      if (state.value.retryCount <= maxRetries) {
        console.warn(`Polling error (retry ${state.value.retryCount}/${maxRetries}):`, errorMessage)
        
        // Schedule retry
        if (retryTimeout) {
          clearTimeout(retryTimeout)
        }
        
        retryTimeout = setTimeout(() => {
          executePoll()
        }, retryDelay)
      } else {
        console.error(`Polling failed after ${maxRetries} retries:`, errorMessage)
        stopPolling() // Stop polling after max retries
      }
      
      return null
    } finally {
      state.value.isFetching = false
    }
  }

  // Start polling
  const startPolling = () => {
    if (state.value.isPolling) {
      return // Already polling
    }

    state.value.isPolling = true
    state.value.error = null

    // Execute immediately if requested
    if (immediate) {
      executePoll()
    }

    // Set up interval
    pollInterval = setInterval(() => {
      executePoll()
    }, interval)
  }

  // Stop polling
  const stopPolling = () => {
    if (pollInterval) {
      clearInterval(pollInterval)
      pollInterval = null
    }

    if (retryTimeout) {
      clearTimeout(retryTimeout)
      retryTimeout = null
    }

    state.value.isPolling = false
    state.value.isFetching = false
  }

  // Toggle polling
  const togglePolling = () => {
    if (state.value.isPolling) {
      stopPolling()
    } else {
      startPolling()
    }
  }

  // Force immediate execution
  const forcePoll = async (): Promise<T | null> => {
    return await executePoll()
  }

  // Update polling interval
  const updateInterval = (newInterval: number) => {
    const wasPolling = state.value.isPolling
    
    if (wasPolling) {
      stopPolling()
    }
    
    // Update interval in options (for next start)
    options.interval = newInterval
    
    if (wasPolling) {
      startPolling()
    }
  }

  // Cleanup on unmount
  onUnmounted(() => {
    stopPolling()
  })

  // Auto-start on mount if immediate is true
  onMounted(() => {
    if (immediate) {
      startPolling()
    }
  })

  return {
    // State
    state: state.value,
    isPolling: state.value.isPolling,
    isFetching: state.value.isFetching,
    error: state.value.error,
    retryCount: state.value.retryCount,
    lastFetchTime: state.value.lastFetchTime,

    // Controls
    startPolling,
    stopPolling,
    togglePolling,
    forcePoll,
    updateInterval,

    // Helper
    resetError: () => {
      state.value.error = null
      state.value.retryCount = 0
    }
  }
}

export default usePolling