"use client";

import { useMemo } from "react";
import { cn } from "@/lib/utils";

export type ProgressRingVariant = "arc" | "circle";

export interface ProgressRingProps {
  value: number;
  max?: number;
  label: string;
  sublabel?: string;
  variant?: ProgressRingVariant;
  size?: "sm" | "md" | "lg";
  className?: string;
  showFraction?: boolean;
  unit?: string;
}

function ringColor(ratio: number): string {
  if (ratio >= 0.7) return "var(--success-green)";
  if (ratio >= 0.5) return "var(--warning-amber)";
  return "#DC2626";
}

const sizeConfig = {
  sm: { box: 72, stroke: 6, fontSize: "text-lg" },
  md: { box: 120, stroke: 8, fontSize: "text-2xl" },
  lg: { box: 140, stroke: 10, fontSize: "text-3xl" },
} as const;

export function ProgressRing({
  value,
  max = 100,
  label,
  sublabel,
  variant = "arc",
  size = "md",
  className,
  showFraction = true,
  unit,
}: ProgressRingProps) {
  const clamped = Math.max(0, Math.min(value, max));
  const ratio = max > 0 ? clamped / max : 0;
  const { box, stroke, fontSize } = sizeConfig[size];
  const radius = variant === "circle" ? (box - stroke) / 2 - 4 : 54;
  const center = box / 2;

  const { path, circumference, dashOffset, viewBox, height } = useMemo(() => {
    if (variant === "circle") {
      const c = 2 * Math.PI * radius;
      return {
        path: `M ${center} ${stroke + 4} A ${radius} ${radius} 0 1 1 ${center - 0.01} ${stroke + 4}`,
        circumference: c,
        dashOffset: c * (1 - ratio),
        viewBox: `0 0 ${box} ${box}`,
        height: box,
      };
    }

    const arcCircumference = Math.PI * radius;
    return {
      path: `M ${center - radius} ${center + radius * 0.4} A ${radius} ${radius} 0 0 1 ${center + radius} ${center + radius * 0.4}`,
      circumference: arcCircumference,
      dashOffset: arcCircumference * (1 - ratio),
      viewBox: `0 0 ${box} ${Math.round(box * 0.65)}`,
      height: Math.round(box * 0.65),
    };
  }, [variant, radius, center, box, stroke, ratio]);

  const color = ringColor(ratio);
  const ariaValueText = showFraction
    ? `${clamped} of ${max}`
    : `${Math.round(ratio * 100)} percent`;

  return (
    <div
      className={cn("inline-flex flex-col items-center gap-1", className)}
      role="group"
      aria-label={`${label}: ${ariaValueText}`}
    >
      <div
        className="relative"
        style={{ width: box, height }}
      >
        <svg
          viewBox={viewBox}
          className="h-full w-full motion-reduce:transition-none"
          role="img"
          aria-label={`${label}: ${ariaValueText}`}
        >
          <path
            d={path}
            fill="none"
            stroke="currentColor"
            className="text-ink/10"
            strokeWidth={stroke}
            strokeLinecap="round"
          />
          <path
            d={path}
            fill="none"
            stroke={color}
            strokeWidth={stroke}
            strokeLinecap="round"
            strokeDasharray={circumference}
            strokeDashoffset={dashOffset}
            className="transition-all duration-700 ease-out motion-reduce:transition-none"
          />
        </svg>
        <div
          className={cn(
            "absolute inset-0 flex flex-col items-center justify-center",
            variant === "arc" ? "pt-2" : "",
          )}
          aria-hidden="true"
        >
          <span className={cn("font-onest font-bold leading-none text-ink", fontSize)}>
            {clamped}
            {unit ? (
              <span className="font-inter text-xs font-medium text-muted"> {unit}</span>
            ) : null}
          </span>
          {showFraction ? (
            <span className="font-inter text-xs text-muted">/{max}</span>
          ) : null}
        </div>
      </div>
      <span className="font-inter text-sm font-medium text-ink">{label}</span>
      {sublabel ? (
        <span className="font-inter text-xs text-muted">{sublabel}</span>
      ) : null}
      <span className="sr-only">
        {label}: {ariaValueText}
        {sublabel ? `, ${sublabel}` : ""}
      </span>
    </div>
  );
}
