import { useCallback, useEffect, useRef } from 'react';

import { WAVEFORM_CONSTANTS } from './WaveformConstants';

interface RecordStaticWaveformProps {
  audioBuffer: AudioBuffer | null;
  className?: string;
}

export const RecordStaticWaveform: React.FC<RecordStaticWaveformProps> = ({
  audioBuffer,
  className = '',
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const resizeObserverRef = useRef<ResizeObserver | null>(null);

  // Calculate responsive waveform dimensions based on container width
  const calculateWaveformDimensions = useCallback((containerWidth: number) => {
    const availableWidth = containerWidth - 40; // Leave some padding
    const minBarWidth = 1;
    const maxBarWidth = 3;
    const barGap = 3;

    // Calculate optimal bar count and width
    const maxBarsWithMinWidth = Math.floor(
      availableWidth / (minBarWidth + barGap)
    );
    const barCount = Math.min(maxBarsWithMinWidth, 160); // Cap at 160 for performance

    // Calculate actual bar width to fill available space
    const totalGaps = (barCount - 1) * barGap;
    const barWidth = Math.min(
      maxBarWidth,
      Math.max(minBarWidth, (availableWidth - totalGaps) / barCount)
    );

    return {
      barCount,
      barWidth,
      barGap,
      totalWidth: barCount * barWidth + (barCount - 1) * barGap,
    };
  }, []);

  const renderWaveform = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas || !audioBuffer) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const dpr = window.devicePixelRatio || 1;
    const rect = canvas.getBoundingClientRect();

    // Set canvas size
    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;
    ctx.scale(dpr, dpr);

    // Clear canvas
    ctx.clearRect(0, 0, rect.width, rect.height);

    // Get audio data from the first channel
    const audioData = audioBuffer.getChannelData(0);
    const samples = audioData.length;

    // Calculate responsive dimensions
    const dimensions = calculateWaveformDimensions(rect.width);
    const startX = (rect.width - dimensions.totalWidth) / 2;

    // Draw bars with responsive dimensions but static
    for (let i = 0; i < dimensions.barCount; i++) {
      const x = startX + i * (dimensions.barWidth + dimensions.barGap);

      // Determine base height based on position with responsive edge calculation
      const edgeRatio = 0.1; // 10% of bars on each edge
      const smallRatio = 0.2; // 20% of bars for small height
      const mediumRatio = 0.3; // 30% of bars for medium height

      const edgeCount = Math.floor(dimensions.barCount * edgeRatio);
      const smallCount = Math.floor(dimensions.barCount * smallRatio);
      const mediumCount = Math.floor(dimensions.barCount * mediumRatio);

      let baseHeight;
      if (i <= edgeCount || i >= dimensions.barCount - edgeCount) {
        baseHeight =
          WAVEFORM_CONSTANTS.MIN_HEIGHT +
          (WAVEFORM_CONSTANTS.MAX_HEIGHT - WAVEFORM_CONSTANTS.MIN_HEIGHT) * 0.2; // Very small edges
      } else if (i <= smallCount || i >= dimensions.barCount - smallCount) {
        baseHeight =
          WAVEFORM_CONSTANTS.MIN_HEIGHT +
          (WAVEFORM_CONSTANTS.MAX_HEIGHT - WAVEFORM_CONSTANTS.MIN_HEIGHT) * 0.5; // Small
      } else if (i <= mediumCount || i >= dimensions.barCount - mediumCount) {
        baseHeight =
          WAVEFORM_CONSTANTS.MIN_HEIGHT +
          (WAVEFORM_CONSTANTS.MAX_HEIGHT - WAVEFORM_CONSTANTS.MIN_HEIGHT) * 0.7; // Medium
      } else {
        baseHeight =
          WAVEFORM_CONSTANTS.MIN_HEIGHT +
          (WAVEFORM_CONSTANTS.MAX_HEIGHT - WAVEFORM_CONSTANTS.MIN_HEIGHT) * 1.0; // Large center
      }

      // Sample the audio data for this bar
      const audioIndex = Math.floor((i / dimensions.barCount) * samples);
      const samplesPerBar = Math.floor(samples / dimensions.barCount);

      // Find the maximum amplitude in this bar's section
      let maxAmplitude = 0;
      const startSample = Math.max(0, audioIndex - samplesPerBar / 2);
      const endSample = Math.min(samples, audioIndex + samplesPerBar / 2);

      for (let j = startSample; j < endSample; j++) {
        const amplitude = Math.abs(audioData[j]);
        if (amplitude > maxAmplitude) {
          maxAmplitude = amplitude;
        }
      }

      // Scale the height based on audio data (similar to live version but static)
      const audioMultiplier = 0.3 + maxAmplitude * 2.0; // Less dramatic than live version
      const height = Math.max(
        WAVEFORM_CONSTANTS.MIN_HEIGHT,
        baseHeight * audioMultiplier
      );
      const y = (rect.height - height) / 2;

      // Use white color for static waveform
      ctx.fillStyle = WAVEFORM_CONSTANTS.STATIC_BAR_COLOR;
      ctx.globalAlpha = 0.8; // Slightly transparent for a clean look
      ctx.fillRect(x, y, dimensions.barWidth, height);
    }

    ctx.globalAlpha = 1;
  }, [audioBuffer, calculateWaveformDimensions]);

  useEffect(() => {
    renderWaveform();

    // Set up ResizeObserver to handle container size changes
    const canvas = canvasRef.current;
    if (canvas && !resizeObserverRef.current) {
      resizeObserverRef.current = new ResizeObserver(() => {
        renderWaveform();
      });
      resizeObserverRef.current.observe(canvas);
    }

    return () => {
      if (resizeObserverRef.current) {
        resizeObserverRef.current.disconnect();
        resizeObserverRef.current = null;
      }
    };
  }, [renderWaveform]);

  return (
    <canvas
      ref={canvasRef}
      className={`h-8 w-full ${className}`}
      style={{ imageRendering: 'pixelated' }}
    />
  );
};
