import { useRef, useEffect, useState } from "react";
import ModalWrapper from "../ModalWrapper";
import Button from "../ui/Button";
import RestartIcon from "../icons/RestartIcon";
import SettingsModal from "./SettingsModal";
import useModalStore from "../../store/modalStore";
import Select from "../ui/Select";

interface SoundCheckModalProps {
  initialSpeaker: string;
  speakers: { deviceId: string; label: string }[];
  speakerVolume: number;
  onSelectSpeaker: (label: string) => void;
}

function SoundCheckModal({
  initialSpeaker,
  speakers,
  speakerVolume,
  onSelectSpeaker,
}: SoundCheckModalProps) {
  const { setModal } = useModalStore();

  const [selectedSpeaker, setSelectedSpeaker] = useState(initialSpeaker);
  const audioContextRef = useRef<AudioContext | null>(null);
  const animationFrameRef = useRef<number | null>(null);
  const audioElementRef = useRef<HTMLAudioElement | null>(null);
  const mediaStreamDestinationRef =
    useRef<MediaStreamAudioDestinationNode | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [playProgress, setPlayProgress] = useState(0); // Прогресс воспроизведения 0-1
  const playStartTimeRef = useRef<number>(0);

  // Обработчик выбора динамика
  const handleSelectSpeaker = (label: string) => {
    setSelectedSpeaker(label);
    onSelectSpeaker(label);
  };

  // Высоты баров эквалайзера (40 баров с несколькими волнами как на макете)
  const barCount = 40;
  const barHeights = [
    3, 12, 16, 20, 44, 28, 12, 12, 16, 20, 34, 60, 28, 12, 8, 16, 12, 20, 40,
    28, 12, 12, 16, 12, 20, 18, 36, 24, 16, 3, 8, 12, 20, 44, 28, 16, 13, 10, 6,
    3,
  ];

  // Обновление прогресса воспроизведения
  useEffect(() => {
    if (!isPlaying) return;

    const updateProgress = () => {
      const elapsed = Date.now() - playStartTimeRef.current;
      const progress = Math.min(elapsed / 3000, 1); // 3 секунды
      setPlayProgress(progress);

      if (progress < 1) {
        animationFrameRef.current = requestAnimationFrame(updateProgress);
      }
    };

    updateProgress();

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

  // Очистка AudioContext при размонтировании
  useEffect(() => {
    return () => {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }
      if (audioElementRef.current) {
        audioElementRef.current.pause();
        audioElementRef.current.srcObject = null;
        audioElementRef.current = null;
      }
      if (mediaStreamDestinationRef.current) {
        mediaStreamDestinationRef.current = null;
      }
      if (audioContextRef.current) {
        audioContextRef.current.close();
        audioContextRef.current = null;
      }
    };
  }, []);

  const playTestSound = async () => {
    // Создаём AudioContext если его нет
    if (!audioContextRef.current) {
      audioContextRef.current = new AudioContext();
    }

    const audioContext = audioContextRef.current;

    // Создаём MediaStreamDestination для вывода на выбранное устройство
    if (!mediaStreamDestinationRef.current) {
      mediaStreamDestinationRef.current =
        audioContext.createMediaStreamDestination();
    }

    const destination = mediaStreamDestinationRef.current;

    // Создаём аудио элемент для вывода на конкретное устройство
    if (!audioElementRef.current) {
      audioElementRef.current = new Audio();
      audioElementRef.current.srcObject = destination.stream;
    }

    // Устанавливаем выбранное устройство вывода
    const selectedDevice = speakers.find((s) => s.label === selectedSpeaker);
    if (
      selectedDevice &&
      audioElementRef.current &&
      "setSinkId" in audioElementRef.current
    ) {
      try {
        await (
          audioElementRef.current as HTMLAudioElement & {
            setSinkId: (sinkId: string) => Promise<void>;
          }
        ).setSinkId(selectedDevice.deviceId);
      } catch (error) {
        console.error("Ошибка при установке устройства вывода:", error);
      }
    }

    // Запускаем воспроизведение через аудио элемент
    audioElementRef.current
      .play()
      .catch((e) => console.error("Ошибка воспроизведения:", e));

    const oscillator = audioContext.createOscillator();
    const gainNode = audioContext.createGain();

    // Подключаем к MediaStreamDestination вместо audioContext.destination
    oscillator.connect(gainNode);
    gainNode.connect(destination);

    oscillator.type = "sine";

    // Применяем громкость из настроек
    const baseVolume = speakerVolume / 100;
    gainNode.gain.setValueAtTime(baseVolume * 0.3, audioContext.currentTime);

    // Создаём динамическое изменение частоты на основе высот баров
    const duration = 3; // 3 секунды
    const timePerBar = duration / barCount;

    // Начальная частота
    const minFreq = 200; // Минимальная частота (низкая нота)
    const maxFreq = 1200; // Максимальная частота (высокая нота)
    const minHeight = 3;
    const maxHeight = 60;

    // Устанавливаем начальную частоту
    const initialFreq =
      minFreq +
      ((barHeights[0] - minHeight) / (maxHeight - minHeight)) *
        (maxFreq - minFreq);
    oscillator.frequency.setValueAtTime(initialFreq, audioContext.currentTime);

    // Создаём плавное изменение частоты для каждого бара
    barHeights.forEach((height, index) => {
      const time = audioContext.currentTime + index * timePerBar;
      // Преобразуем высоту бара в частоту
      const frequency =
        minFreq +
        ((height - minHeight) / (maxHeight - minHeight)) * (maxFreq - minFreq);
      oscillator.frequency.linearRampToValueAtTime(frequency, time);
    });

    // Плавное затухание громкости к концу
    gainNode.gain.linearRampToValueAtTime(
      baseVolume * 0.3,
      audioContext.currentTime + duration * 0.8
    );
    gainNode.gain.exponentialRampToValueAtTime(
      0.01,
      audioContext.currentTime + duration
    );

    // Запускаем анимацию прогресса
    playStartTimeRef.current = Date.now();
    setIsPlaying(true);
    setPlayProgress(0);

    // Играем звук 3 секунды
    oscillator.start(audioContext.currentTime);
    oscillator.stop(audioContext.currentTime + duration);

    // Останавливаем анимацию после окончания звука
    setTimeout(() => {
      setIsPlaying(false);
      setPlayProgress(0);
    }, duration * 1000);
  };

  return (
    <ModalWrapper className="2xl:max-w-[21.111vw] max-w-[304px]">
      <div className="flex flex-col 2xl:gap-[1.667vw] gap-6">
        <div className="flex flex-col items-center 2xl:gap-[0.278vw] gap-1">
          <p className="caption-xs text-[#7D7D7D] font-medium">Динамик</p>
          <Select
            size="small"
            options={speakers.map((s) => s.label)}
            defaultOption={selectedSpeaker}
            onSelect={handleSelectSpeaker}
          />
        </div>

        <div className="flex flex-col items-center 2xl:gap-[0.833vw] gap-3">
          <div className="flex items-center justify-center 2xl:gap-[0.208vw] gap-[3px] 2xl:h-[4.167vw] h-[60px]">
            {barHeights.map((height, index) => {
              // Определяем, заполнен ли бар синим (прогресс слева направо)
              const barProgress = (index + 1) / barCount;
              const isActivated = playProgress >= barProgress;

              // Создаём эффект волны звука - бары впереди прогресса тоже окрашиваются
              const distanceFromProgress = Math.abs(
                index / barCount - playProgress
              );
              const isInWave = isPlaying && distanceFromProgress < 0.15; // Волна охватывает 15% баров

              return (
                <div
                  key={index}
                  className="2xl:w-[0.208vw] w-[3px] 2xl:rounded-[0.556vw] rounded-lg transition-colors duration-150 ease-out"
                  style={{
                    height: `${height}px`,
                    backgroundColor:
                      isActivated || isInWave ? "#7B60F3" : "#D6D6D6",
                  }}
                />
              );
            })}
          </div>

          <button
            onClick={playTestSound}
            disabled={isPlaying}
            className="2xl:size-[2.778vw] size-10 rounded-full bg-[#7B60F3] hover:bg-[#9184F6] active:bg-[#B3AAF9] disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center text-white transition-colors"
          >
            <div className="2xl:size-[1.111vw] size-4">
              <RestartIcon />
            </div>
          </button>
        </div>

        <div className="flex flex-col items-center 2xl:gap-[0.556vw] gap-2 text-center">
          <h2 className="title-l font-medium">Вы слышите звук?</h2>
          <p className="text-s text-[#7D7D7D]">
            Если нет, проверьте громкость и&nbsp;подключение динамиков
          </p>
        </div>

        <Button
          variant="primary"
          size="large"
          onClick={() => setModal(<SettingsModal />)}
        >
          Завершить
        </Button>
      </div>
    </ModalWrapper>
  );
}

export default SoundCheckModal;
