import { useCallback, useEffect, useRef, useState } from 'react'
import type { MediaClient, MediaItem } from './client.js'

export interface UseMediaLibraryResult {
  items: MediaItem[]
  loading: boolean
  error: Error | null
  hasMore: boolean
  loadMore(): Promise<void>
  refresh(): Promise<void>
  remove(key: string): Promise<void>
}

export function useMediaLibrary(client: MediaClient, opts?: { limit?: number }): UseMediaLibraryResult {
  const [items, setItems] = useState<MediaItem[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<Error | null>(null)
  const [cursor, setCursor] = useState<string | undefined>(undefined)
  const [hasMore, setHasMore] = useState(false)
  const clientRef = useRef(client)
  clientRef.current = client
  const inFlightRef = useRef(false)
  const limit = opts?.limit

  const fetchPage = useCallback(async (reset: boolean, fromCursor?: string) => {
    if (inFlightRef.current) return
    inFlightRef.current = true
    setLoading(true)
    setError(null)
    try {
      const res = await clientRef.current.list({ cursor: fromCursor, limit })
      setItems((prev) => (reset ? res.items : [...prev, ...res.items]))
      setCursor(res.cursor)
      setHasMore(Boolean(res.cursor))
    } catch (e) {
      setError(e instanceof Error ? e : new Error(String(e)))
    } finally {
      inFlightRef.current = false
      setLoading(false)
    }
  }, [limit])

  useEffect(() => {
    void fetchPage(true, undefined)
  }, [fetchPage])

  const loadMore = useCallback(async () => {
    if (!cursor) return
    await fetchPage(false, cursor)
  }, [cursor, fetchPage])

  const refresh = useCallback(async () => {
    await fetchPage(true, undefined)
  }, [fetchPage])

  const remove = useCallback(async (key: string) => {
    try {
      await clientRef.current.remove(key)
      setItems((prev) => prev.filter((i) => i.key !== key))
    } catch (e) {
      setError(e instanceof Error ? e : new Error(String(e)))
    }
  }, [])

  return { items, loading, error, hasMore, loadMore, refresh, remove }
}
