"use client";

import { useEffect, useRef, useState, useCallback } from "react";
import {
  Play, Pause, Volume2, VolumeX, Maximize, Minimize, Settings, SkipForward,
  Rewind, FastForward, PictureInPicture2, Subtitles, Loader2, X, AlertCircle,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { toPersianDigits } from "@/lib/poster";

export interface VideoSource {
  id?: string;
  quality: string;
  url: string;
  isHls: boolean;
}

interface VideoPlayerProps {
  sources: VideoSource[];
  title: string;
  poster?: string | null;
  gradient?: [string, string];
  onClose?: () => void;
  onNext?: () => void;
  nextLabel?: string;
}

const SPEEDS = [0.5, 0.75, 1, 1.25, 1.5, 2];

function fmtTime(s: number) {
  if (!isFinite(s) || s < 0) s = 0;
  const m = Math.floor(s / 60);
  const sec = Math.floor(s % 60);
  const h = Math.floor(m / 60);
  if (h > 0) return `${toPersianDigits(h)}:${toPersianDigits(String(m % 60).padStart(2, "0"))}:${toPersianDigits(String(sec).padStart(2, "0"))}`;
  return `${toPersianDigits(m)}:${toPersianDigits(String(sec).padStart(2, "0"))}`;
}

export function VideoPlayer({ sources, title, poster, gradient, onClose, onNext, nextLabel }: VideoPlayerProps) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const hlsRef = useRef<any>(null);
  const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  const [playing, setPlaying] = useState(false);
  const [muted, setMuted] = useState(false);
  const [volume, setVolume] = useState(1);
  const [current, setCurrent] = useState(0);
  const [duration, setDuration] = useState(0);
  const [buffered, setBuffered] = useState(0);
  const [fullscreen, setFullscreen] = useState(false);
  const [showControls, setShowControls] = useState(true);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [speed, setSpeed] = useState(1);
  const [showSettings, setShowSettings] = useState(false);
  const [showSubs, setShowSubs] = useState(false);
  const [activeQuality, setActiveQuality] = useState<string>("");
  const [pip, setPip] = useState(false);

  // Pick an initial source: prefer 1080p HLS, else first HLS, else first MP4.
  const pickInitial = useCallback((): VideoSource | undefined => {
    if (!sources.length) return undefined;
    const hls = sources.filter((s) => s.isHls);
    const mp4 = sources.filter((s) => !s.isHls);
    return hls.find((s) => s.quality === "1080p") ?? hls[0] ?? mp4.find((s) => s.quality === "1080p") ?? mp4[0] ?? sources[0];
  }, [sources]);

  const loadSource = useCallback(async (src: VideoSource) => {
    const video = videoRef.current;
    if (!video) return;
    setError(null);
    setLoading(true);
    // cleanup previous hls
    if (hlsRef.current) {
      try { hlsRef.current.destroy(); } catch {}
      hlsRef.current = null;
    }
    setActiveQuality(src.quality);

    if (src.isHls) {
      // Native HLS (Safari)
      if (video.canPlayType("application/vnd.apple.mpegurl")) {
        video.src = src.url;
      } else {
        // Use hls.js
        try {
          const { default: Hls } = await import("hls.js");
          if (Hls.isSupported()) {
            const hls = new Hls({ enableWorker: true, lowLatencyMode: false });
            hlsRef.current = hls;
            hls.loadSource(src.url);
            hls.attachMedia(video);
            hls.on(Hls.Events.ERROR, (_e: any, data: any) => {
              if (data?.fatal) {
                setError("خطا در بارگذاری استریم. لطفاً کیفیت دیگری انتخاب کنید.");
                setLoading(false);
              }
            });
          } else {
            setError("مرورگر شما از پخش این استریم پشتیبانی نمی‌کند.");
            setLoading(false);
            return;
          }
        } catch (e) {
          setError("بارگذاری پخش‌کننده HLS ناموفق بود.");
          setLoading(false);
          return;
        }
      }
    } else {
      video.src = src.url;
    }
    video.play().catch(() => {});
  }, []);

  // initial load
  useEffect(() => {
    const initial = pickInitial();
    if (initial) loadSource(initial);
    else { setError("منبع ویدئو موجود نیست."); setLoading(false); }
    return () => {
      if (hlsRef.current) { try { hlsRef.current.destroy(); } catch {} }
    };
  }, []);

  // video events
  useEffect(() => {
    const v = videoRef.current;
    if (!v) return;
    const onPlay = () => setPlaying(true);
    const onPause = () => setPlaying(false);
    const onTime = () => { setCurrent(v.currentTime); setDuration(v.duration || 0); };
    const onProgress = () => {
      if (v.buffered.length) setBuffered(v.buffered.end(v.buffered.length - 1));
    };
    const onWaiting = () => setLoading(true);
    const onPlaying = () => setLoading(false);
    const onLoaded = () => { setDuration(v.duration || 0); setLoading(false); };
    const onError = () => { setError("خطا در پخش ویدئو. ممکن است منبع در دسترس نباشد."); setLoading(false); };
    v.addEventListener("play", onPlay);
    v.addEventListener("pause", onPause);
    v.addEventListener("timeupdate", onTime);
    v.addEventListener("progress", onProgress);
    v.addEventListener("waiting", onWaiting);
    v.addEventListener("playing", onPlaying);
    v.addEventListener("loadedmetadata", onLoaded);
    v.addEventListener("canplay", onLoaded);
    v.addEventListener("error", onError);
    return () => {
      v.removeEventListener("play", onPlay);
      v.removeEventListener("pause", onPause);
      v.removeEventListener("timeupdate", onTime);
      v.removeEventListener("progress", onProgress);
      v.removeEventListener("waiting", onWaiting);
      v.removeEventListener("playing", onPlaying);
      v.removeEventListener("loadedmetadata", onLoaded);
      v.removeEventListener("canplay", onLoaded);
      v.removeEventListener("error", onError);
    };
  }, []);

  // fullscreen listener
  useEffect(() => {
    const onFs = () => setFullscreen(!!document.fullscreenElement);
    document.addEventListener("fullscreenchange", onFs);
    return () => document.removeEventListener("fullscreenchange", onFs);
  }, []);

  const togglePlay = () => {
    const v = videoRef.current;
    if (!v) return;
    if (v.paused) v.play(); else v.pause();
  };

  const toggleMute = () => {
    const v = videoRef.current;
    if (!v) return;
    v.muted = !v.muted;
    setMuted(v.muted);
  };

  const onVolume = (val: number) => {
    const v = videoRef.current;
    if (!v) return;
    v.volume = val;
    v.muted = val === 0;
    setVolume(val);
    setMuted(val === 0);
  };

  const seek = (val: number) => {
    const v = videoRef.current;
    if (!v) return;
    v.currentTime = val;
    setCurrent(val);
  };

  const skip = (delta: number) => {
    const v = videoRef.current;
    if (!v) return;
    v.currentTime = Math.max(0, Math.min(v.duration || 0, v.currentTime + delta));
  };

  const toggleFullscreen = () => {
    const el = containerRef.current;
    if (!el) return;
    if (document.fullscreenElement) document.exitFullscreen();
    else el.requestFullscreen().catch(() => {});
  };

  const togglePip = async () => {
    const v = videoRef.current;
    if (!v) return;
    try {
      if (document.pictureInPictureElement) {
        await document.exitPictureInPicture();
        setPip(false);
      } else if (document.pictureInPictureEnabled) {
        await v.requestPictureInPicture();
        setPip(true);
      }
    } catch {}
  };

  const applySpeed = (s: number) => {
    const v = videoRef.current;
    if (!v) return;
    v.playbackRate = s;
    setSpeed(s);
  };

  const changeQuality = (src: VideoSource) => {
    const v = videoRef.current;
    const resumeAt = v?.currentTime ?? 0;
    const wasPlaying = !v?.paused;
    loadSource(src).then(() => {
      if (v) {
        v.currentTime = resumeAt;
        if (wasPlaying) v.play().catch(() => {});
      }
    });
    setShowSettings(false);
  };

  const toggleSubs = () => {
    const v = videoRef.current;
    if (!v) return;
    const tracks = v.textTracks;
    for (let i = 0; i < tracks.length; i++) tracks[i].mode = tracks[i].mode === "showing" ? "hidden" : "showing";
    setShowSubs((p) => !p);
  };

  // controls auto-hide
  const pingControls = useCallback(() => {
    setShowControls(true);
    if (hideTimer.current) clearTimeout(hideTimer.current);
    hideTimer.current = setTimeout(() => {
      if (videoRef.current && !videoRef.current.paused) setShowControls(false);
    }, 3000);
  }, []);

  // keyboard
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.target instanceof HTMLInputElement) return;
      switch (e.key) {
        case " ": case "k": e.preventDefault(); togglePlay(); pingControls(); break;
        case "ArrowRight": skip(10); pingControls(); break;
        case "ArrowLeft": skip(-10); pingControls(); break;
        case "ArrowUp": onVolume(Math.min(1, volume + 0.1)); pingControls(); break;
        case "ArrowDown": onVolume(Math.max(0, volume - 0.1)); pingControls(); break;
        case "f": toggleFullscreen(); break;
        case "m": toggleMute(); pingControls(); break;
        case "p": togglePip(); break;
        case "Escape": if (onClose && !document.fullscreenElement) onClose(); break;
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [volume]);

  const pct = duration > 0 ? (current / duration) * 100 : 0;
  const bufPct = duration > 0 ? (buffered / duration) * 100 : 0;
  const bg = poster ? undefined : (gradient ? `linear-gradient(135deg, ${gradient[0]}, ${gradient[1]})` : "#000");

  return (
    <div
      ref={containerRef}
      className="relative w-full h-full bg-black flex items-center justify-center group/player"
      onMouseMove={pingControls}
      onMouseLeave={() => playing && setShowControls(false)}
      onClick={(e) => { if (e.target === e.currentTarget || e.target === videoRef.current) togglePlay(); }}
      dir="ltr"
    >
      <video
        ref={videoRef}
        className="w-full h-full object-contain"
        poster={poster ?? undefined}
        style={poster ? undefined : { background: bg }}
        playsInline
        onClick={togglePlay}
      />

      {/* Loading */}
      {loading && !error && (
        <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
          <Loader2 className="h-12 w-12 animate-spin text-primary" />
        </div>
      )}

      {/* Error */}
      {error && (
        <div className="absolute inset-0 flex flex-col items-center justify-center gap-3 bg-black/80 p-6 text-center">
          <AlertCircle className="h-12 w-12 text-destructive" />
          <p className="text-white max-w-md">{error}</p>
          {sources.length > 1 && (
            <div className="flex flex-wrap gap-2 justify-center mt-2">
              {sources.map((s) => (
                <button
                  key={s.quality}
                  onClick={() => changeQuality(s)}
                  className="rounded-lg glass-strong px-3 py-1.5 text-sm hover:bg-primary/20 transition"
                >
                  {s.quality} {s.isHls ? "HLS" : ""}
                </button>
              ))}
            </div>
          )}
        </div>
      )}

      {/* Top bar */}
      <div className={cn("absolute top-0 inset-x-0 p-4 bg-gradient-to-b from-black/80 to-transparent transition-opacity", showControls ? "opacity-100" : "opacity-0 pointer-events-none")}>
        <div className="flex items-center gap-3">
          {onClose && (
            <button onClick={onClose} className="flex h-10 w-10 items-center justify-center rounded-full bg-black/50 hover:bg-black/70 text-white transition" aria-label="بستن">
              <X className="h-5 w-5" />
            </button>
          )}
          <h3 className="text-white font-bold text-sm md:text-base truncate">{title}</h3>
        </div>
      </div>

      {/* Center play/pause big */}
      {!loading && !error && (
        <button
          onClick={togglePlay}
          className={cn(
            "absolute flex h-16 w-16 items-center justify-center rounded-full bg-black/50 backdrop-blur text-white hover:bg-primary/60 transition",
            showControls ? "opacity-100" : "opacity-0 pointer-events-none",
          )}
          aria-label={playing ? "توقف" : "پخش"}
        >
          {playing ? <Pause className="h-7 w-7 fill-white" /> : <Play className="h-7 w-7 fill-white ml-1" />}
        </button>
      )}

      {/* Bottom controls */}
      <div className={cn("absolute bottom-0 inset-x-0 p-3 md:p-4 bg-gradient-to-t from-black/90 to-transparent transition-opacity", showControls ? "opacity-100" : "opacity-0 pointer-events-none")}>
        {/* Progress bar */}
        <div className="relative w-full h-1.5 rounded-full bg-white/20 mb-3 cursor-pointer group/bar" onClick={(e) => {
          const rect = e.currentTarget.getBoundingClientRect();
          const ratio = (e.clientX - rect.left) / rect.width;
          seek(ratio * duration);
        }}>
          <div className="absolute inset-y-0 left-0 bg-white/30 rounded-full" style={{ width: `${bufPct}%` }} />
          <div className="absolute inset-y-0 left-0 bg-primary rounded-full group-hover:bg-primary" style={{ width: `${pct}%` }}>
            <div className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-1/2 h-3 w-3 rounded-full bg-primary shadow-glow opacity-0 group-hover:opacity-100" />
          </div>
        </div>

        <div className="flex items-center gap-2 md:gap-3">
          <button onClick={togglePlay} className="text-white hover:text-primary transition" aria-label="پخش/توقف">
            {playing ? <Pause className="h-5 w-5 fill-white" /> : <Play className="h-5 w-5 fill-white" />}
          </button>
          <button onClick={() => skip(-10)} className="text-white hover:text-primary transition" aria-label="عقب ۱۰ ثانیه">
            <Rewind className="h-5 w-5" />
          </button>
          <button onClick={() => skip(10)} className="text-white hover:text-primary transition" aria-label="جلو ۱۰ ثانیه">
            <FastForward className="h-5 w-5" />
          </button>

          <div className="flex items-center gap-1.5">
            <button onClick={toggleMute} className="text-white hover:text-primary transition" aria-label="بی‌صدا">
              {muted || volume === 0 ? <VolumeX className="h-5 w-5" /> : <Volume2 className="h-5 w-5" />}
            </button>
            <input
              type="range" min={0} max={1} step={0.05} value={muted ? 0 : volume}
              onChange={(e) => onVolume(Number(e.target.value))}
              className="peep-range w-16 md:w-24 hidden sm:block"
              aria-label="صدا"
            />
          </div>

          <span className="text-xs text-white/80 tabular-nums hidden sm:inline">
            {fmtTime(current)} / {fmtTime(duration)}
          </span>

          <div className="flex-1" />

          {/* Subtitles */}
          <button onClick={toggleSubs} className={cn("text-white hover:text-primary transition", showSubs && "text-accent")} aria-label="زیرنویس">
            <Subtitles className="h-5 w-5" />
          </button>

          {/* Settings */}
          <div className="relative">
            <button onClick={() => setShowSettings((p) => !p)} className="text-white hover:text-primary transition" aria-label="تنظیمات">
              <Settings className={cn("h-5 w-5 transition-transform", showSettings && "rotate-45")} />
            </button>
            {showSettings && (
              <div className="absolute bottom-full mb-2 left-0 w-44 glass-strong rounded-xl p-2 shadow-xl">
                <div className="px-2 py-1 text-[10px] text-muted-foreground font-bold">کیفیت</div>
                {sources.map((s) => (
                  <button
                    key={s.quality + (s.isHls ? "-hls" : "")}
                    onClick={() => changeQuality(s)}
                    className={cn("w-full text-right px-2 py-1.5 rounded-lg text-sm hover:bg-white/10 transition flex items-center justify-between",
                      activeQuality === s.quality && "text-accent")}
                  >
                    <span>{s.quality === "2160p" ? "4K" : s.quality} {s.isHls ? "(HLS)" : ""}</span>
                    {activeQuality === s.quality && <span className="text-accent">✓</span>}
                  </button>
                ))}
                <div className="border-t border-border my-1" />
                <div className="px-2 py-1 text-[10px] text-muted-foreground font-bold">سرعت پخش</div>
                <div className="grid grid-cols-3 gap-1 px-1 pb-1">
                  {SPEEDS.map((sp) => (
                    <button
                      key={sp}
                      onClick={() => applySpeed(sp)}
                      className={cn("rounded-md py-1 text-xs hover:bg-white/10 transition",
                        speed === sp ? "bg-primary text-white" : "text-white/80")}
                    >
                      {toPersianDigits(sp)}x
                    </button>
                  ))}
                </div>
              </div>
            )}
          </div>

          {onNext && (
            <button onClick={onNext} className="text-white hover:text-primary transition flex items-center gap-1" aria-label={nextLabel ?? "بعدی"}>
              <SkipForward className="h-5 w-5" />
              <span className="hidden md:inline text-xs">{nextLabel ?? "بعدی"}</span>
            </button>
          )}

          <button onClick={togglePip} className={cn("text-white hover:text-primary transition hidden sm:block", pip && "text-accent")} aria-label="تصویر در تصویر">
            <PictureInPicture2 className="h-5 w-5" />
          </button>

          <button onClick={toggleFullscreen} className="text-white hover:text-primary transition" aria-label="تمام صفحه">
            {fullscreen ? <Minimize className="h-5 w-5" /> : <Maximize className="h-5 w-5" />}
          </button>
        </div>
      </div>
    </div>
  );
}
