import * as React from 'react'

import {Star, StarHalf} from 'lucide-react'

import {cn} from '../../lib/utils'
import {formatReviewCount, normalizeRating} from '../../utils/merchant-card'

const starSizeClasses = {
  sm: 'h-3 w-3',
  md: 'h-4 w-4',
  lg: 'h-5 w-5',
} as const

const textSizeClasses = {
  sm: 'text-xs',
  md: 'text-sm',
  lg: 'text-base',
} as const

export interface ProductReviewStarsProps extends React.HTMLAttributes<HTMLDivElement> {
  /**
   * Average rating value (0-5)
   */
  averageRating: number
  /**
   * Total number of reviews
   */
  reviewCount?: number | null
  /**
   * Custom color for filled star
   * @default 'var(--grayscale-d100)' (black)
   */
  filledStarColor?: string
  /**
   * Custom color for empty star
   * @default 'var(--grayscale-l20)' (light gray)
   */
  emptyStarColor?: string
  /**
   * Size of the stars
   * @default 'sm'
   */
  size?: 'sm' | 'md' | 'lg'
}

export const ProductReviewStars = React.forwardRef<
  HTMLDivElement,
  ProductReviewStarsProps
>(
  (
    {
      averageRating,
      reviewCount,
      size = 'sm',
      filledStarColor = 'var(--grayscale-d100)',
      emptyStarColor = 'var(--grayscale-l20)',
      className,
      ...props
    },
    ref
  ) => {
    const normalizedRating = Math.min(5, normalizeRating(averageRating))
    const filledStars = Math.floor(normalizedRating)
    const remainder = normalizedRating % 1

    return (
      <div
        ref={ref}
        className={cn('flex items-center', className)}
        data-slot="product-review-stars"
        {...props}
      >
        <div className="relative">
          <div className="flex">
            {Array.from({length: 5}, (_, i) => (
              <Star
                key={i}
                className={cn(starSizeClasses[size])}
                style={{fill: emptyStarColor}}
                strokeWidth={0}
              />
            ))}
          </div>
          <div className="flex absolute top-0 left-0">
            {Array.from({length: filledStars}, (_, i) => (
              <Star
                key={i}
                className={cn(starSizeClasses[size])}
                style={{fill: filledStarColor}}
                strokeWidth={0}
              />
            ))}
            {remainder >= 0.5 && (
              <StarHalf
                className={cn(starSizeClasses[size])}
                style={{fill: filledStarColor}}
                strokeWidth={0}
              />
            )}
          </div>
        </div>
        {reviewCount && (
          <span className={cn(textSizeClasses[size], 'ml-1')}>
            ({formatReviewCount(reviewCount)})
          </span>
        )}
      </div>
    )
  }
)

ProductReviewStars.displayName = 'ProductReviewStars'
