import { useState } from 'react'
import { trpc } from '@/src/trpc-client'

type ContextString = 'review' | 'product_info' | 'notification' | 'store' | 'complaint' | 'profile'

interface UploadInput {
  blob: Blob
  mimeType: string
}

interface UploadBatchInput {
  images: UploadInput[]
  contextString: ContextString
}

interface UploadResult {
  keys: string[]
  presignedUrls: string[]
}

export function useUploadToObjectStorage() {
  const [isUploading, setIsUploading] = useState(false)
  const [error, setError] = useState<Error | null>(null)
  const [progress, setProgress] = useState<{ completed: number; total: number } | null>(null)

  const generateUploadUrls = trpc.common.generateUploadUrls.useMutation()

  const upload = async (input: UploadBatchInput): Promise<UploadResult> => {
    setIsUploading(true)
    setError(null)
    setProgress({ completed: 0, total: input.images.length })

    try {
      const { images, contextString } = input

      if (images.length === 0) {
        return { keys: [], presignedUrls: [] }
      }

      const mimeTypes = images.map((img) => img.mimeType)
      const { uploadUrls } = await generateUploadUrls.mutateAsync({
        contextString: contextString as any,
        mimeTypes,
      })

      if (uploadUrls.length !== images.length) {
        throw new Error(`Expected ${images.length} URLs, got ${uploadUrls.length}`)
      }

      const uploadPromises = images.map(async (image, index) => {
        const presignedUrl = uploadUrls[index]
        const { blob, mimeType } = image

        const response = await fetch(presignedUrl, {
          method: 'PUT',
          body: blob,
          headers: { 'Content-Type': mimeType },
        })

        if (!response.ok) {
          throw new Error(`Upload ${index + 1} failed with status ${response.status}`)
        }

        setProgress((prev) => (prev ? { ...prev, completed: prev.completed + 1 } : null))

        return {
          key: extractKeyFromPresignedUrl(presignedUrl),
          presignedUrl,
        }
      })

      const results = await Promise.all(uploadPromises)

      return {
        keys: results.map((result) => result.key),
        presignedUrls: results.map((result) => result.presignedUrl),
      }
    } catch (err) {
      const uploadError = err instanceof Error ? err : new Error('Upload failed')
      setError(uploadError)
      throw uploadError
    } finally {
      setIsUploading(false)
      setProgress(null)
    }
  }

  const uploadSingle = async (
    blob: Blob,
    mimeType: string,
    contextString: ContextString
  ): Promise<{ key: string; presignedUrl: string }> => {
    const result = await upload({
      images: [{ blob, mimeType }],
      contextString,
    })

    return {
      key: result.keys[0],
      presignedUrl: result.presignedUrls[0],
    }
  }

  return {
    upload,
    uploadSingle,
    isUploading,
    error,
    progress,
    isPending: generateUploadUrls.isPending,
  }
}

function extractKeyFromPresignedUrl(url: string): string {
  const parsedUrl = new URL(url)
  let rawKey = parsedUrl.pathname.replace(/^\/+/, '')
  rawKey = rawKey.split('/').slice(1).join('/')
  return decodeURIComponent(rawKey)
}
