"use client";

import { useId } from "react";

interface SparklineProps {
  data: number[];
  width?: number;
  height?: number;
  color?: string;
  fillOpacity?: number;
  strokeWidth?: number;
  className?: string;
  animated?: boolean;
}

function buildPoints(
  data: number[],
  width: number,
  height: number,
  strokeWidth: number,
): string {
  if (data.length === 0) return "";

  const padding = strokeWidth;
  const drawWidth = width - padding * 2;
  const drawHeight = height - padding * 2;

  const min = Math.min(...data);
  const max = Math.max(...data);
  const range = max - min || 1; // avoid division by zero when all values equal

  return data
    .map((v, i) => {
      const x =
        data.length === 1
          ? width / 2
          : padding + (i / (data.length - 1)) * drawWidth;
      const y = padding + drawHeight - ((v - min) / range) * drawHeight;
      return `${x},${y}`;
    })
    .join(" ");
}

function buildAreaPoints(
  linePoints: string,
  width: number,
  height: number,
  strokeWidth: number,
  dataLength: number,
): string {
  if (!linePoints) return "";

  const padding = strokeWidth;
  const drawWidth = width - padding * 2;
  const bottom = height - padding;

  const lastX =
    dataLength === 1 ? width / 2 : padding + drawWidth;
  const firstX = dataLength === 1 ? width / 2 : padding;

  return `${linePoints} ${lastX},${bottom} ${firstX},${bottom}`;
}

export function Sparkline({
  data,
  width = 60,
  height = 20,
  color = "currentColor",
  fillOpacity = 0.1,
  strokeWidth = 1.5,
  className,
  animated = true,
}: SparklineProps) {
  const id = useId();

  if (data.length === 0) {
    return (
      <svg
        width={width}
        height={height}
        viewBox={`0 0 ${width} ${height}`}
        className={className}
        role="img"
        aria-label="No data"
      />
    );
  }

  const linePoints = buildPoints(data, width, height, strokeWidth);
  const areaPoints = buildAreaPoints(
    linePoints,
    width,
    height,
    strokeWidth,
    data.length,
  );

  // Approximate path length for dash animation
  const approxLength = width * 2;

  return (
    <>
      {animated && (
        <style
          dangerouslySetInnerHTML={{
            __html: `
              @keyframes sparkline-draw-${CSS.escape(id)} {
                from { stroke-dashoffset: ${approxLength}; }
                to   { stroke-dashoffset: 0; }
              }
            `,
          }}
        />
      )}
      <svg
        width={width}
        height={height}
        viewBox={`0 0 ${width} ${height}`}
        className={className}
        role="img"
        aria-label={`Sparkline: ${data.join(", ")}`}
      >
        {/* Area fill */}
        {data.length > 1 && (
          <polygon
            points={areaPoints}
            fill={color}
            opacity={fillOpacity}
          />
        )}

        {/* Line */}
        {data.length === 1 ? (
          <circle
            cx={width / 2}
            cy={height / 2}
            r={strokeWidth}
            fill={color}
          />
        ) : (
          <polyline
            points={linePoints}
            fill="none"
            stroke={color}
            strokeWidth={strokeWidth}
            strokeLinecap="round"
            strokeLinejoin="round"
            {...(animated
              ? {
                  strokeDasharray: approxLength,
                  strokeDashoffset: approxLength,
                  style: {
                    animation: `sparkline-draw-${CSS.escape(id)} 600ms ease-out forwards`,
                  },
                }
              : {})}
          />
        )}
      </svg>
    </>
  );
}
