'use client';

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

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

export function PhaseCorrelationMeter({ analyserNode, className }: PhaseCorrelationMeterProps) {
  const canvasRef = React.useRef<HTMLCanvasElement>(null);
  const animationFrameRef = React.useRef<number | undefined>(undefined);
  const [correlation, setCorrelation] = React.useState(0);

  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 audioContext = analyserNode.context as AudioContext;
    const bufferLength = analyserNode.fftSize;
    const dataArrayL = new Float32Array(bufferLength);
    const dataArrayR = new Float32Array(bufferLength);

    // Create a splitter to get L/R channels
    const splitter = audioContext.createChannelSplitter(2);
    const analyserL = audioContext.createAnalyser();
    const analyserR = audioContext.createAnalyser();

    analyserL.fftSize = bufferLength;
    analyserR.fftSize = bufferLength;

    // Try to connect to the analyser node's source
    // Note: This is a simplified approach - ideally we'd get the source node
    try {
      analyserNode.connect(splitter);
      splitter.connect(analyserL, 0);
      splitter.connect(analyserR, 1);
    } catch (e) {
      // If connection fails, just show static display
    }

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

      try {
        analyserL.getFloatTimeDomainData(dataArrayL);
        analyserR.getFloatTimeDomainData(dataArrayR);

        // Calculate phase correlation (Pearson correlation coefficient)
        let sumL = 0, sumR = 0, sumLR = 0, sumL2 = 0, sumR2 = 0;
        const n = bufferLength;

        for (let i = 0; i < n; i++) {
          sumL += dataArrayL[i];
          sumR += dataArrayR[i];
          sumLR += dataArrayL[i] * dataArrayR[i];
          sumL2 += dataArrayL[i] * dataArrayL[i];
          sumR2 += dataArrayR[i] * dataArrayR[i];
        }

        const meanL = sumL / n;
        const meanR = sumR / n;
        const covLR = (sumLR / n) - (meanL * meanR);
        const varL = (sumL2 / n) - (meanL * meanL);
        const varR = (sumR2 / n) - (meanR * meanR);

        let r = 0;
        if (varL > 0 && varR > 0) {
          r = covLR / Math.sqrt(varL * varR);
          r = Math.max(-1, Math.min(1, r)); // Clamp to [-1, 1]
        }

        setCorrelation(r);

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

        // Draw scale background
        const centerY = rect.height / 2;
        const barHeight = 20;

        // Draw scale markers
        ctx.fillStyle = 'rgba(128, 128, 128, 0.2)';
        ctx.fillRect(0, centerY - barHeight / 2, rect.width, barHeight);

        // Draw center line (0)
        ctx.strokeStyle = 'rgba(128, 128, 128, 0.5)';
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(rect.width / 2, centerY - barHeight / 2 - 5);
        ctx.lineTo(rect.width / 2, centerY + barHeight / 2 + 5);
        ctx.stroke();

        // Draw correlation indicator
        const x = ((r + 1) / 2) * rect.width;

        // Color based on correlation value
        let color;
        if (r > 0.9) {
          color = '#10b981'; // Green - good correlation (mono-ish)
        } else if (r > 0.5) {
          color = '#84cc16'; // Lime - moderate correlation
        } else if (r > -0.5) {
          color = '#eab308'; // Yellow - decorrelated (good stereo)
        } else if (r > -0.9) {
          color = '#f97316'; // Orange - negative correlation
        } else {
          color = '#ef4444'; // Red - phase issues
        }

        ctx.fillStyle = color;
        ctx.fillRect(x - 2, centerY - barHeight / 2, 4, barHeight);

        // Draw labels
        ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
        ctx.font = '9px monospace';
        ctx.textAlign = 'left';
        ctx.fillText('-1', 2, centerY - barHeight / 2 - 8);
        ctx.textAlign = 'center';
        ctx.fillText('0', rect.width / 2, centerY - barHeight / 2 - 8);
        ctx.textAlign = 'right';
        ctx.fillText('+1', rect.width - 2, centerY - barHeight / 2 - 8);

        // Draw correlation value
        ctx.textAlign = 'center';
        ctx.font = 'bold 11px monospace';
        ctx.fillText(r.toFixed(3), rect.width / 2, centerY + barHeight / 2 + 15);
      } catch (e) {
        // Silently handle errors
      }
    };

    draw();

    return () => {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }
      try {
        splitter.disconnect();
        analyserL.disconnect();
        analyserR.disconnect();
      } catch (e) {
        // Ignore disconnection errors
      }
    };
  }, [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">
        Phase Correlation
      </div>
      <div className="w-full h-[calc(100%-24px)] rounded bg-muted/30 flex flex-col items-center justify-center">
        <canvas
          ref={canvasRef}
          className="w-full h-16 rounded"
        />
        <div className="text-[9px] text-muted-foreground mt-2 text-center px-2">
          {correlation > 0.9 ? 'Mono-like' :
           correlation > 0.5 ? 'Good Stereo' :
           correlation > -0.5 ? 'Wide Stereo' :
           'Phase Issues'}
        </div>
      </div>
    </div>
  );
}
