import * as React from 'react'
import { cn } from '../core/cn'

type SparklineVariant = 'line' | 'area' | 'bar'

interface SparklineProps extends React.SVGAttributes<SVGSVGElement> {
  data: number[]
  variant?: SparklineVariant
  color?: string
  width?: number
  height?: number
  strokeWidth?: number
  showLastPoint?: boolean
}

function getPath(data: number[], width: number, height: number, padding: number = 2) {
  if (data.length === 0) return { linePath: '', areaPath: '' }
  const min = Math.min(...data)
  const max = Math.max(...data)
  const range = max - min || 1
  const ew = width - padding * 2
  const eh = height - padding * 2
  const points = data.map((value, index) => ({
    x: padding + (index / (data.length - 1)) * ew,
    y: padding + eh - ((value - min) / range) * eh,
  }))
  const linePath = points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ')
  const areaPath = `${linePath} L ${points[points.length - 1].x} ${height - padding} L ${padding} ${height - padding} Z`
  return { linePath, areaPath }
}

const Sparkline = React.forwardRef<SVGSVGElement, SparklineProps>(
  ({ data, variant = 'line', color = 'currentColor', width = 80, height = 24, strokeWidth = 1.5, showLastPoint = true, className, ...props }, ref) => {
    if (data.length === 0) return <svg ref={ref} width={width} height={height} viewBox={`0 0 ${width} ${height}`} className={cn('text-primary', className)} {...props} />

    if (variant === 'bar') {
      const min = Math.min(...data, 0)
      const max = Math.max(...data)
      const range = max - min || 1
      const p = 2
      const eh = height - p * 2
      const bw = (width - p * 2) / data.length - 1
      return (
        <svg ref={ref} width={width} height={height} viewBox={`0 0 ${width} ${height}`} className={cn('text-primary', className)} {...props}>
          {data.map((value, index) => {
            const bh = ((value - min) / range) * eh
            const x = p + index * ((width - p * 2) / data.length) + 0.5
            const y = p + eh - bh
            return <rect key={index} x={x} y={y} width={Math.max(bw, 1)} height={Math.max(bh, 1)} fill={color} opacity={0.8} />
          })}
        </svg>
      )
    }

    const { linePath, areaPath } = getPath(data, width, height)
    const lastPoint = {
      x: width - 2,
      y: 2 + (height - 4) - ((data[data.length - 1] - Math.min(...data)) / (Math.max(...data) - Math.min(...data) || 1)) * (height - 4)
    }

    return (
      <svg ref={ref} width={width} height={height} viewBox={`0 0 ${width} ${height}`} className={cn('text-primary', className)} {...props}>
        {variant === 'area' && <path d={areaPath} fill={color} opacity={0.2} />}
        <path d={linePath} fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" />
        {showLastPoint && <circle cx={lastPoint.x} cy={lastPoint.y} r={2.5} fill={color} />}
      </svg>
    )
  }
)
Sparkline.displayName = 'Sparkline'

export { Sparkline, type SparklineProps, type SparklineVariant }
