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

export interface UseUploadResult {
  upload(file: File, opts?: { signal?: AbortSignal }): Promise<MediaItem>
  uploading: boolean
  progress: number
  error: Error | null
  reset(): void
}

export function useUpload(client: MediaClient): UseUploadResult {
  const [uploading, setUploading] = useState(false)
  const [progress, setProgress] = useState(0)
  const [error, setError] = useState<Error | null>(null)
  const clientRef = useRef(client)
  clientRef.current = client
  const inFlightRef = useRef(false)

  const upload = useCallback(async (file: File, opts?: { signal?: AbortSignal }): Promise<MediaItem> => {
    if (inFlightRef.current) {
      throw new UploadInFlightError()
    }
    inFlightRef.current = true
    setUploading(true)
    setProgress(0)
    setError(null)
    try {
      const item = await clientRef.current.upload(file, {
        signal: opts?.signal,
        onProgress: (f) => setProgress(f),
      })
      setProgress(1)
      return item
    } catch (e) {
      const err = e instanceof Error ? e : new Error(String(e))
      setError(err)
      throw err
    } finally {
      inFlightRef.current = false
      setUploading(false)
    }
  }, [])

  const reset = useCallback(() => {
    setError(null)
    setProgress(0)
  }, [])

  return { upload, uploading, progress, error, reset }
}
