"use client"

import { useState, useEffect, useCallback } from "react"
import { offlineStorage } from "@/lib/offline-storage"

interface OfflineState {
  isOffline: boolean
  isOnline: boolean
  wasOffline: boolean // Was offline but now back online (for sync)
}

export function useOffline() {
  const [state, setState] = useState<OfflineState>({
    isOffline: typeof navigator !== "undefined" ? !navigator.onLine : false,
    isOnline: typeof navigator !== "undefined" ? navigator.onLine : true,
    wasOffline: false,
  })

  useEffect(() => {
    const handleOnline = () => {
      setState(prev => ({
        isOffline: false,
        isOnline: true,
        wasOffline: prev.isOffline, // Mark that we were offline
      }))
    }

    const handleOffline = () => {
      setState({
        isOffline: true,
        isOnline: false,
        wasOffline: false,
      })
    }

    window.addEventListener("online", handleOnline)
    window.addEventListener("offline", handleOffline)

    return () => {
      window.removeEventListener("online", handleOnline)
      window.removeEventListener("offline", handleOffline)
    }
  }, [])

  const clearWasOffline = useCallback(() => {
    setState(prev => ({ ...prev, wasOffline: false }))
  }, [])

  return {
    ...state,
    clearWasOffline,
  }
}

// Hook for offline data caching
export function useOfflineCache<T>(
  key: string,
  fetchFn: () => Promise<T>,
  options: {
    userId?: string
    enabled?: boolean
    staleTime?: number // ms before data is considered stale
  } = {}
) {
  const { userId, enabled = true, staleTime = 5 * 60 * 1000 } = options
  const [data, setData] = useState<T | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [error, setError] = useState<Error | null>(null)
  const [isFromCache, setIsFromCache] = useState(false)
  const { isOffline } = useOffline()

  const cacheKey = `offline-cache-${key}`

  useEffect(() => {
    if (!enabled) {
      setIsLoading(false)
      return
    }

    async function loadData() {
      setIsLoading(true)
      setError(null)

      // Try to get cached data first
      const cached = localStorage.getItem(cacheKey)
      if (cached) {
        try {
          const { data: cachedData, timestamp } = JSON.parse(cached)
          const isStale = Date.now() - timestamp > staleTime
          
          // Use cached data immediately
          setData(cachedData)
          setIsFromCache(true)

          // If offline or data is fresh, don't fetch
          if (isOffline || !isStale) {
            setIsLoading(false)
            return
          }
        } catch (e) {
          console.warn("[useOfflineCache] Failed to parse cache:", e)
        }
      }

      // If offline and no cache, return early
      if (isOffline) {
        setIsLoading(false)
        return
      }

      // Fetch fresh data
      try {
        const freshData = await fetchFn()
        setData(freshData)
        setIsFromCache(false)

        // Cache the data
        localStorage.setItem(cacheKey, JSON.stringify({
          data: freshData,
          timestamp: Date.now(),
        }))
      } catch (e) {
        setError(e as Error)
        // Keep cached data on error
      } finally {
        setIsLoading(false)
      }
    }

    loadData()
  }, [enabled, isOffline, cacheKey, staleTime])

  const refresh = useCallback(async () => {
    if (isOffline) return

    setIsLoading(true)
    try {
      const freshData = await fetchFn()
      setData(freshData)
      setIsFromCache(false)
      localStorage.setItem(cacheKey, JSON.stringify({
        data: freshData,
        timestamp: Date.now(),
      }))
    } catch (e) {
      setError(e as Error)
    } finally {
      setIsLoading(false)
    }
  }, [isOffline, cacheKey])

  return {
    data,
    isLoading,
    error,
    isFromCache,
    isOffline,
    refresh,
  }
}

// Store pending actions to sync when back online
interface PendingAction {
  id: string
  type: "like" | "unlike" | "play_history" | "playlist_add"
  payload: any
  timestamp: number
}

const PENDING_ACTIONS_KEY = "offline-pending-actions"

export function usePendingActions() {
  const { isOnline, wasOffline, clearWasOffline } = useOffline()

  const addPendingAction = useCallback((action: Omit<PendingAction, "id" | "timestamp">) => {
    const pending = JSON.parse(localStorage.getItem(PENDING_ACTIONS_KEY) || "[]")
    pending.push({
      ...action,
      id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      timestamp: Date.now(),
    })
    localStorage.setItem(PENDING_ACTIONS_KEY, JSON.stringify(pending))
  }, [])

  const getPendingActions = useCallback((): PendingAction[] => {
    return JSON.parse(localStorage.getItem(PENDING_ACTIONS_KEY) || "[]")
  }, [])

  const clearPendingActions = useCallback(() => {
    localStorage.removeItem(PENDING_ACTIONS_KEY)
  }, [])

  const removePendingAction = useCallback((id: string) => {
    const pending = JSON.parse(localStorage.getItem(PENDING_ACTIONS_KEY) || "[]")
    const filtered = pending.filter((a: PendingAction) => a.id !== id)
    localStorage.setItem(PENDING_ACTIONS_KEY, JSON.stringify(filtered))
  }, [])

  // Auto-sync when coming back online
  useEffect(() => {
    if (wasOffline && isOnline) {
      const pending = getPendingActions()
      if (pending.length > 0) {
        console.log("[useOffline] Syncing", pending.length, "pending actions...")
        // Dispatch event for sync handling
        window.dispatchEvent(new CustomEvent("offline-sync-needed", { 
          detail: { actions: pending } 
        }))
      }
      clearWasOffline()
    }
  }, [wasOffline, isOnline, clearWasOffline, getPendingActions])

  return {
    addPendingAction,
    getPendingActions,
    clearPendingActions,
    removePendingAction,
  }
}
