import { useCallback, useRef, useState } from 'react'
import type { Product } from '@platform-modules/commerce-catalog'
import { reviveProduct } from '@platform-modules/commerce-catalog-react'
import type { ProductPatch } from '@platform-modules/commerce-marketplace'
import { useMarketplaceContext } from './MarketplaceProvider.js'

export function useUpdateVendorProduct(): {
  update: (productId: string, patch: ProductPatch) => Promise<Product>
  pending: boolean
  result: Product | undefined
  error: Error | undefined
  reset: () => void
} {
  const { client } = useMarketplaceContext('useUpdateVendorProduct')
  const [result, setResult] = useState<Product | undefined>()
  const [error, setError] = useState<Error | undefined>()
  const [pending, setPending] = useState(false)

  const inflightRef = useRef(0)
  const latestTagRef = useRef(0)

  const update = useCallback((productId: string, patch: ProductPatch): Promise<Product> => {
    const tag = ++latestTagRef.current
    inflightRef.current++
    setPending(inflightRef.current > 0)

    return client
      .updateVendorProduct(productId, patch)
      .then((wire) => {
        const revived = reviveProduct(wire)
        if (latestTagRef.current === tag) {
          setResult(revived)
          setError(undefined)
        }
        return revived
      })
      .catch((e: unknown) => {
        if (latestTagRef.current === tag) {
          setError(e instanceof Error ? e : new Error(String(e)))
          setResult(undefined)
        }
        throw e
      })
      .finally(() => {
        inflightRef.current--
        setPending(inflightRef.current > 0)
      })
  }, [client])

  const reset = useCallback(() => {
    // Orphan any in-flight update so its later resolve/reject no-ops on visible
    // state (same model as useSubmitReview); finally still decrements inflightRef.
    latestTagRef.current++
    setResult(undefined)
    setError(undefined)
  }, [])

  return { update, pending, result, error, reset }
}
