"use client";

import { useEffect, useRef, useState, useCallback } from "react";
import { useAudioRecorder } from "@/lib/useAudioRecorder";
import { RecordingControls } from "@/components/RecordingControls";

// Drum kit configuration - 4x4 grid
// Row 1 (top): 1234 - empty for now
// Row 2: QWER - empty for now
// Row 3: ASDF - drums
// Row 4 (bottom): ZXCV - drums
const DRUMS = [
  // Row 1 - Number keys (empty)
  { name: "", key: "1", color: "bg-gray-700", freq: 0, isEmpty: true },
  { name: "", key: "2", color: "bg-gray-700", freq: 0, isEmpty: true },
  { name: "", key: "3", color: "bg-gray-700", freq: 0, isEmpty: true },
  { name: "", key: "4", color: "bg-gray-700", freq: 0, isEmpty: true },
  // Row 2 - QWER (empty)
  { name: "", key: "Q", color: "bg-gray-700", freq: 0, isEmpty: true },
  { name: "", key: "W", color: "bg-gray-700", freq: 0, isEmpty: true },
  { name: "", key: "E", color: "bg-gray-700", freq: 0, isEmpty: true },
  { name: "", key: "R", color: "bg-gray-700", freq: 0, isEmpty: true },
  // Row 3 - ASDF (active drums)
  { name: "Kick", key: "A", color: "bg-red-500", freq: 60, isEmpty: false },
  { name: "Snare", key: "S", color: "bg-blue-500", freq: 200, isEmpty: false },
  { name: "Hi-Hat", key: "D", color: "bg-yellow-500", freq: 8000, isEmpty: false },
  { name: "Clap", key: "F", color: "bg-green-500", freq: 1000, isEmpty: false },
  // Row 4 - ZXCV (active drums)
  { name: "Tom", key: "Z", color: "bg-purple-500", freq: 150, isEmpty: false },
  { name: "Rim", key: "X", color: "bg-pink-500", freq: 800, isEmpty: false },
  { name: "Crash", key: "C", color: "bg-orange-500", freq: 4000, isEmpty: false },
  { name: "Perc", key: "V", color: "bg-cyan-500", freq: 500, isEmpty: false },
];

export default function DrumPad() {
  const [audioContext, setAudioContext] = useState<AudioContext | null>(null);
  const [activeKeys, setActiveKeys] = useState<Set<string>>(new Set());
  const [gameStarted, setGameStarted] = useState(false);

  // Use the shared audio recorder hook
  const recorder = useAudioRecorder({ audioContext });

  // Cache audio buffers for better performance
  const snareBufferRef = useRef<AudioBuffer | null>(null);
  const hihatBufferRef = useRef<AudioBuffer | null>(null);
  const clapBufferRef = useRef<AudioBuffer | null>(null);

  // Initialize AudioContext with explicit sample rate
  useEffect(() => {
    const initAudio = async () => {
      if (!audioContext) {
        // Force 48kHz to match most MediaRecorder implementations
        const ctx = new AudioContext({ sampleRate: 48000 });

        // Wait for context to be running and stable
        if (ctx.state === 'suspended') {
          await ctx.resume();
        }

        // Give a moment for the context to fully initialize
        await new Promise(resolve => setTimeout(resolve, 100));

        console.log(`AudioContext initialized at ${ctx.sampleRate}Hz, state: ${ctx.state}`);
        setAudioContext(ctx);
      }
    };

    document.addEventListener("click", initAudio, { once: true });
    document.addEventListener("touchstart", initAudio, { once: true });
    document.addEventListener("keydown", initAudio, { once: true });

    return () => {
      document.removeEventListener("click", initAudio);
      document.removeEventListener("touchstart", initAudio);
      document.removeEventListener("keydown", initAudio);
    };
  }, [audioContext]);

  // Pre-generate noise buffers when audio context is ready
  useEffect(() => {
    if (audioContext && !snareBufferRef.current) {

      // Pre-generate noise buffers for performance
      // Snare buffer (200ms)
      const snareSize = audioContext.sampleRate * 0.2;
      const snareBuffer = audioContext.createBuffer(1, snareSize, audioContext.sampleRate);
      const snareData = snareBuffer.getChannelData(0);
      for (let i = 0; i < snareSize; i++) {
        snareData[i] = Math.random() * 2 - 1;
      }
      snareBufferRef.current = snareBuffer;

      // Hi-hat buffer (50ms)
      const hihatSize = audioContext.sampleRate * 0.05;
      const hihatBuffer = audioContext.createBuffer(1, hihatSize, audioContext.sampleRate);
      const hihatData = hihatBuffer.getChannelData(0);
      for (let i = 0; i < hihatSize; i++) {
        hihatData[i] = Math.random() * 2 - 1;
      }
      hihatBufferRef.current = hihatBuffer;

      // Clap buffer (100ms)
      const clapSize = audioContext.sampleRate * 0.1;
      const clapBuffer = audioContext.createBuffer(1, clapSize, audioContext.sampleRate);
      const clapData = clapBuffer.getChannelData(0);
      for (let i = 0; i < clapSize; i++) {
        clapData[i] = Math.random() * 2 - 1;
      }
      clapBufferRef.current = clapBuffer;
    }
  }, [audioContext]);

  // Notify parent game started
  const notifyGameStart = useCallback(() => {
    if (!gameStarted) {
      setGameStarted(true);
      window.parent?.postMessage(
        {
          type: "game:start",
          slug: "drum-pad",
        },
        "*"
      );
    }
  }, [gameStarted]);

  // Play drum sound
  const playDrum = useCallback(
    (drumIndex: number) => {
      if (!audioContext) return;

      const drum = DRUMS[drumIndex];

      // Skip empty pads
      if (drum.isEmpty) return;

      // Debug logging
      console.log(`🥁 playDrum called: ${drum.name} (${drum.key}) at ${Date.now()}`);

      const now = audioContext.currentTime;

      // Visual feedback using direct DOM manipulation for better performance
      const button = document.querySelector(`[data-pad-index="${drumIndex}"]`) as HTMLButtonElement;
      if (button && !drum.isEmpty) {
        button.classList.add('pad-active');
        setTimeout(() => {
          button.classList.remove('pad-active');
        }, 80);
      }

      if (drum.name === "Kick") {
        // Kick drum: low frequency sine wave with pitch drop
        const osc = audioContext.createOscillator();
        const gain = audioContext.createGain();

        osc.type = "sine";
        osc.frequency.setValueAtTime(150, now);
        osc.frequency.exponentialRampToValueAtTime(40, now + 0.1);

        gain.gain.setValueAtTime(1, now);
        gain.gain.exponentialRampToValueAtTime(0.01, now + 0.5);

        osc.connect(gain);
        gain.connect(audioContext.destination);
        // Only connect to recorder when actively recording
        if (recorder.recordingState === "recording") {
          recorder.connectToRecording(gain);
        }

        osc.start(now);
        osc.stop(now + 0.5);
      } else if (drum.name === "Snare") {
        // Snare: white noise with bandpass filter (using cached buffer)
        if (!snareBufferRef.current) return;

        const noise = audioContext.createBufferSource();
        noise.buffer = snareBufferRef.current;

        const filter = audioContext.createBiquadFilter();
        filter.type = "bandpass";
        filter.frequency.value = 1000;

        const gain = audioContext.createGain();
        gain.gain.setValueAtTime(0.5, now);
        gain.gain.exponentialRampToValueAtTime(0.01, now + 0.2);

        noise.connect(filter);
        filter.connect(gain);
        gain.connect(audioContext.destination);
        // Only connect to recorder when actively recording
        if (recorder.recordingState === "recording") {
          recorder.connectToRecording(gain);
        }

        noise.start(now);
        noise.stop(now + 0.2);
      } else if (drum.name === "Hi-Hat") {
        // Hi-hat: high-pass filtered noise (using cached buffer)
        if (!hihatBufferRef.current) return;

        const noise = audioContext.createBufferSource();
        noise.buffer = hihatBufferRef.current;

        const filter = audioContext.createBiquadFilter();
        filter.type = "highpass";
        filter.frequency.value = 7000;

        const gain = audioContext.createGain();
        gain.gain.setValueAtTime(0.3, now);
        gain.gain.exponentialRampToValueAtTime(0.01, now + 0.05);

        noise.connect(filter);
        filter.connect(gain);
        gain.connect(audioContext.destination);
        // Only connect to recorder when actively recording
        if (recorder.recordingState === "recording") {
          recorder.connectToRecording(gain);
        }

        noise.start(now);
        noise.stop(now + 0.05);
      } else if (drum.name === "Clap") {
        // Clap: burst of noise (using cached buffer)
        if (!clapBufferRef.current) return;

        const noise = audioContext.createBufferSource();
        noise.buffer = clapBufferRef.current;

        const filter = audioContext.createBiquadFilter();
        filter.type = "bandpass";
        filter.frequency.value = 1500;

        const gain = audioContext.createGain();
        gain.gain.setValueAtTime(0.4, now);
        gain.gain.exponentialRampToValueAtTime(0.01, now + 0.1);

        noise.connect(filter);
        filter.connect(gain);
        gain.connect(audioContext.destination);
        // Only connect to recorder when actively recording
        if (recorder.recordingState === "recording") {
          recorder.connectToRecording(gain);
        }

        noise.start(now);
        noise.stop(now + 0.1);
      } else {
        // Generic drum: simple oscillator
        const osc = audioContext.createOscillator();
        const gain = audioContext.createGain();

        osc.type = "triangle";
        osc.frequency.value = drum.freq;

        gain.gain.setValueAtTime(0.3, now);
        gain.gain.exponentialRampToValueAtTime(0.01, now + 0.1);

        osc.connect(gain);
        gain.connect(audioContext.destination);
        // Only connect to recorder when actively recording
        if (recorder.recordingState === "recording") {
          recorder.connectToRecording(gain);
        }

        osc.start(now);
        osc.stop(now + 0.1);
      }
    },
    [audioContext, recorder]
  );

  // Handle keyboard
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      const key = e.key.toUpperCase();
      const drumIndex = DRUMS.findIndex((d) => d.key === key);

      if (drumIndex !== -1 && !activeKeys.has(key)) {
        notifyGameStart();
        setActiveKeys((prev) => new Set(prev).add(key));
        playDrum(drumIndex);
      }

      // Spacebar to toggle recording
      if (key === " ") {
        e.preventDefault();
        notifyGameStart();
        if (recorder.recordingState === "idle" || recorder.recordingState === "recorded") {
          recorder.startRecording();
        } else if (recorder.recordingState === "recording") {
          recorder.stopRecording();
        }
      }
    };

    const handleKeyUp = (e: KeyboardEvent) => {
      const key = e.key.toUpperCase();
      setActiveKeys((prev) => {
        const newSet = new Set(prev);
        newSet.delete(key);
        return newSet;
      });
    };

    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);

    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("keyup", handleKeyUp);
    };
  }, [activeKeys, playDrum, notifyGameStart, recorder]);

  return (
    <div className="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 flex flex-col items-center justify-center p-4">
      <style jsx global>{`
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }
        body {
          font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
          overflow-x: hidden;
          user-select: none;
          -webkit-user-select: none;
        }
        .pad-active {
          transform: scale(0.95) !important;
          filter: brightness(1.25) !important;
          box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3) !important;
        }
      `}</style>

      <div className="text-center mb-6">
        <h1 className="text-4xl md:text-5xl font-bold text-white mb-2 drop-shadow-lg">
          🥁 Drum Pad
        </h1>
        <p className="text-white/80 text-sm md:text-base">
          Click pads or press keys to play • Space to record
        </p>
        {!audioContext && (
          <p className="text-yellow-300 text-xs md:text-sm mt-2">
            👆 Click or press any key to enable sound
          </p>
        )}
        {audioContext && audioContext.state !== 'running' && (
          <p className="text-yellow-300 text-xs md:text-sm mt-2">
            🔄 Audio context initializing...
          </p>
        )}
      </div>

      <RecordingControls
        recordingState={recorder.recordingState}
        recordedAudioUrl={recorder.recordedAudioUrl}
        onStartRecording={recorder.startRecording}
        onStopRecording={recorder.stopRecording}
        onClearRecording={recorder.clearRecording}
        disabled={!audioContext || audioContext.state !== 'running'}
      />

      {/* Drum Pads Grid - 4x4 */}
      <div className="bg-black/40 backdrop-blur-sm p-4 md:p-6 rounded-2xl shadow-2xl mb-6 max-w-xs md:max-w-sm mx-auto">
        <div className="grid grid-cols-4 gap-3 md:gap-4">
          {DRUMS.map((drum, index) => (
            <button
              key={`${drum.key}-${index}`}
              data-pad-index={index}
              onClick={() => {
                if (!drum.isEmpty) {
                  notifyGameStart();
                  playDrum(index);
                }
              }}
              disabled={drum.isEmpty}
              className={`${drum.color} text-white font-bold px-4 py-6 md:px-6 md:py-8 rounded-xl transition-all shadow-lg ${
                drum.isEmpty
                  ? "opacity-30 cursor-not-allowed"
                  : "hover:shadow-2xl"
              } ${
                !drum.isEmpty && activeKeys.has(drum.key)
                  ? "scale-95 brightness-125 shadow-2xl"
                  : "scale-100"
              }`}
            >
              <div className="text-lg md:text-xl mb-2">
                {drum.name || <span className="opacity-50">-</span>}
              </div>
              <div className="text-xs md:text-sm opacity-70 font-mono">
                [{drum.key}]
              </div>
            </button>
          ))}
        </div>
      </div>

      {/* Keyboard reference */}
      <div className="text-center">
        <p className="text-white/60 text-xs md:text-sm mb-2">
          Keyboard: 1234 (empty) • QWER (empty) • ASDF (drums) • ZXCV (drums)
        </p>
        <p className="text-white/60 text-xs md:text-sm">
          Press SPACE to start/stop recording
        </p>
      </div>
    </div>
  );
}
