import React, { useRef, useEffect, useState, useCallback } from 'react';
import { InstrumentLayer } from '../utils/types';
import AnimatedGradient from './AnimatedGradient';

interface LayerWaveformProps {
  layer: InstrumentLayer;
  width?: number;
  height?: number;
  currentTime?: number; // Current playback time in seconds
  isPlaying?: boolean;
  onSeek?: (time: number) => void; // Callback when user clicks to seek
}

const LayerWaveform: React.FC<LayerWaveformProps> = ({
  layer,
  width: propWidth,
  height = 60,
  currentTime = 0,
  isPlaying = false,
  onSeek
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [isHovering, setIsHovering] = useState(false);
  const [hoverTime, setHoverTime] = useState(0);
  const [width, setWidth] = useState(propWidth || 800);

  // Measure container width for responsive sizing
  useEffect(() => {
    const updateWidth = () => {
      if (containerRef.current) {
        const containerWidth = containerRef.current.offsetWidth;
        setWidth(propWidth || containerWidth || 800);
      }
    };

    updateWidth();
    window.addEventListener('resize', updateWidth);
    return () => window.removeEventListener('resize', updateWidth);
  }, [propWidth]);

  // Draw the waveform
  const drawWaveform = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

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

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

    // Skip if no waveform data (handled by component render logic)
    if (!layer.waveformData || layer.waveformData.length === 0) {
      return;
    }

    drawWaveformPath(ctx);
    drawProgressIndicator(ctx);
    
    if (isHovering) {
      drawHoverIndicator(ctx);
    }
  }, [layer.waveformData, width, height, currentTime, isHovering, hoverTime]);



  const drawWaveformPath = (ctx: CanvasRenderingContext2D) => {
    if (!layer.waveformData) return;

    const peaks = layer.waveformData;
    const gradient = ctx.createLinearGradient(0, 0, 0, height);
    
    // Unified blue gradient theme
    gradient.addColorStop(0, '#3B82F6'); // Blue-500
    gradient.addColorStop(0.5, '#60A5FA'); // Blue-400
    gradient.addColorStop(1, '#93C5FD'); // Blue-300

    ctx.fillStyle = gradient;
    
    // Enable smooth rendering
    ctx.imageSmoothingEnabled = true;
    ctx.imageSmoothingQuality = 'high';

    // Calculate bar width to fill the full width with no gaps
    const barWidth = width / peaks.length;

    // Draw waveform as vertical bars
    for (let i = 0; i < peaks.length; i++) {
      const x = i * barWidth;
      const amplitude = peaks[i] * height * 0.85; // 85% of full height
      const barHeight = Math.max(1, amplitude); // Minimum bar height
      const y = (height - barHeight) / 2;
      
      // Draw crisp rectangle (no rounding for sharper edges)
      ctx.fillRect(Math.round(x), Math.round(y), Math.ceil(barWidth), Math.round(barHeight));
    }
  };

  const drawProgressIndicator = (ctx: CanvasRenderingContext2D) => {
    if (!layer.metadata.duration || currentTime <= 0) return;

    const progressX = (currentTime / layer.metadata.duration) * width;
    
    // Draw progress line
    ctx.strokeStyle = '#EF4444'; // Red-500
    ctx.lineWidth = 2;
    ctx.setLineDash([]);
    
    ctx.beginPath();
    ctx.moveTo(progressX, 0);
    ctx.lineTo(progressX, height);
    ctx.stroke();

    // Draw small circle at top of progress line
    ctx.fillStyle = '#EF4444';
    ctx.beginPath();
    ctx.arc(progressX, 4, 3, 0, 2 * Math.PI);
    ctx.fill();
  };

  const drawHoverIndicator = (ctx: CanvasRenderingContext2D) => {
    if (!layer.metadata.duration) return;

    const hoverX = (hoverTime / layer.metadata.duration) * width;
    
    // Draw hover line
    ctx.strokeStyle = '#6B7280'; // Gray-500
    ctx.lineWidth = 1;
    ctx.setLineDash([4, 4]);
    
    ctx.beginPath();
    ctx.moveTo(hoverX, 0);
    ctx.lineTo(hoverX, height);
    ctx.stroke();
    ctx.setLineDash([]);
  };

  const handleMouseMove = (event: React.MouseEvent<HTMLCanvasElement>) => {
    if (!layer.metadata.duration) return;

    const canvas = canvasRef.current;
    if (!canvas) return;

    const rect = canvas.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const time = (x / width) * layer.metadata.duration;
    
    setHoverTime(Math.max(0, Math.min(time, layer.metadata.duration)));
  };

  const handleClick = (event: React.MouseEvent<HTMLCanvasElement>) => {
    if (!onSeek || !layer.metadata.duration) return;

    const canvas = canvasRef.current;
    if (!canvas) return;

    const rect = canvas.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const time = (x / width) * layer.metadata.duration;
    
    onSeek(Math.max(0, Math.min(time, layer.metadata.duration)));
  };

  const formatTime = (seconds: number): string => {
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  };

  // Redraw when dependencies change
  useEffect(() => {
    drawWaveform();
  }, [drawWaveform]);

  // Handle canvas scaling for high-DPI displays
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

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

    const devicePixelRatio = window.devicePixelRatio || 1;
    const displayWidth = width;
    const displayHeight = height;
    
    // Set actual canvas size in memory (scaled for high DPI)
    canvas.width = displayWidth * devicePixelRatio;
    canvas.height = displayHeight * devicePixelRatio;
    
    // Scale CSS size back down
    canvas.style.width = `${displayWidth}px`;
    canvas.style.height = `${displayHeight}px`;
    
    // Scale the drawing context so everything draws at high DPI
    ctx.scale(devicePixelRatio, devicePixelRatio);
    
    // Set anti-aliasing for crisp edges
    ctx.imageSmoothingEnabled = false; // Disable for pixel-perfect bars
    
    drawWaveform();
  }, [width, height, drawWaveform]);

  return (
    <div ref={containerRef} className="relative w-full">
      {/* Show animated gradient for loading states */}
      {(!layer.waveformData || layer.waveformData.length === 0) && layer.status !== 'error' ? (
        <div className="w-full rounded" style={{ height: `${height}px` }}>
          <AnimatedGradient className="rounded" />
        </div>
      ) : (
        <canvas
          ref={canvasRef}
          className="cursor-pointer rounded w-full"
          onMouseMove={handleMouseMove}
          onMouseEnter={() => setIsHovering(true)}
          onMouseLeave={() => setIsHovering(false)}
          onClick={handleClick}
        />
      )}
      
      {/* Hover tooltip */}
      {isHovering && layer.metadata.duration && (
        <div className="absolute -top-8 left-0 bg-slate-800 text-white text-xs px-2 py-1 rounded pointer-events-none"
             style={{ left: `${(hoverTime / layer.metadata.duration) * width}px`, transform: 'translateX(-50%)' }}>
          {formatTime(hoverTime)}
        </div>
      )}
      
      {/* Error overlay */}
      {layer.status === 'error' && (
        <div className="absolute inset-0 bg-white bg-opacity-90 flex items-center justify-center rounded">
          <span className="text-red-600">Error loading audio</span>
        </div>
      )}
    </div>
  );
};

export default LayerWaveform;