<script lang="ts">
  import type { HistogramData } from "../lib/types";

  let {
    data,
    unit = "tokens/sec",
    colorClass = "text-blue-500 dark:text-blue-400",
  }: {
    data: HistogramData;
    unit?: string;
    colorClass?: string;
  } = $props();

  const height = 250;
  const padding = { top: 30, right: 20, bottom: 40, left: 75 };
  const viewBoxWidth = 1200;
  const chartWidth = viewBoxWidth - padding.left - padding.right;
  const chartHeight = height - padding.top - padding.bottom;

  let maxCount = $derived(Math.max(...data.bins));
  let barWidth = $derived(chartWidth / data.bins.length);
  let range = $derived(data.max - data.min);

  function getXPosition(value: number): number {
    return padding.left + ((value - data.min) / range) * chartWidth;
  }
</script>

<div class="mt-2 w-full">
  <svg viewBox="0 0 {viewBoxWidth} {height}" class="w-full h-auto" preserveAspectRatio="xMidYMid meet">
    <!-- Y-axis -->
    <line
      x1={padding.left}
      y1={padding.top}
      x2={padding.left}
      y2={height - padding.bottom}
      stroke="currentColor"
      stroke-width="1"
      opacity="0.3"
    />

    <!-- Y-axis ticks and labels -->
    {#each [0, 0.5, 1] as fraction}
      {@const tickCount = Math.round(maxCount * fraction)}
      {@const tickY = height - padding.bottom - fraction * chartHeight}
      <line
        x1={padding.left - 8}
        y1={tickY}
        x2={padding.left}
        y2={tickY}
        stroke="currentColor"
        stroke-width="1"
        opacity="0.4"
      />
      <text x={padding.left - 10} y={tickY + 10} font-size="26" fill="currentColor" opacity="0.8" text-anchor="end">
        {tickCount}
      </text>
    {/each}

    <!-- X-axis -->
    <line
      x1={padding.left}
      y1={height - padding.bottom}
      x2={viewBoxWidth - padding.right}
      y2={height - padding.bottom}
      stroke="currentColor"
      stroke-width="1"
      opacity="0.3"
    />

    <!-- Histogram bars -->
    {#each data.bins as count, i}
      {@const barHeight = maxCount > 0 ? (count / maxCount) * chartHeight : 0}
      {@const x = padding.left + i * barWidth}
      {@const y = height - padding.bottom - barHeight}
      {@const binStart = data.min + i * data.binSize}
      {@const binEnd = binStart + data.binSize}
      <g>
        <rect
          {x}
          {y}
          width={Math.max(barWidth - 1, 1)}
          height={barHeight}
          fill="currentColor"
          opacity="0.6"
          class="{colorClass} hover:opacity-90 transition-opacity cursor-pointer"
        />
        <title>{`${binStart.toFixed(1)} - ${binEnd.toFixed(1)} ${unit}\nCount: ${count}`}</title>
      </g>
    {/each}

    <!-- Percentile lines -->
    <line
      x1={getXPosition(data.p50)}
      y1={padding.top}
      x2={getXPosition(data.p50)}
      y2={height - padding.bottom}
      stroke="currentColor"
      stroke-width="2"
      stroke-dasharray="4 2"
      opacity="0.7"
      class="text-gray-600 dark:text-gray-400"
    />

    <line
      x1={getXPosition(data.p95)}
      y1={padding.top}
      x2={getXPosition(data.p95)}
      y2={height - padding.bottom}
      stroke="currentColor"
      stroke-width="2"
      stroke-dasharray="4 2"
      opacity="0.7"
      class="text-orange-500 dark:text-orange-400"
    />

    <line
      x1={getXPosition(data.p99)}
      y1={padding.top}
      x2={getXPosition(data.p99)}
      y2={height - padding.bottom}
      stroke="currentColor"
      stroke-width="2"
      stroke-dasharray="4 2"
      opacity="0.7"
      class="text-green-500 dark:text-green-400"
    />

    <!-- X-axis labels -->
    <text x={padding.left} y={height - 8} font-size="26" fill="currentColor" opacity="0.8" text-anchor="start">
      {data.min.toFixed(1)}
    </text>

    <text
      x={viewBoxWidth - padding.right}
      y={height - 8}
      font-size="26"
      fill="currentColor"
      opacity="0.8"
      text-anchor="end"
    >
      {data.max.toFixed(1)}
    </text>
  </svg>
</div>
