'use client';

import * as React from 'react';
import { Modal } from '@/components/ui/Modal';
import { Button } from '@/components/ui/Button';
import { Slider } from '@/components/ui/Slider';
import { cn } from '@/lib/utils/cn';
import type { FilterType } from '@/lib/audio/effects/filters';

export interface FilterParameters {
  type: FilterType;
  frequency: number;
  Q?: number;
  gain?: number;
}

export interface EffectPreset {
  name: string;
  parameters: Partial<FilterParameters>;
}

export interface EffectParameterDialogProps {
  open: boolean;
  onClose: () => void;
  effectType: 'lowpass' | 'highpass' | 'bandpass' | 'notch' | 'lowshelf' | 'highshelf' | 'peaking';
  onApply: (params: FilterParameters) => void;
  sampleRate?: number;
}

const EFFECT_LABELS: Record<string, string> = {
  lowpass: 'Low-Pass Filter',
  highpass: 'High-Pass Filter',
  bandpass: 'Band-Pass Filter',
  notch: 'Notch Filter',
  lowshelf: 'Low Shelf Filter',
  highshelf: 'High Shelf Filter',
  peaking: 'Peaking EQ',
};

const EFFECT_DESCRIPTIONS: Record<string, string> = {
  lowpass: 'Removes high frequencies above the cutoff',
  highpass: 'Removes low frequencies below the cutoff',
  bandpass: 'Isolates frequencies around the center frequency',
  notch: 'Removes frequencies around the center frequency',
  lowshelf: 'Boosts or cuts low frequencies',
  highshelf: 'Boosts or cuts high frequencies',
  peaking: 'Boosts or cuts a specific frequency band',
};

const PRESETS: Record<string, EffectPreset[]> = {
  lowpass: [
    { name: 'Telephone', parameters: { frequency: 3000, Q: 0.7 } },
    { name: 'Radio', parameters: { frequency: 5000, Q: 1.0 } },
    { name: 'Warm', parameters: { frequency: 8000, Q: 0.5 } },
    { name: 'Muffled', parameters: { frequency: 1000, Q: 1.5 } },
  ],
  highpass: [
    { name: 'Rumble Removal', parameters: { frequency: 80, Q: 0.7 } },
    { name: 'Voice Clarity', parameters: { frequency: 150, Q: 1.0 } },
    { name: 'Thin', parameters: { frequency: 300, Q: 0.5 } },
  ],
  bandpass: [
    { name: 'Telephone', parameters: { frequency: 1000, Q: 2.0 } },
    { name: 'Vocal Range', parameters: { frequency: 2000, Q: 1.0 } },
    { name: 'Narrow', parameters: { frequency: 1000, Q: 10.0 } },
  ],
  notch: [
    { name: '60Hz Hum', parameters: { frequency: 60, Q: 10.0 } },
    { name: '50Hz Hum', parameters: { frequency: 50, Q: 10.0 } },
    { name: 'Narrow Notch', parameters: { frequency: 1000, Q: 20.0 } },
  ],
  lowshelf: [
    { name: 'Bass Boost', parameters: { frequency: 200, gain: 6 } },
    { name: 'Bass Cut', parameters: { frequency: 200, gain: -6 } },
    { name: 'Warmth', parameters: { frequency: 150, gain: 3 } },
  ],
  highshelf: [
    { name: 'Treble Boost', parameters: { frequency: 3000, gain: 6 } },
    { name: 'Treble Cut', parameters: { frequency: 3000, gain: -6 } },
    { name: 'Brightness', parameters: { frequency: 5000, gain: 3 } },
  ],
  peaking: [
    { name: 'Presence Boost', parameters: { frequency: 3000, Q: 1.0, gain: 4 } },
    { name: 'Vocal Cut', parameters: { frequency: 2000, Q: 2.0, gain: -3 } },
    { name: 'Narrow Boost', parameters: { frequency: 1000, Q: 5.0, gain: 6 } },
  ],
};

export function EffectParameterDialog({
  open,
  onClose,
  effectType,
  onApply,
  sampleRate = 48000,
}: EffectParameterDialogProps) {
  const [parameters, setParameters] = React.useState<FilterParameters>(() => ({
    type: effectType,
    frequency: effectType === 'lowpass' ? 1000 : effectType === 'highpass' ? 100 : 1000,
    Q: 1.0,
    gain: 0,
  }));

  const canvasRef = React.useRef<HTMLCanvasElement>(null);

  // Get appropriate presets for this effect type
  const presets = PRESETS[effectType] || [];

  // Update parameters when effect type changes
  React.useEffect(() => {
    setParameters((prev) => ({ ...prev, type: effectType }));
  }, [effectType]);

  // Draw frequency response curve
  React.useEffect(() => {
    if (!canvasRef.current) return;

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

    // Get actual dimensions
    const rect = canvas.getBoundingClientRect();
    const dpr = window.devicePixelRatio || 1;

    // Set actual size in memory (scaled to account for extra pixel density)
    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;

    // Normalize coordinate system to use CSS pixels
    ctx.scale(dpr, dpr);

    const width = rect.width;
    const height = rect.height;
    const nyquist = sampleRate / 2;

    // Clear canvas
    ctx.fillStyle = getComputedStyle(canvas).getPropertyValue('background-color') || '#1a1a1a';
    ctx.fillRect(0, 0, width, height);

    // Draw grid
    ctx.strokeStyle = 'rgba(128, 128, 128, 0.2)';
    ctx.lineWidth = 1;

    // Horizontal grid lines (dB)
    for (let db = -24; db <= 24; db += 6) {
      const y = height / 2 - (db / 24) * (height / 2);
      ctx.beginPath();
      ctx.moveTo(0, y);
      ctx.lineTo(width, y);
      ctx.stroke();
    }

    // Vertical grid lines (frequency)
    const frequencies = [100, 1000, 10000];
    frequencies.forEach((freq) => {
      const x = (Math.log10(freq) - 1) / (Math.log10(nyquist) - 1) * width;
      ctx.beginPath();
      ctx.moveTo(x, 0);
      ctx.lineTo(x, height);
      ctx.stroke();
    });

    // Draw frequency response curve
    ctx.strokeStyle = '#3b82f6'; // Primary blue
    ctx.lineWidth = 2;
    ctx.beginPath();

    for (let x = 0; x < width; x++) {
      const freq = Math.pow(10, 1 + (x / width) * (Math.log10(nyquist) - 1));
      const magnitude = getFilterMagnitude(freq, parameters, sampleRate);
      const db = 20 * Math.log10(Math.max(magnitude, 0.0001)); // Prevent log(0)
      const y = height / 2 - (db / 24) * (height / 2);

      if (x === 0) {
        ctx.moveTo(x, y);
      } else {
        ctx.lineTo(x, y);
      }
    }

    ctx.stroke();

    // Draw 0dB line
    ctx.strokeStyle = 'rgba(156, 163, 175, 0.5)'; // Muted foreground
    ctx.lineWidth = 1;
    ctx.setLineDash([5, 5]);
    ctx.beginPath();
    ctx.moveTo(0, height / 2);
    ctx.lineTo(width, height / 2);
    ctx.stroke();
    ctx.setLineDash([]);

  }, [parameters, sampleRate]);

  const handleApply = () => {
    onApply(parameters);
    onClose();
  };

  const handlePresetClick = (preset: EffectPreset) => {
    setParameters((prev) => ({
      ...prev,
      ...preset.parameters,
    }));
  };

  const needsQ = ['lowpass', 'highpass', 'bandpass', 'notch', 'peaking'].includes(effectType);
  const needsGain = ['lowshelf', 'highshelf', 'peaking'].includes(effectType);

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={EFFECT_LABELS[effectType] || 'Effect Parameters'}
      description={EFFECT_DESCRIPTIONS[effectType]}
      size="lg"
      footer={
        <>
          <Button variant="outline" onClick={onClose}>
            Cancel
          </Button>
          <Button onClick={handleApply}>
            Apply Effect
          </Button>
        </>
      }
    >
      <div className="space-y-4">
        {/* Frequency Response Visualization */}
        <div className="space-y-2">
          <label className="text-sm font-medium text-foreground">
            Frequency Response
          </label>
          <canvas
            ref={canvasRef}
            className="w-full h-48 border border-border rounded bg-background"
          />
          <div className="flex justify-between text-xs text-muted-foreground px-2">
            <span>100 Hz</span>
            <span>1 kHz</span>
            <span>10 kHz</span>
          </div>
        </div>

        {/* Presets */}
        {presets.length > 0 && (
          <div className="space-y-2">
            <label className="text-sm font-medium text-foreground">
              Presets
            </label>
            <div className="grid grid-cols-2 gap-2">
              {presets.map((preset) => (
                <Button
                  key={preset.name}
                  variant="outline"
                  size="sm"
                  onClick={() => handlePresetClick(preset)}
                  className="justify-start"
                >
                  {preset.name}
                </Button>
              ))}
            </div>
          </div>
        )}

        {/* Frequency Parameter */}
        <div className="space-y-2">
          <label className="text-sm font-medium text-foreground flex justify-between">
            <span>Frequency</span>
            <span className="text-muted-foreground font-mono">
              {parameters.frequency.toFixed(0)} Hz
            </span>
          </label>
          <Slider
            value={[Math.log10(parameters.frequency)]}
            onValueChange={([value]) =>
              setParameters((prev) => ({ ...prev, frequency: Math.pow(10, value) }))
            }
            min={1}
            max={Math.log10(sampleRate / 2)}
            step={0.01}
            className="w-full"
          />
          <div className="flex justify-between text-xs text-muted-foreground">
            <span>10 Hz</span>
            <span>{(sampleRate / 2).toFixed(0)} Hz</span>
          </div>
        </div>

        {/* Q Parameter */}
        {needsQ && (
          <div className="space-y-2">
            <label className="text-sm font-medium text-foreground flex justify-between">
              <span>Q (Resonance)</span>
              <span className="text-muted-foreground font-mono">
                {parameters.Q?.toFixed(2)}
              </span>
            </label>
            <Slider
              value={[parameters.Q || 1.0]}
              onValueChange={([value]) =>
                setParameters((prev) => ({ ...prev, Q: value }))
              }
              min={0.1}
              max={20}
              step={0.1}
              className="w-full"
            />
            <div className="flex justify-between text-xs text-muted-foreground">
              <span>0.1 (Gentle)</span>
              <span>20 (Sharp)</span>
            </div>
          </div>
        )}

        {/* Gain Parameter */}
        {needsGain && (
          <div className="space-y-2">
            <label className="text-sm font-medium text-foreground flex justify-between">
              <span>Gain</span>
              <span className="text-muted-foreground font-mono">
                {parameters.gain && parameters.gain > 0 ? '+' : ''}
                {parameters.gain?.toFixed(1)} dB
              </span>
            </label>
            <Slider
              value={[parameters.gain || 0]}
              onValueChange={([value]) =>
                setParameters((prev) => ({ ...prev, gain: value }))
              }
              min={-24}
              max={24}
              step={0.5}
              className="w-full"
            />
            <div className="flex justify-between text-xs text-muted-foreground">
              <span>-24 dB</span>
              <span>+24 dB</span>
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
}

/**
 * Calculate filter magnitude at a given frequency
 */
function getFilterMagnitude(
  freq: number,
  params: FilterParameters,
  sampleRate: number
): number {
  const w = (2 * Math.PI * freq) / sampleRate;
  const w0 = (2 * Math.PI * params.frequency) / sampleRate;
  const Q = params.Q || 1.0;
  const gain = params.gain || 0;
  const A = Math.pow(10, gain / 40);

  // Simplified magnitude calculation for different filter types
  switch (params.type) {
    case 'lowpass': {
      const ratio = freq / params.frequency;
      return 1 / Math.sqrt(1 + Math.pow(ratio * Q, 2 * 2));
    }
    case 'highpass': {
      const ratio = params.frequency / freq;
      return 1 / Math.sqrt(1 + Math.pow(ratio * Q, 2 * 2));
    }
    case 'bandpass': {
      const ratio = Math.abs(freq - params.frequency) / (params.frequency / Q);
      return 1 / Math.sqrt(1 + Math.pow(ratio, 2));
    }
    case 'notch': {
      const ratio = Math.abs(freq - params.frequency) / (params.frequency / Q);
      return Math.abs(ratio) / Math.sqrt(1 + Math.pow(ratio, 2));
    }
    case 'lowshelf':
    case 'highshelf':
    case 'peaking': {
      // Simplified for visualization
      const dist = Math.abs(Math.log(freq / params.frequency));
      const influence = Math.exp(-dist * Q);
      return 1 + (A - 1) * influence;
    }
    default:
      return 1;
  }
}
