'use client';

import { useEffect, useRef } from 'react';
interface WaveformProps {
  buffer: AudioBuffer;
  /** Offset into the source buffer in seconds */
  sourceIn: number;
  /** Duration to display in seconds */
  duration: number;
  /** Height of canvas in px */
  height: number;
  color?: string;
}

/**
 * Draws a real waveform from AudioBuffer channel data using the canvas 2D API.
 * Resizes with ResizeObserver and re-renders on dimension or buffer changes.
 */
export function Waveform({
  buffer,
  sourceIn,
  duration,
  height,
  color = '#ff8a3d',
}: WaveformProps) {
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const containerRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    const container = containerRef.current;
    if (!canvas || !container) return;

    let cancelled = false;

    function render() {
      if (cancelled) return;
      const dpr = window.devicePixelRatio || 1;
      const cssWidth = container?.clientWidth ?? 0;
      const cssHeight = height;
      canvas!.style.width = `${cssWidth}px`;
      canvas!.style.height = `${cssHeight}px`;
      canvas!.width = Math.max(1, Math.floor(cssWidth * dpr));
      canvas!.height = Math.max(1, Math.floor(cssHeight * dpr));

      const ctx = canvas!.getContext('2d');
      if (!ctx) return;
      ctx.scale(dpr, dpr);
      ctx.clearRect(0, 0, cssWidth, cssHeight);

      // Compute peaks for the visible slice of buffer
      const sampleRate = buffer.sampleRate;
      const startSample = Math.max(0, Math.floor(sourceIn * sampleRate));
      const endSample = Math.min(buffer.length, Math.floor((sourceIn + duration) * sampleRate));
      const sliceLen = Math.max(1, endSample - startSample);
      const samplesPerPixel = Math.max(1, Math.floor(sliceLen / cssWidth));

      const channel = buffer.getChannelData(0);
      ctx.fillStyle = color;
      const mid = cssHeight / 2;

      for (let x = 0; x < cssWidth; x++) {
        let min = 1.0;
        let max = -1.0;
        const s = startSample + x * samplesPerPixel;
        const e = Math.min(endSample, s + samplesPerPixel);
        for (let i = s; i < e; i++) {
          const v = channel[i];
          if (v < min) min = v;
          if (v > max) max = v;
        }
        if (min === 1.0) min = 0;
        if (max === -1.0) max = 0;
        const y1 = mid - max * (mid - 1);
        const y2 = mid - min * (mid - 1);
        ctx.fillRect(x, y1, 1, Math.max(1, y2 - y1));
      }

      // Center line
      ctx.fillStyle = 'rgba(255,255,255,0.08)';
      ctx.fillRect(0, mid, cssWidth, 1);
    }

    render();
    const ro = new ResizeObserver(render);
    ro.observe(container);
    return () => {
      cancelled = true;
      ro.disconnect();
    };
  }, [buffer, sourceIn, duration, height, color]);

  return (
    <div ref={containerRef} className="w-full h-full">
      <canvas ref={canvasRef} className="block w-full h-full" />
    </div>
  );
}