<script lang="ts">
  interface Props {
    progress: number;
    size?: number;
    strokeWidth?: number;
    accentColor?: string;
    label?: string;
    valueText?: string;
    children?: import("svelte").Snippet;
  }

  let {
    progress,
    size = 280,
    strokeWidth = 8,
    accentColor = "#ff4d00",
    label = "Timer",
    valueText = "",
    children,
  }: Props = $props();

  const padding = 40;
  const viewSize = $derived(size + padding * 2);
  const radius = $derived((size - strokeWidth) / 2);
  const circumference = $derived(2 * Math.PI * radius);
  const dashOffset = $derived(circumference * (1 - progress));
  const center = $derived(viewSize / 2);

  // Unique filter IDs based on color to avoid SVG collisions
  const fid = $derived(`ring-${size}-${accentColor.replace('#', '')}`);

  // Derive lighter shade for gradient end
  function lighten(hex: string, amount: number): string {
    const r = parseInt(hex.slice(1, 3), 16);
    const g = parseInt(hex.slice(3, 5), 16);
    const b = parseInt(hex.slice(5, 7), 16);
    const lr = Math.min(255, r + (255 - r) * amount);
    const lg = Math.min(255, g + (255 - g) * amount);
    const lb = Math.min(255, b + (255 - b) * amount);
    return `#${Math.round(lr).toString(16).padStart(2, '0')}${Math.round(lg).toString(16).padStart(2, '0')}${Math.round(lb).toString(16).padStart(2, '0')}`;
  }

  const gradA = $derived(accentColor);
  const gradB = $derived(lighten(accentColor, 0.2));
  const gradC = $derived(lighten(accentColor, 0.4));
</script>

<div
  class="relative flex items-center justify-center"
  style="width: {size}px; height: {size}px;"
  role="progressbar"
  aria-valuemin={0}
  aria-valuemax={100}
  aria-valuenow={Math.round(progress * 100)}
  aria-label={label}
  aria-valuetext={valueText}
>
  <!-- Glow SVG -- drawn larger than the container so blur isn't clipped -->
  <svg
    aria-hidden="true"
    width={viewSize}
    height={viewSize}
    class="pointer-events-none absolute"
    style="
      left: {-padding}px;
      top: {-padding}px;
      transform: rotate(-90deg);
      overflow: visible;
    "
  >
    <defs>
      <linearGradient id="ring-grad-{fid}" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color={gradA} />
        <stop offset="50%" stop-color={gradB} />
        <stop offset="100%" stop-color={gradC} />
      </linearGradient>

      <!-- Wide ambient glow filter -->
      <filter id="glow-wide-{fid}" x="-100%" y="-100%" width="300%" height="300%">
        <feGaussianBlur stdDeviation="28" />
      </filter>

      <!-- Medium glow filter -->
      <filter id="glow-mid-{fid}" x="-60%" y="-60%" width="220%" height="220%">
        <feGaussianBlur stdDeviation="12" />
      </filter>

      <!-- Core tight glow filter -->
      <filter id="glow-core-{fid}" x="-40%" y="-40%" width="180%" height="180%">
        <feGaussianBlur stdDeviation="5" result="blur" />
        <feMerge>
          <feMergeNode in="blur" />
          <feMergeNode in="SourceGraphic" />
        </feMerge>
      </filter>
    </defs>

    {#if progress > 0.002}
      <!-- Layer 1: Wide ambient bloom -->
      <circle
        cx={center}
        cy={center}
        r={radius}
        fill="none"
        stroke="url(#ring-grad-{fid})"
        stroke-width={strokeWidth * 4}
        stroke-linecap="round"
        stroke-dasharray={circumference}
        stroke-dashoffset={dashOffset}
        filter="url(#glow-wide-{fid})"
        opacity="0.35"
        class="transition-[stroke-dashoffset] duration-1000 ease-linear"
      />

      <!-- Layer 2: Medium glow -->
      <circle
        cx={center}
        cy={center}
        r={radius}
        fill="none"
        stroke="url(#ring-grad-{fid})"
        stroke-width={strokeWidth * 2}
        stroke-linecap="round"
        stroke-dasharray={circumference}
        stroke-dashoffset={dashOffset}
        filter="url(#glow-mid-{fid})"
        opacity="0.5"
        class="transition-[stroke-dashoffset] duration-1000 ease-linear"
      />

      <!-- Layer 3: Core ring with tight glow -->
      <circle
        cx={center}
        cy={center}
        r={radius}
        fill="none"
        stroke="url(#ring-grad-{fid})"
        stroke-width={strokeWidth}
        stroke-linecap="round"
        stroke-dasharray={circumference}
        stroke-dashoffset={dashOffset}
        filter="url(#glow-core-{fid})"
        class="transition-[stroke-dashoffset] duration-1000 ease-linear"
      />
    {/if}
  </svg>

  <!-- Non-glow SVG -- exact size, draws the track + crisp ring -->
  <svg
    aria-hidden="true"
    width={size}
    height={size}
    class="absolute"
    style="transform: rotate(-90deg);"
  >
    <!-- Background track -->
    <circle
      cx={size / 2}
      cy={size / 2}
      r={radius}
      fill="none"
      stroke="#161616"
      stroke-width={strokeWidth}
    />

    {#if progress > 0.002}
      <!-- Sharp foreground ring (no filter) -->
      <circle
        cx={size / 2}
        cy={size / 2}
        r={radius}
        fill="none"
        stroke="url(#ring-grad-{fid})"
        stroke-width={strokeWidth}
        stroke-linecap="round"
        stroke-dasharray={circumference}
        stroke-dashoffset={dashOffset}
        class="transition-[stroke-dashoffset] duration-1000 ease-linear"
      />
    {/if}
  </svg>

  <!-- Content overlay -->
  <div class="absolute inset-0 flex flex-col items-center justify-center">
    {#if children}
      {@render children()}
    {/if}
  </div>
</div>
