'use client';

import * as React from 'react';
import { cn } from '@/lib/utils/cn';

export interface LUFSMeterProps {
  analyserNode: AnalyserNode | null;
  className?: string;
}

export function LUFSMeter({ analyserNode, className }: LUFSMeterProps) {
  const canvasRef = React.useRef<HTMLCanvasElement>(null);
  const animationFrameRef = React.useRef<number | undefined>(undefined);
  const [lufs, setLufs] = React.useState({ integrated: -23, shortTerm: -23, momentary: -23 });
  const lufsHistoryRef = React.useRef<number[]>([]);

  React.useEffect(() => {
    if (!analyserNode || !canvasRef.current) return;

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

    // Set canvas size
    const dpr = window.devicePixelRatio || 1;
    const rect = canvas.getBoundingClientRect();
    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;
    ctx.scale(dpr, dpr);

    const bufferLength = analyserNode.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);

    const draw = () => {
      animationFrameRef.current = requestAnimationFrame(draw);

      analyserNode.getByteFrequencyData(dataArray);

      // Calculate RMS from frequency data
      let sum = 0;
      for (let i = 0; i < bufferLength; i++) {
        const normalized = dataArray[i] / 255;
        sum += normalized * normalized;
      }
      const rms = Math.sqrt(sum / bufferLength);

      // Convert to LUFS approximation (simplified K-weighting)
      // Real LUFS requires proper K-weighting filter, this is an approximation
      let lufsValue = -23; // Silence baseline
      if (rms > 0.0001) {
        lufsValue = 20 * Math.log10(rms) - 0.691; // Simplified LUFS estimation
        lufsValue = Math.max(-70, Math.min(0, lufsValue));
      }

      // Store history for integrated measurement
      lufsHistoryRef.current.push(lufsValue);
      if (lufsHistoryRef.current.length > 300) { // Keep last 10 seconds at 30fps
        lufsHistoryRef.current.shift();
      }

      // Calculate measurements
      const momentary = lufsValue; // Current value
      const shortTerm = lufsHistoryRef.current.slice(-90).reduce((a, b) => a + b, 0) / Math.min(90, lufsHistoryRef.current.length); // Last 3 seconds
      const integrated = lufsHistoryRef.current.reduce((a, b) => a + b, 0) / lufsHistoryRef.current.length; // All time

      setLufs({ integrated, shortTerm, momentary });

      // Clear canvas
      const bgColor = getComputedStyle(canvas.parentElement!).backgroundColor;
      ctx.fillStyle = bgColor;
      ctx.fillRect(0, 0, rect.width, rect.height);

      // Draw LUFS scale (-70 to 0)
      const lufsToY = (lufs: number) => {
        return ((0 - lufs) / 70) * rect.height;
      };

      // Draw reference lines
      ctx.strokeStyle = 'rgba(128, 128, 128, 0.2)';
      ctx.lineWidth = 1;
      [-23, -16, -9, -3].forEach(db => {
        const y = lufsToY(db);
        ctx.beginPath();
        ctx.moveTo(0, y);
        ctx.lineTo(rect.width, y);
        ctx.stroke();

        // Labels
        ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
        ctx.font = '9px monospace';
        ctx.textAlign = 'right';
        ctx.fillText(`${db}`, rect.width - 2, y - 2);
      });

      // Draw -23 LUFS broadcast standard line
      ctx.strokeStyle = 'rgba(59, 130, 246, 0.5)';
      ctx.lineWidth = 2;
      const standardY = lufsToY(-23);
      ctx.beginPath();
      ctx.moveTo(0, standardY);
      ctx.lineTo(rect.width, standardY);
      ctx.stroke();

      // Draw bars
      const barWidth = rect.width / 4;
      const drawBar = (value: number, x: number, color: string, label: string) => {
        const y = lufsToY(value);
        const height = rect.height - y;

        ctx.fillStyle = color;
        ctx.fillRect(x, y, barWidth - 4, height);

        // Label
        ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
        ctx.font = 'bold 9px monospace';
        ctx.textAlign = 'center';
        ctx.fillText(label, x + barWidth / 2 - 2, rect.height - 2);
      };

      drawBar(momentary, 0, 'rgba(239, 68, 68, 0.7)', 'M');
      drawBar(shortTerm, barWidth, 'rgba(251, 146, 60, 0.7)', 'S');
      drawBar(integrated, barWidth * 2, 'rgba(34, 197, 94, 0.7)', 'I');
    };

    draw();

    return () => {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }
    };
  }, [analyserNode]);

  return (
    <div className={cn('w-full h-full bg-card/50 border-2 border-accent/50 rounded-lg p-2', className)}>
      <div className="text-[10px] font-bold text-accent uppercase tracking-wider mb-2">
        LUFS Loudness
      </div>
      <div className="w-full h-[calc(100%-24px)] rounded bg-muted/30 flex flex-col">
        <canvas
          ref={canvasRef}
          className="w-full flex-1 rounded"
        />
        <div className="grid grid-cols-3 gap-1 mt-2 text-[9px] font-mono text-center">
          <div>
            <div className="text-muted-foreground">Momentary</div>
            <div className={cn('font-bold', lufs.momentary > -9 ? 'text-red-500' : 'text-foreground')}>
              {lufs.momentary > -70 ? lufs.momentary.toFixed(1) : '-∞'}
            </div>
          </div>
          <div>
            <div className="text-muted-foreground">Short-term</div>
            <div className={cn('font-bold', lufs.shortTerm > -16 ? 'text-orange-500' : 'text-foreground')}>
              {lufs.shortTerm > -70 ? lufs.shortTerm.toFixed(1) : '-∞'}
            </div>
          </div>
          <div>
            <div className="text-muted-foreground">Integrated</div>
            <div className={cn('font-bold', Math.abs(lufs.integrated + 23) < 2 ? 'text-green-500' : 'text-foreground')}>
              {lufs.integrated > -70 ? lufs.integrated.toFixed(1) : '-∞'}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
