import { useEffect, useRef, useState } from "react";
import HandRaisedOffFilledIcon from "../icons/HandRaisedOffFilledIcon";
import HandRaisedFilledIcon from "../icons/HandRaisedFilledIcon";
import MicrophoneFilledIcon from "../icons/MicrophoneFilledIcon";
import VideoOffFilledIcon from "../icons/VideoOffFilledIcon";
import MicrophoneOffIcon from "../icons/MicrophoneOffIcon";
import VideoFilledIcon from "../icons/VideoFilledIcon";
import ControlButton from "./ControlButton";
import Admin from "../indicators/Admin";
import clsx from "clsx";
import VolumeIcon from "../icons/VolumeIcon";
import VolumeOffIcon from "../icons/VolumeOffIcon";
import { useVoiceActivity } from "../../hooks/useVoiceActivity";
import MicrophoneOffFilledIcon from "../icons/MicrophoneOffFilledIcon";

interface UserCameraControlsProps {
  isMuted: boolean;
  isVideoOff: boolean;
  isControlDisabled: boolean;
  isAdmin: boolean;
  onMute: () => void;
  onVideoOff: () => void;
  onCanControl: () => void;
}

interface UserCameraProps {
  isMuted: boolean;
  isVideoOff: boolean;
  isControlDisabled: boolean;
  onMute: () => void;
  onVideoOff: () => void;
  onCanControl: () => void;
  isAdmin?: boolean;
  name?: string;
  mediaStream?: MediaStream | null;
  isLocal?: boolean;
  isSpeaking?: boolean; // Для удаленных участников - получаем по Socket.IO
  onSpeakingChange?: (isSpeaking: boolean) => void; // Для локального - отправляем изменения
  hasLocalMediaPermission?: boolean; // Есть ли у локального пользователя разрешение на медиа
  mode: "full" | "mini";
  className?: string;
}

export default function UserCamera({
  isMuted,
  isVideoOff,
  isControlDisabled,
  onMute,
  onVideoOff,
  onCanControl,
  isAdmin = false,
  name = "Гость",
  mediaStream = null,
  isLocal = false,
  isSpeaking: remoteSpeaking,
  onSpeakingChange,
  hasLocalMediaPermission = false,
  mode = "full",
  className,
}: UserCameraProps) {
  const ref = useRef<HTMLVideoElement>(null);
  // Для удаленных участников: если у локального пользователя есть разрешение на медиа - unmute, иначе mute (для autoplay)
  const [isAudioMuted, setIsAudioMuted] = useState(!hasLocalMediaPermission);

  // Детекция голосовой активности (только для локального пользователя)
  const { isSpeaking: isVoiceActive } = useVoiceActivity(
    isLocal ? mediaStream : null
  );

  // Для локального - используем локальную детекцию
  // Для удаленных - используем полученное состояние через Socket.IO
  const localSpeaking = !isMuted && isVoiceActive;
  const isSpeaking = isLocal ? localSpeaking : remoteSpeaking || false;

  // Отправляем изменения состояния для локального пользователя
  // Используем ref для отслеживания предыдущего состояния, чтобы избежать лишних вызовов
  const prevLocalSpeakingRef = useRef<boolean>(localSpeaking);

  useEffect(() => {
    if (
      isLocal &&
      onSpeakingChange &&
      prevLocalSpeakingRef.current !== localSpeaking
    ) {
      prevLocalSpeakingRef.current = localSpeaking;
      onSpeakingChange(localSpeaking);
    }
  }, [isLocal, localSpeaking, onSpeakingChange]);

  // Рамка либо горит на 100%, либо выключена
  // isSpeaking уже учитывает threshold и debounce (1 сек)
  const ringOpacity = isSpeaking ? 1 : 0;

  // Логируем для отладки (отключено для снижения шума)
  // useEffect(() => {
  //   console.log(
  //     `[${name}${
  //       isLocal ? " (local)" : ""
  //     }] isSpeaking: ${isSpeaking}, ringOpacity: ${ringOpacity.toFixed(
  //       2
  //     )}, isMuted: ${isMuted}`
  //   );
  // }, [isSpeaking, ringOpacity, name, isMuted, isLocal]);

  useEffect(() => {
    if (ref.current && mediaStream) {
      console.log(
        `[UserCamera] Setting srcObject for ${name}, isLocal: ${isLocal}, stream:`,
        mediaStream
      );
      ref.current.srcObject = mediaStream;

      // Принудительно запускаем воспроизведение
      ref.current.play().catch((error) => {
        console.error(`[UserCamera] Failed to play video for ${name}:`, error);
      });

      // Дополнительная попытка воспроизведения с задержкой для Firefox
      if (!isLocal) {
        // Попытка через 500ms
        setTimeout(() => {
          if (ref.current) {
            console.log(
              `[UserCamera] First retry for ${name}, paused: ${ref.current.paused}, readyState: ${ref.current.readyState}`
            );
            if (ref.current.paused) {
              ref.current.play().catch((error) => {
                console.error(
                  `[UserCamera] First retry play failed for ${name}:`,
                  error
                );
              });
            }
          }
        }, 500);

        // Попытка через 1 секунду
        setTimeout(() => {
          if (ref.current && ref.current.paused) {
            console.log(`[UserCamera] Second retry for ${name} after timeout`);
            ref.current.play().catch((error) => {
              console.error(
                `[UserCamera] Second retry play failed for ${name}:`,
                error
              );
            });
          }
        }, 1000);

        // Еще одна попытка через 3 секунды
        setTimeout(() => {
          if (ref.current) {
            console.log(
              `[UserCamera] Final retry for ${name}, paused: ${ref.current.paused}, readyState: ${ref.current.readyState}`
            );
            if (ref.current.paused) {
              ref.current.play().catch((error) => {
                console.error(
                  `[UserCamera] Final retry play failed for ${name}:`,
                  error
                );
              });
            }
          }
        }, 3000);
      }
    } else if (ref.current && !mediaStream) {
      console.log(`[UserCamera] Clearing srcObject for ${name}`);
      ref.current.srcObject = null;
    }
  }, [mediaStream, name, isLocal]);

  // Добавляем обработчики событий для отладки
  useEffect(() => {
    const videoElement = ref.current;
    if (!videoElement) return;

    const handleLoadStart = () => {
      console.log(`[UserCamera] ${name} video loadstart`);
    };

    const handleLoadedData = () => {
      console.log(`[UserCamera] ${name} video loadeddata`);
    };

    const handleCanPlay = () => {
      console.log(`[UserCamera] ${name} video canplay`);
    };

    const handleLoadedMetadata = () => {
      console.log(`[UserCamera] ${name} video loadedmetadata`);
    };

    const handleCanPlayThrough = () => {
      console.log(`[UserCamera] ${name} video canplaythrough`);
    };

    const handlePlay = () => {
      console.log(`[UserCamera] ${name} video play event`);
    };

    const handlePlaying = () => {
      console.log(`[UserCamera] ${name} video playing event`);
    };

    const handleWaiting = () => {
      console.log(
        `[UserCamera] ${name} video waiting event, paused: ${videoElement.paused}, readyState: ${videoElement.readyState}`
      );
    };

    const handleStalled = () => {
      console.log(
        `[UserCamera] ${name} video stalled event, paused: ${videoElement.paused}, readyState: ${videoElement.readyState}`
      );
    };

    const handlePause = () => {
      console.log(`[UserCamera] ${name} video pause event`);
    };

    const handleError = (e: Event) => {
      console.error(`[UserCamera] ${name} video error:`, e);
    };

    videoElement.addEventListener("loadstart", handleLoadStart);
    videoElement.addEventListener("loadeddata", handleLoadedData);
    videoElement.addEventListener("loadedmetadata", handleLoadedMetadata);
    videoElement.addEventListener("canplay", handleCanPlay);
    videoElement.addEventListener("canplaythrough", handleCanPlayThrough);
    videoElement.addEventListener("play", handlePlay);
    videoElement.addEventListener("playing", handlePlaying);
    videoElement.addEventListener("waiting", handleWaiting);
    videoElement.addEventListener("stalled", handleStalled);
    videoElement.addEventListener("pause", handlePause);
    videoElement.addEventListener("error", handleError);

    return () => {
      videoElement.removeEventListener("loadstart", handleLoadStart);
      videoElement.removeEventListener("loadeddata", handleLoadedData);
      videoElement.removeEventListener("loadedmetadata", handleLoadedMetadata);
      videoElement.removeEventListener("canplay", handleCanPlay);
      videoElement.removeEventListener("canplaythrough", handleCanPlayThrough);
      videoElement.removeEventListener("play", handlePlay);
      videoElement.removeEventListener("playing", handlePlaying);
      videoElement.removeEventListener("waiting", handleWaiting);
      videoElement.removeEventListener("stalled", handleStalled);
      videoElement.removeEventListener("pause", handlePause);
      videoElement.removeEventListener("error", handleError);
    };
  }, [name]);

  const toggleRemoteAudio = () => {
    if (!isLocal) {
      const newMutedState = !isAudioMuted;
      setIsAudioMuted(newMutedState);
      console.log(
        `[UserCamera] ${name} audio ${newMutedState ? "muted" : "unmuted"}`
      );
    }
  };

  const handleVideoClick = () => {
    if (!isLocal && ref.current) {
      console.log(
        `[UserCamera] User clicked on ${name} video, paused: ${ref.current.paused}, readyState: ${ref.current.readyState}, muted: ${ref.current.muted}`
      );
      if (ref.current.paused) {
        ref.current.play().catch((error) => {
          console.error(`[UserCamera] Click play failed for ${name}:`, error);
        });
      } else {
        console.log(`[UserCamera] Video ${name} is already playing`);
      }
    }
  };

  return (
    <div
      className={clsx(
        mode === "mini"
          ? "aspect-square h-fit group 2xl:rounded-[1.667vw] rounded-2xl relative flex-shrink-0 pointer-events-auto 2xl:hover:w-[10.833vw] 2xl:w-[6.944vw] sm:w-[15.625vw] w-[27.778vw] overflow-hidden"
          : "aspect-video 2xl:rounded-[2.222vw] rounded-[32px] overflow-hidden group relative pointer-events-auto max-w-full h-full self-center object-cover",
        isLocal && "order-last",
        isVideoOff ? "bg-green-500" : "bg-yellow-500/10",
        className
      )}
      style={{
        boxShadow: isSpeaking
          ? `0 4px 40px 0 rgba(15,16,17,0.1), 0 2px 2px 0 rgba(0,0,0,0.06), 0 0 0 ${
              window.innerWidth >= 1536 ? "0.139vw" : "2px"
            } rgba(34, 197, 94, ${ringOpacity})`
          : `0 4px 40px 0 rgba(15,16,17,0.1), 0 2px 2px 0 rgba(0,0,0,0.06), 0 0 0 ${
              window.innerWidth >= 1536 ? "0.069vw" : "1px"
            } rgba(255, 255, 255, 0.3)`,
        transition:
          mode === "mini"
            ? "box-shadow 0.1s ease-out, width 0.3s, background-color 0.3s"
            : undefined,
      }}
      onClick={handleVideoClick}
    >
      {isLocal && <Admin className="absolute top-0 right-0" />}

      <div
        key="name"
        className="absolute whitespace-nowrap transition-opacity duration-300 group-hover:opacity-100 opacity-0 text-white button-s top-[0.556vw] left-1/2 translate-x-[-50%] px-[0.556vw] py-[0.278vw] rounded-full bg-[#14141440] backdrop-blur-[4px]"
      >
        {name}
      </div>

      {/* Заглушка когда нет видео */}
      {(!mediaStream || isVideoOff) && (
        <div className="flex absolute inset-0 justify-center items-center bg-gradient-to-br from-gray-700 to-gray-900">
          <div className="flex flex-col gap-2 items-center text-white/60">
            <div className="2xl:size-[2.778vw] size-10">
              <VideoOffFilledIcon />
            </div>
            <span className="text-xs">Нет видео</span>
          </div>
        </div>
      )}

      <video
        ref={ref}
        className={clsx(
          "object-cover size-full",
          isLocal && "scale-x-[-1]",
          (!mediaStream || isVideoOff) && "hidden"
        )}
        autoPlay
        muted={isLocal ? true : isAudioMuted}
        playsInline
        onLoadedData={() => {
          if (!isLocal && ref.current) {
            console.log(
              `[UserCamera] onLoadedData for ${name}, attempting play, readyState: ${ref.current.readyState}`
            );
            ref.current.play().catch((error) => {
              console.error(
                `[UserCamera] onLoadedData play failed for ${name}:`,
                error
              );
            });
          }
        }}
        onLoadedMetadata={() => {
          if (!isLocal && ref.current) {
            console.log(
              `[UserCamera] onLoadedMetadata for ${name}, attempting play, readyState: ${ref.current.readyState}`
            );
            ref.current.play().catch((error) => {
              console.error(
                `[UserCamera] onLoadedMetadata play failed for ${name}:`,
                error
              );
            });
          }
        }}
        onCanPlay={() => {
          if (!isLocal && ref.current) {
            console.log(`[UserCamera] onCanPlay for ${name}, attempting play`);
            ref.current.play().catch((error) => {
              console.error(
                `[UserCamera] onCanPlay play failed for ${name}:`,
                error
              );
            });
          }
        }}
        onPlaying={() => {
          console.log(
            `[UserCamera] onPlaying for ${name} - video is actually playing!`
          );
        }}
        onClick={(e) => {
          e.stopPropagation();
          handleVideoClick();
        }}
      />

      {/* Кнопка управления звуком для удаленных участников */}
      {!isLocal && mediaStream && !isVideoOff && (
        <div
          className="absolute top-[0.556vw] right-[0.556vw] opacity-0 group-hover:opacity-100 transition-opacity duration-300"
          onMouseDown={(e) => e.stopPropagation()}
        >
          <button
            onClick={toggleRemoteAudio}
            className="2xl:size-[1.667vw] size-6 bg-[#14141426] backdrop-blur-[4px] hover:bg-[#14141440] rounded-full flex items-center justify-center transition-colors"
            title={isAudioMuted ? "Включить звук" : "Выключить звук"}
          >
            <div className="2xl:size-[0.972vw] size-3.5 text-white">
              {isAudioMuted ? <VolumeOffIcon /> : <VolumeIcon />}
            </div>
          </button>
        </div>
      )}

      {/* Элементы управления только для удаленных участников */}
      {!isLocal && (
        <UserCameraControls
          isMuted={isMuted}
          isVideoOff={isVideoOff}
          isControlDisabled={isControlDisabled}
          isAdmin={isAdmin || false}
          onMute={onMute}
          onVideoOff={onVideoOff}
          onCanControl={onCanControl}
        />
      )}
    </div>
  );
}

function UserCameraControls({
  isMuted,
  isVideoOff,
  isControlDisabled,
  isAdmin,
  onMute,
  onVideoOff,
  onCanControl,
}: UserCameraControlsProps) {
  return (
    <div className="absolute transition-[bottom] duration-300 2xl:bottom-[0.278vw] 2xl:group-hover:bottom-[0.556vw] group-hover:bottom-2 bottom-1 left-1/2 -translate-x-1/2">
      {/* Индикатор muted - показывается всегда */}
      <div
        className={clsx(
          "2xl:size-[1.667vw] size-6 bg-[#14141426] backdrop-blur-[4px] transition-opacity duration-300 rounded-full flex items-center justify-center z-10a absolute left-1/2 -translate-x-1/2 2xl:bottom-0 [0.278vw] group-hover:opacity-0",
          isMuted ? "opacity-100" : "opacity-0"
        )}
      >
        <div className="size-[0.972vw] text-white">
          <MicrophoneOffIcon />
        </div>
      </div>

      {/* Кнопки управления - только для администраторов */}
      {isAdmin && (
        <div
          className="flex gap-[0.278vw] mb-[0.278vw] group-hover:opacity-100 opacity-0 transition-opacity duration-300"
          onMouseDown={(e) => e.stopPropagation()}
        >
          <ControlButton
            icon={
              isMuted ? <MicrophoneOffFilledIcon /> : <MicrophoneFilledIcon />
            }
            size={"small"}
            disabled={false}
            onClick={onMute}
          />
          <ControlButton
            icon={isVideoOff ? <VideoOffFilledIcon /> : <VideoFilledIcon />}
            size={"small"}
            disabled={false}
            onClick={onVideoOff}
          />
          <ControlButton
            icon={
              isControlDisabled ? (
                <HandRaisedOffFilledIcon />
              ) : (
                <HandRaisedFilledIcon />
              )
            }
            size={"small"}
            disabled={false}
            onClick={onCanControl}
          />
        </div>
      )}
    </div>
  );
}
