import { useCallback, useRef, type Ref, type RefCallback } from 'react'
import { useMergedRefs } from '@base-ui/utils/useMergedRefs'

import {
  parseCSSPropValue,
  type ComponentCSSPropsConfig,
  type CSSPropType,
  type GDSComponent,
} from '@graphprotocol/gds-css'

import { styleScheduler } from '../utils/index.ts'

/**
 * Returns a `ref` to set on an element, and an async function to get the current value of a CSS
 * prop from said element (or `null` if we can't access the DOM, e.g. on the server).
 */
export function useCSSProp<
  C extends GDSComponent,
  P extends keyof ComponentCSSPropsConfig<C> & string,
>(component: C, propName: P, options: { ref?: Ref<HTMLElement> } = {}) {
  const { ref: passedRef } = options
  const elementRef = useRef<HTMLElement>(null)
  const callbackRef: RefCallback<HTMLElement> | null = useMergedRefs(elementRef, passedRef)
  const cssProp = component.getCSSPropByName(propName)

  const getCSSPropValue = useCallback(async () => {
    if (typeof window === 'undefined' || !elementRef.current) return null
    const element = elementRef.current
    const computedStyle = await styleScheduler.getComputedStyle(element)
    const rawValue = computedStyle.getPropertyValue(cssProp.cssProperty)
    return parseCSSPropValue(cssProp, rawValue) as CSSPropType<ComponentCSSPropsConfig<C>[P]>
  }, [cssProp])

  return [callbackRef, getCSSPropValue] as const
}
