/* eslint-disable react-hooks/exhaustive-deps */
import { useState, useRef, useEffect } from "react";
import SoundIcon from "../icons/SoundIcon";
import VideoFilledIcon from "../icons/VideoFilledIcon";
import ModalWrapper from "../ModalWrapper";
import Button from "../ui/Button";
import RangeInput from "../ui/RangeInput";
import Select from "../ui/Select";
import MicrophoneFilledIcon from "../icons/MicrophoneFilledIcon";
import Switch from "../ui/Switch";
import clsx from "clsx";
import useModalStore from "../../store/modalStore";
import SoundCheckModal from "./SoundCheckModal";
import VoiceCheckModal from "./VoiceCheckModal";
import LoaderIcon from "../icons/LoaderIcon";

interface MediaDevice {
  deviceId: string;
  label: string;
}

function SettingsModal() {
  const [microphoneVolume, setMicrophoneVolume] = useState(50);
  const [speakerVolume, setSpeakerVolume] = useState(50);

  // Списки устройств
  const [microphones, setMicrophones] = useState<MediaDevice[]>([]);
  const [speakers, setSpeakers] = useState<MediaDevice[]>([]);
  const [cameras, setCameras] = useState<MediaDevice[]>([]);

  // Выбранные устройства
  const [selectedMicrophone, setSelectedMicrophone] = useState<string>("");
  const [selectedSpeaker, setSelectedSpeaker] = useState<string>("");
  const [selectedCamera, setSelectedCamera] = useState<string>("");

  const [mediaType, setMediaType] = useState<"sound" | "video">("sound");

  const [participantsVideosHidden, setParticipantsVideosHidden] =
    useState(false);

  const [isVideoTestingError, setIsVideoTestingError] = useState(false);
  const [isVideoTestingLoading, setIsVideoTestingLoading] = useState(false);
  const [isVideoTesting, setIsVideoTesting] = useState(false);
  const videoRef = useRef<HTMLVideoElement>(null);
  const streamRef = useRef<MediaStream | null>(null);

  const [isLoadingMicrophones, setIsLoadingMicrophones] = useState(false);
  const [isLoadingSpeakers, setIsLoadingSpeakers] = useState(false);
  const [isLoadingCameras, setIsLoadingCameras] = useState(false);

  const { setModal } = useModalStore();

  // Остановка видео
  function stopVideoTest() {
    if (streamRef.current) {
      streamRef.current.getTracks().forEach((track) => track.stop());
      streamRef.current = null;
    }
    if (videoRef.current) videoRef.current.srcObject = null;

    setIsVideoTesting(false);
  }

  // Загрузка аудио устройств
  async function loadAudioDevices() {
    setIsLoadingMicrophones(true);
    setIsLoadingSpeakers(true);

    try {
      // Запрашиваем разрешения на аудио
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: true,
      });

      // Сразу останавливаем стрим после получения разрешений
      stream.getTracks().forEach((track) => track.stop());

      const devices = await navigator.mediaDevices.enumerateDevices();
      console.log("Найдено аудио устройств:", devices);

      const audioInputs: MediaDevice[] = [];
      const audioOutputs: MediaDevice[] = [];

      devices.forEach((device) => {
        const deviceInfo: MediaDevice = {
          deviceId: device.deviceId,
          label:
            device.label || `${device.kind} (${device.deviceId.slice(0, 8)})`,
        };

        if (device.kind === "audioinput") {
          audioInputs.push(deviceInfo);
        } else if (device.kind === "audiooutput") {
          audioOutputs.push(deviceInfo);
        }
      });

      console.log("Микрофоны:", audioInputs);
      console.log("Динамики:", audioOutputs);

      setMicrophones(audioInputs);
      setIsLoadingMicrophones(false);

      setSpeakers(audioOutputs);
      setIsLoadingSpeakers(false);

      // Устанавливаем первое устройство по умолчанию
      if (audioInputs.length > 0 && !selectedMicrophone) {
        setSelectedMicrophone(audioInputs[0].label);
      }
      if (audioOutputs.length > 0 && !selectedSpeaker) {
        setSelectedSpeaker(audioOutputs[0].label);
      }
    } catch (error) {
      console.error("Ошибка при загрузке аудио устройств:", error);

      // Пробуем загрузить устройства без разрешений
      try {
        const devices = await navigator.mediaDevices.enumerateDevices();
        console.log("Аудио устройства без разрешений:", devices);

        const audioInputs: MediaDevice[] = [];
        const audioOutputs: MediaDevice[] = [];

        devices.forEach((device) => {
          const deviceInfo: MediaDevice = {
            deviceId: device.deviceId,
            label: device.label || `${device.kind} (требуется разрешение)`,
          };

          if (device.kind === "audioinput") {
            audioInputs.push(deviceInfo);
          } else if (device.kind === "audiooutput") {
            audioOutputs.push(deviceInfo);
          }
        });

        setMicrophones(audioInputs);
        setSpeakers(audioOutputs);
      } catch (err) {
        console.error("Не удалось загрузить аудио устройства:", err);
      } finally {
        setIsLoadingMicrophones(false);
        setIsLoadingSpeakers(false);
      }
    }
  }

  // Загрузка видео устройств
  async function loadVideoDevices() {
    setIsLoadingCameras(true);

    try {
      // Запрашиваем разрешения на видео
      const stream = await navigator.mediaDevices.getUserMedia({
        video: true,
      });

      // Сразу останавливаем стрим после получения разрешений
      stream.getTracks().forEach((track) => track.stop());

      const devices = await navigator.mediaDevices.enumerateDevices();
      console.log("Найдено видео устройств:", devices);

      const videoInputs: MediaDevice[] = [];

      devices.forEach((device) => {
        if (device.kind === "videoinput") {
          const deviceInfo: MediaDevice = {
            deviceId: device.deviceId,
            label:
              device.label || `${device.kind} (${device.deviceId.slice(0, 8)})`,
          };
          videoInputs.push(deviceInfo);
        }
      });

      console.log("Камеры:", videoInputs);

      setCameras(videoInputs);
      setIsLoadingCameras(false);

      // Устанавливаем первое устройство по умолчанию
      if (videoInputs.length > 0 && !selectedCamera) {
        setSelectedCamera(videoInputs[0].label);
      }
    } catch (error) {
      console.error("Ошибка при загрузке видео устройств:", error);

      // Пробуем загрузить устройства без разрешений
      try {
        const devices = await navigator.mediaDevices.enumerateDevices();
        console.log("Видео устройства без разрешений:", devices);

        const videoInputs: MediaDevice[] = [];

        devices.forEach((device) => {
          if (device.kind === "videoinput") {
            const deviceInfo: MediaDevice = {
              deviceId: device.deviceId,
              label: device.label || `${device.kind} (требуется разрешение)`,
            };
            videoInputs.push(deviceInfo);
          }
        });

        setCameras(videoInputs);
      } catch (err) {
        console.error("Не удалось загрузить видео устройства:", err);
      } finally {
        setIsLoadingCameras(false);
      }
    }
  }

  // Запуск видео
  async function startVideoTest() {
    try {
      setIsVideoTestingLoading(true);
      setIsVideoTestingError(false);

      // Находим deviceId выбранной камеры
      const selectedCameraDevice = cameras.find(
        (cam) => cam.label === selectedCamera
      );

      const constraints: MediaStreamConstraints = {
        video: selectedCameraDevice
          ? { deviceId: { exact: selectedCameraDevice.deviceId } }
          : true,
        audio: false,
      };

      const stream = await navigator.mediaDevices.getUserMedia(constraints);
      streamRef.current = stream;
      if (videoRef.current) videoRef.current.srcObject = stream;

      setIsVideoTesting(true);
    } catch (error) {
      console.error("Ошибка при доступе к камере:", error);
      setIsVideoTestingError(true);
    } finally {
      setIsVideoTestingLoading(false);
    }
  }

  // Загружаем только аудио устройства при монтировании
  useEffect(() => {
    loadAudioDevices();

    // Слушаем изменения устройств (подключение/отключение)
    const handleDeviceChange = () => {
      // Загружаем аудио всегда
      loadAudioDevices();
      // Загружаем видео только если находимся на вкладке "Видео"
      if (mediaType === "video") {
        loadVideoDevices();
      }
    };

    navigator.mediaDevices.addEventListener("devicechange", handleDeviceChange);

    return () => {
      navigator.mediaDevices.removeEventListener(
        "devicechange",
        handleDeviceChange
      );
    };
  }, [mediaType]);

  // Загружаем видео устройства и запускаем видео при переключении на вкладку "Видео"
  useEffect(() => {
    if (mediaType === "video") {
      // Всегда загружаем камеры при переходе на вкладку, если их еще нет
      if (cameras.length === 0 && !isLoadingCameras) {
        loadVideoDevices();
      }

      // Запускаем видео только если камеры уже загружены
      if (cameras.length > 0) {
        startVideoTest();
      }

      return stopVideoTest;
    }
  }, [mediaType, cameras.length]);

  // Перезапускаем видео при смене камеры
  useEffect(() => {
    if (isVideoTesting && selectedCamera) {
      stopVideoTest();
      startVideoTest();
    }
  }, [selectedCamera]);

  // Открыть модальное окно проверки микрофона
  const openMicrophoneCheck = () => {
    setModal(
      <VoiceCheckModal
        selectedMicrophone={selectedMicrophone}
        microphones={microphones}
        onSelectMicrophone={setSelectedMicrophone}
        onClose={() => setModal(null)}
      />
    );
  };

  // Открыть модальное окно проверки динамика
  const openSpeakerCheck = () => {
    setModal(
      <SoundCheckModal
        selectedSpeaker={selectedSpeaker}
        speakers={speakers}
        onSelectSpeaker={setSelectedSpeaker}
        onClose={() => setModal(null)}
      />
    );
  };

  return (
    <ModalWrapper title="Настройки" className="max-w-[27.778vw]">
      <div className="2xl:space-y-[1.389vw] space-y-5 2xl:-mt-[1.389vw] -mt-5">
        <div className="flex">
          <Button
            variant="menu"
            size="large"
            className={"w-full"}
            onClick={() => setMediaType("sound")}
            isActive={mediaType === "sound"}
          >
            <div className="flex 2xl:gap-[0.556vw] items-center">
              <div
                className={clsx(
                  "2xl:size-[1.111vw] size-4",
                  mediaType === "sound" ? "text-[#7B60F3]" : "text-[#7D7D7D]"
                )}
              >
                <SoundIcon />
              </div>
              <p className="font-medium">Звук</p>
            </div>
          </Button>
          <Button
            variant="menu"
            size="large"
            className="w-full"
            onClick={() => setMediaType("video")}
            isActive={mediaType === "video"}
          >
            <div className="flex 2xl:gap-[0.556vw] items-center">
              <div
                className={clsx(
                  "2xl:size-[1.111vw] size-4",
                  mediaType === "video" ? "text-[#7B60F3]" : "text-[#7D7D7D]"
                )}
              >
                <VideoFilledIcon />
              </div>
              <p className="font-medium">Видео</p>
            </div>
          </Button>
        </div>
        {mediaType === "sound" && (
          <div className="2xl:space-y-[1.667vw] space-y-6">
            <div className="2xl:space-y-[0.833vw] space-y-3">
              <p className="title-s font-medium">Микрофон</p>
              <div className="2xl:space-y-[1.111vw] space-y-4">
                {isLoadingMicrophones ? (
                  <div className="bg-[#F3F3F3] 2xl:p-[1.667vw] p-6 2xl:rounded-[1.111vw] rounded-2xl flex flex-col items-center 2xl:gap-[0.833vw] gap-3">
                    <div className="2xl:size-[2.222vw] size-8 text-[#7B60F3] animate-spin">
                      <LoaderIcon />
                    </div>
                    <p className="text-s text-[#7D7D7D]">
                      Загрузка микрофонов...
                    </p>
                  </div>
                ) : microphones.length === 0 ? (
                  <div className="bg-[#FEF3F2] 2xl:p-[1.111vw] p-4 2xl:rounded-[1.111vw] rounded-2xl 2xl:space-y-[0.556vw] space-y-2">
                    <p className="text-s text-[#FF4517]">
                      Микрофоны не найдены. Проверьте подключение устройства и
                      разрешения браузера.
                    </p>
                    <Button
                      variant="secondary"
                      size="medium"
                      onClick={loadAudioDevices}
                      className="w-full"
                    >
                      Обновить устройства
                    </Button>
                  </div>
                ) : (
                  <div className="flex 2xl:gap-[0.556vw]">
                    <Select
                      className="flex-1"
                      options={microphones.map((m) => m.label)}
                      defaultOption={selectedMicrophone}
                      onSelect={setSelectedMicrophone}
                    />
                    <Button
                      variant="cta"
                      size="large"
                      onClick={openMicrophoneCheck}
                      disabled={!selectedMicrophone}
                    >
                      Проверить
                    </Button>
                  </div>
                )}
                <div className="flex items-center 2xl:gap-[0.833vw]">
                  <div className="2xl:size-[1.111vw] size-4 text-[#7D7D7D]">
                    <MicrophoneFilledIcon />
                  </div>
                  <RangeInput
                    value={microphoneVolume}
                    onChange={setMicrophoneVolume}
                  />
                  <p className="caption-xs font-medium text-[#7D7D7D] 2xl:w-[1.667vw] w-6">
                    {microphoneVolume.toFixed(0)}%
                  </p>
                </div>
              </div>
            </div>
            <hr className="bg-[#F6F6F6] 2xl:h-[0.069vw] h-px" />
            <div className="2xl:space-y-[0.833vw] space-y-3">
              <p className="title-s font-medium">Динамик</p>
              <div className="2xl:space-y-[1.111vw] space-y-4">
                {isLoadingSpeakers ? (
                  <div className="bg-[#F3F3F3] 2xl:p-[1.667vw] p-6 2xl:rounded-[1.111vw] rounded-2xl flex flex-col items-center 2xl:gap-[0.833vw] gap-3">
                    <div className="2xl:size-[2.222vw] size-8 text-[#7B60F3] animate-spin">
                      <LoaderIcon />
                    </div>
                    <p className="text-s text-[#7D7D7D]">
                      Загрузка динамиков...
                    </p>
                  </div>
                ) : speakers.length === 0 ? (
                  <div className="bg-[#FEF3F2] 2xl:p-[1.111vw] p-4 2xl:rounded-[1.111vw] rounded-2xl 2xl:space-y-[0.556vw] space-y-2">
                    <p className="text-s text-[#FF4517]">
                      Динамики не найдены. Проверьте подключение устройства и
                      разрешения браузера.
                    </p>
                    <Button
                      variant="secondary"
                      size="medium"
                      onClick={loadAudioDevices}
                      className="w-full"
                    >
                      Обновить устройства
                    </Button>
                  </div>
                ) : (
                  <div className="flex 2xl:gap-[0.556vw]">
                    <Select
                      className="flex-1"
                      options={speakers.map((s) => s.label)}
                      defaultOption={selectedSpeaker}
                      onSelect={setSelectedSpeaker}
                    />
                    <Button
                      variant="cta"
                      size="large"
                      onClick={openSpeakerCheck}
                      disabled={!selectedSpeaker}
                    >
                      Проверить
                    </Button>
                  </div>
                )}
                <div className="flex items-center 2xl:gap-[0.833vw]">
                  <div className="2xl:size-[1.111vw] size-4 text-[#7D7D7D]">
                    <SoundIcon />
                  </div>
                  <RangeInput
                    value={speakerVolume}
                    onChange={setSpeakerVolume}
                  />
                  <p className="caption-xs font-medium text-[#7D7D7D] 2xl:w-[1.667vw] w-6">
                    {speakerVolume.toFixed(0)}%
                  </p>
                </div>
              </div>
            </div>
          </div>
        )}
        {mediaType === "video" && (
          <div className="2xl:space-y-[1.667vw] space-y-6">
            <div className="2xl:space-y-[0.556vw] space-y-2">
              <p className="title-s font-medium">Камера</p>
              {isLoadingCameras ? (
                <div className="bg-[#F3F3F3] 2xl:p-[1.667vw] p-6 2xl:rounded-[1.111vw] rounded-2xl flex flex-col items-center 2xl:gap-[0.833vw] gap-3">
                  <div className="2xl:size-[2.222vw] size-8 text-[#7B60F3] animate-spin">
                    <LoaderIcon />
                  </div>
                  <p className="text-s text-[#7D7D7D]">Загрузка камер...</p>
                </div>
              ) : cameras.length === 0 ? (
                <div className="bg-[#FEF3F2] 2xl:p-[1.111vw] p-4 2xl:rounded-[1.111vw] rounded-2xl 2xl:space-y-[0.556vw] space-y-2">
                  <p className="text-s text-[#FF4517]">
                    Камеры не найдены. Проверьте подключение устройства и
                    разрешения браузера.
                  </p>
                  <Button
                    variant="secondary"
                    size="medium"
                    onClick={loadVideoDevices}
                    className="w-full"
                  >
                    Обновить устройства
                  </Button>
                </div>
              ) : (
                <Select
                  options={cameras.map((c) => c.label)}
                  onSelect={setSelectedCamera}
                  defaultOption={selectedCamera}
                />
              )}
              <video
                ref={videoRef}
                muted
                autoPlay
                playsInline
                hidden={!isVideoTesting}
                className="2xl:rounded-[1.111vw] rounded-2xl 2xl:w-[25vw] w-[360px] aspect-[360/202] object-cover"
              />
              {!isVideoTesting && (
                <div className="bg-[#F3F3F3] 2xl:w-[25vw] w-[360px] aspect-[360/202] flex justify-center items-center 2xl:rounded-[1.111vw] rounded-2xl">
                  {isVideoTestingError && (
                    <div className="2xl:space-y-[0.556vw] space-y-2">
                      <p className="title-s font-medium text-center">
                        Включить видео не удалось
                      </p>
                      <p className="text-center text-[#7D7D7D] caption-s font-medium">
                        Проверьте подключение камеры и разрешения
                      </p>
                    </div>
                  )}
                  {isVideoTestingLoading && (
                    <div className="2xl:space-y-[0.556vw] space-y-2">
                      <p className="title-s font-medium text-center">
                        Проверка видео...
                      </p>
                    </div>
                  )}
                </div>
              )}
            </div>
            <div className="flex items-center 2xl:gap-[0.556vw] gap-2">
              <Switch
                enabled={participantsVideosHidden}
                onChange={setParticipantsVideosHidden}
              />
              <p className="text-m">Скрыть видео участников</p>
            </div>
          </div>
        )}
      </div>
    </ModalWrapper>
  );
}

export default SettingsModal;
