"use client";

import { useEffect, useRef, useState, useCallback } from "react";
import type * as embedVideo from "@/lib/lexicons/app/bsky/embed/video";
import Hls from "hls.js";
import "./BlueskyVideoPlayer.css";

interface BlueskyVideoPlayerProps {
  video: embedVideo.View;
  compact?: boolean;
}

export function BlueskyVideoPlayer({ video, compact }: BlueskyVideoPlayerProps) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const hlsRef = useRef<Hls | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  const [playing, setPlaying] = useState(false);
  const [muted, setMuted] = useState(true);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [buffering, setBuffering] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [showControls, setShowControls] = useState(true);
  const [volume, setVolume] = useState(1);
  const [isFullscreen, setIsFullscreen] = useState(false);

  const hideControlsTimeoutRef = useRef<number | null>(null);

  // Initialize HLS
  useEffect(() => {
    if (!videoRef.current) return;

    if (!Hls.isSupported()) {
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setError("Your browser does not support HLS video playback");
      return;
    }

    const hls = new Hls({
      maxMaxBufferLength: 10,
      enableWorker: true,
    });

    hlsRef.current = hls;

    hls.attachMedia(videoRef.current);
    hls.loadSource(video.playlist);

    hls.on(Hls.Events.ERROR, (_event, data) => {
      if (data.fatal) {
        if (data.details === "manifestLoadError" && data.response?.code === 404) {
          setError("Video not found");
        } else {
          setError("Error loading video");
        }
      }
    });

    return () => {
      hls.destroy();
      hlsRef.current = null;
    };
  }, [video.playlist]);

  // Video event handlers
  useEffect(() => {
    const videoElement = videoRef.current;
    if (!videoElement) return;

    const handleTimeUpdate = () => {
      setCurrentTime(videoElement.currentTime);
    };

    const handleDurationChange = () => {
      setDuration(videoElement.duration);
    };

    const handlePlay = () => {
      setPlaying(true);
      setError(null);
    };

    const handlePause = () => {
      setPlaying(false);
    };

    const handleWaiting = () => {
      setBuffering(true);
    };

    const handlePlaying = () => {
      setBuffering(false);
    };

    const handleVolumeChange = () => {
      setMuted(videoElement.muted);
      setVolume(videoElement.volume);
    };

    videoElement.addEventListener("timeupdate", handleTimeUpdate);
    videoElement.addEventListener("durationchange", handleDurationChange);
    videoElement.addEventListener("play", handlePlay);
    videoElement.addEventListener("pause", handlePause);
    videoElement.addEventListener("waiting", handleWaiting);
    videoElement.addEventListener("playing", handlePlaying);
    videoElement.addEventListener("volumechange", handleVolumeChange);

    return () => {
      videoElement.removeEventListener("timeupdate", handleTimeUpdate);
      videoElement.removeEventListener("durationchange", handleDurationChange);
      videoElement.removeEventListener("play", handlePlay);
      videoElement.removeEventListener("pause", handlePause);
      videoElement.removeEventListener("waiting", handleWaiting);
      videoElement.removeEventListener("playing", handlePlaying);
      videoElement.removeEventListener("volumechange", handleVolumeChange);
    };
  }, []);

  // Fullscreen handling
  useEffect(() => {
    const handleFullscreenChange = () => {
      setIsFullscreen(!!document.fullscreenElement);
    };

    document.addEventListener("fullscreenchange", handleFullscreenChange);
    return () => {
      document.removeEventListener("fullscreenchange", handleFullscreenChange);
    };
  }, []);

  // Auto-hide controls
  const resetControlsTimeout = useCallback(() => {
    setShowControls(true);
    if (hideControlsTimeoutRef.current) {
      clearTimeout(hideControlsTimeoutRef.current);
    }
    if (playing) {
      hideControlsTimeoutRef.current = window.setTimeout(() => {
        setShowControls(false);
      }, 2000);
    }
  }, [playing]);

  useEffect(() => {
    return () => {
      if (hideControlsTimeoutRef.current) {
        clearTimeout(hideControlsTimeoutRef.current);
      }
    };
  }, []);

  const togglePlayPause = useCallback(() => {
    if (!videoRef.current) return;

    if (videoRef.current.paused) {
      videoRef.current.play();
    } else {
      videoRef.current.pause();
    }
  }, []);

  const toggleMute = useCallback(() => {
    if (!videoRef.current) return;
    videoRef.current.muted = !videoRef.current.muted;
  }, []);

  const handleSeek = useCallback((time: number) => {
    if (!videoRef.current) return;
    videoRef.current.currentTime = time;
  }, []);

  const handleVolumeChangeHandler = useCallback((newVolume: number) => {
    if (!videoRef.current) return;
    videoRef.current.volume = newVolume;
    if (newVolume > 0) {
      videoRef.current.muted = false;
    }
  }, []);

  const toggleFullscreen = useCallback(() => {
    if (!containerRef.current) return;

    if (!document.fullscreenElement) {
      containerRef.current.requestFullscreen();
    } else {
      document.exitFullscreen();
    }
  }, []);

  const formatTime = (time: number) => {
    if (isNaN(time)) return "0:00";
    const minutes = Math.floor(time / 60);
    const seconds = Math.floor(time % 60)
      .toString()
      .padStart(2, "0");
    return `${minutes}:${seconds}`;
  };

  // Compact mode - just show thumbnail with play button
  if (compact) {
    return (
      <div className="bsky-video-compact">
        <img src={video.thumbnail} alt={video.alt || ""} className="bsky-video-compact-thumb" />
        <div className="bsky-video-play-icon">
          <svg viewBox="0 0 24 24" width="32" height="32" fill="white">
            <path d="M8 5v14l11-7z" />
          </svg>
        </div>
      </div>
    );
  }

  // Calculate aspect ratio and constrain it like Bluesky does
  let aspectRatio: number | undefined;
  const dims = video.aspectRatio;
  if (dims) {
    aspectRatio = dims.width / dims.height;
    if (Number.isNaN(aspectRatio)) {
      aspectRatio = undefined;
    }
  }

  // Constrain aspect ratio to prevent videos from being too tall
  // Use 1:2 ratio max (min aspect ratio 0.5) like Bluesky does for feeds
  const constrainedAspectRatio = aspectRatio !== undefined ? Math.max(aspectRatio, 0.5) : 16 / 9;

  if (error) {
    return (
      <div className="bsky-video-container" style={{ aspectRatio: `${constrainedAspectRatio}` }}>
        <div className="bsky-video-error">
          <div className="bsky-video-error-text">{error}</div>
        </div>
      </div>
    );
  }

  return (
    <div
      ref={containerRef}
      className="bsky-video-container"
      style={{ aspectRatio: `${constrainedAspectRatio}` }}
      onMouseMove={resetControlsTimeout}
      onMouseLeave={() => setShowControls(false)}
    >
      <video
        ref={videoRef}
        poster={video.thumbnail}
        playsInline
        preload="metadata"
        muted={muted}
        className="bsky-video-element"
        onClick={togglePlayPause}
      />

      {/* Play overlay (when paused) */}
      {!playing && !buffering && (
        <div className="bsky-video-play-overlay" onClick={togglePlayPause}>
          <div className="bsky-video-play-button">
            <svg viewBox="0 0 24 24" width="64" height="64" fill="white">
              <path d="M8 5v14l11-7z" />
            </svg>
          </div>
        </div>
      )}

      {/* Buffering indicator */}
      {buffering && (
        <div className="bsky-video-buffering">
          <div className="bsky-video-spinner"></div>
        </div>
      )}

      {/* Controls */}
      <div className={`bsky-video-controls ${showControls || !playing ? "visible" : ""}`}>
        {/* Seek bar */}
        <div className="bsky-video-seek-container">
          <input
            type="range"
            min="0"
            max={duration || 100}
            value={currentTime}
            onChange={(e) => handleSeek(parseFloat(e.target.value))}
            className="bsky-video-seek-bar"
          />
        </div>

        {/* Bottom controls */}
        <div className="bsky-video-controls-bottom">
          {/* Play/Pause */}
          <button
            className="bsky-video-control-btn"
            onClick={togglePlayPause}
            aria-label={playing ? "Pause" : "Play"}
          >
            {playing ? (
              <svg viewBox="0 0 24 24" width="20" height="20" fill="white">
                <path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z" />
              </svg>
            ) : (
              <svg viewBox="0 0 24 24" width="20" height="20" fill="white">
                <path d="M8 5v14l11-7z" />
              </svg>
            )}
          </button>

          {/* Volume */}
          <div className="bsky-video-volume-container">
            <button
              className="bsky-video-control-btn"
              onClick={toggleMute}
              aria-label={muted ? "Unmute" : "Mute"}
            >
              {muted || volume === 0 ? (
                <svg viewBox="0 0 24 24" width="20" height="20" fill="white">
                  <path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z" />
                </svg>
              ) : (
                <svg viewBox="0 0 24 24" width="20" height="20" fill="white">
                  <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z" />
                </svg>
              )}
            </button>
            <input
              type="range"
              min="0"
              max="1"
              step="0.1"
              value={muted ? 0 : volume}
              onChange={(e) => handleVolumeChangeHandler(parseFloat(e.target.value))}
              className="bsky-video-volume-slider"
            />
          </div>

          {/* Time */}
          <div className="bsky-video-time">
            {formatTime(currentTime)} / {formatTime(duration)}
          </div>

          <div style={{ flex: 1 }} />

          {/* Fullscreen */}
          <button
            className="bsky-video-control-btn"
            onClick={toggleFullscreen}
            aria-label={isFullscreen ? "Exit fullscreen" : "Fullscreen"}
          >
            {isFullscreen ? (
              <svg viewBox="0 0 24 24" width="20" height="20" fill="white">
                <path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" />
              </svg>
            ) : (
              <svg viewBox="0 0 24 24" width="20" height="20" fill="white">
                <path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" />
              </svg>
            )}
          </button>
        </div>
      </div>
    </div>
  );
}
