"use client"
import NumberFlow from "@number-flow/react"
import React, { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"
import { useLocale } from "../../hooks"
import { BigNumberLike, bn, classNames, EM_DASH } from "../../utils"
import {
  getBoundedNumber,
  getNumberFormatOptions,
  getNumberPrefix,
  isValidNumber,
  NumberFormatOptions,
  ONE_BIL,
} from "../../utils/formatter/number"

export type AnimatedNumberProps = {
  value?: BigNumberLike | undefined | null
  className?: string
} & NumberFormatOptions &
  ComponentPropsWithoutRef<"span">

export const AnimatedNumber = forwardRef<
  ElementRef<"span">,
  AnimatedNumberProps
>(function AnimatedNumber(
  { value, className, display = "quantity", prefix, suffix, bounded, ...rest },
  ref,
) {
  const locale = useLocale()

  if (!isValidNumber(value)) {
    return EM_DASH
  }

  const number = bn(value).toNumber()

  const numberFormatOptions = getNumberFormatOptions({
    display,
    value: number,
  })

  const lowerBound =
    numberFormatOptions.maximumFractionDigits !== undefined
      ? bn(1, numberFormatOptions.maximumFractionDigits).toNumber()
      : undefined

  const boundedNumber = getBoundedNumber(display, number, {
    upperBound: bounded ? ONE_BIL : undefined,
    lowerBound,
  })

  const numberPrefix = getNumberPrefix(display, number, {
    upperBound: bounded ? ONE_BIL : undefined,
    lowerBound,
  })

  // Combine both prefixes into a single string
  const combinedPrefix = `${prefix || ""}${numberPrefix || ""}`

  return (
    <span
      aria-label={boundedNumber.toString()}
      className={classNames("font-mono", className)}
      ref={ref}
      {...rest}
    >
      <NumberFlow
        format={numberFormatOptions}
        locales={locale}
        prefix={combinedPrefix || undefined}
        suffix={suffix ? ` ${suffix}` : undefined}
        value={boundedNumber}
      />
    </span>
  )
})
