import { useEffect, useRef, useState, useCallback } from "react";
import { useSearchParams } from "react-router-dom";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { getVideoByYtId, updateProgress, createDownload, followChannelByUrl, getDownload } from "../api";

function formatDuration(s) {
  if (!s) return "";
  const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), sec = s % 60;
  if (h > 0) return `${h}:${String(m).padStart(2, "0")}:${String(sec).padStart(2, "0")}`;
  return `${m}:${String(sec).padStart(2, "0")}`;
}

function CloseIcon() {
  return (
    <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
    </svg>
  );
}

function YoutubeEmbed({ youtubeId, startAt, onTimeUpdate }) {
  useEffect(() => {
    const handler = (e) => {
      if (e.origin !== "https://www.youtube.com") return;
      try {
        const data = JSON.parse(e.data);
        if (data.event === "infoDelivery" && data.info?.currentTime != null) {
          onTimeUpdate(Math.floor(data.info.currentTime));
        }
      } catch {}
    };
    window.addEventListener("message", handler);
    return () => window.removeEventListener("message", handler);
  }, [onTimeUpdate]);

  const start = startAt > 10 ? startAt : 0;
  const src = `https://www.youtube.com/embed/${youtubeId}?autoplay=1&rel=0&modestbranding=1&enablejsapi=1&start=${start}&origin=${encodeURIComponent(window.location.origin)}`;

  return (
    <iframe
      src={src}
      className="w-full aspect-video rounded-lg bg-black"
      allow="autoplay; fullscreen; picture-in-picture"
      allowFullScreen
    />
  );
}

function LocalVideo({ src, startAt, onTimeUpdate }) {
  const ref = useRef(null);

  useEffect(() => {
    if (ref.current && startAt > 10) {
      ref.current.currentTime = startAt;
    }
  }, []); // only on mount

  return (
    <video
      ref={ref}
      src={src}
      controls
      autoPlay
      className="w-full aspect-video rounded-lg bg-black"
      onTimeUpdate={() => {
        if (ref.current) onTimeUpdate(Math.floor(ref.current.currentTime));
      }}
    />
  );
}

function DownloadProgress({ pct, status }) {
  const label = status === "pending" ? "Queued…" : `Downloading ${pct.toFixed(0)}%`;
  return (
    <div className="flex items-center gap-3">
      <div className="flex-1 h-1.5 bg-zinc-800 rounded-full overflow-hidden">
        <div
          className="h-full bg-accent rounded-full transition-all duration-500"
          style={{ width: `${pct}%` }}
        />
      </div>
      <span className="text-xs text-zinc-500 shrink-0 font-mono w-28">{label}</span>
    </div>
  );
}

export default function VideoPlayer() {
  const [params, setParams] = useSearchParams();
  const qc = useQueryClient();
  const youtubeId = params.get("play");
  const urlTitle   = params.get("pt");
  const urlChannel = params.get("pc");

  const [currentTime, setCurrentTime] = useState(0);
  const [downloadId, setDownloadId]   = useState(null);
  const saveTimerRef = useRef(null);
  const initiatedRef = useRef(null);

  // ── Video metadata ────────────────────────────────────────────────────────
  const { data: video, refetch: refetchVideo } = useQuery({
    queryKey: ["video-play", youtubeId],
    queryFn: () =>
      getVideoByYtId(youtubeId)
        .then((r) => r.data)
        .catch((err) => (err.response?.status === 404 ? null : Promise.reject(err))),
    enabled: !!youtubeId,
    staleTime: 0,
  });

  // ── Download polling ──────────────────────────────────────────────────────
  const { data: dlStatus } = useQuery({
    queryKey: ["download-status", downloadId],
    queryFn: () => getDownload(downloadId).then((r) => r.data),
    enabled: !!downloadId,
    refetchInterval: (query) => {
      const s = query.state.data?.status;
      return s === "complete" || s === "failed" ? false : 1500;
    },
  });

  // When download finishes, refetch video — local_file_url will appear once the
  // file exists on disk, which is the single source of truth for switching players
  useEffect(() => {
    if (dlStatus?.status === "complete" && !video?.local_file_url) {
      refetchVideo();
    }
  }, [dlStatus?.status]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Trigger download on open ──────────────────────────────────────────────
  const downloadMut = useMutation({
    mutationFn: (ytId) => createDownload(ytId),
    onSuccess: (res) => {
      const dl = res.data;
      setDownloadId(dl.id);
      // If already complete (pre-downloaded), refetch to get local_file_url
      if (dl.status === "complete") refetchVideo();
    },
  });

  useEffect(() => {
    if (!youtubeId || initiatedRef.current === youtubeId) return;
    initiatedRef.current = youtubeId;
    setCurrentTime(0);
    setDownloadId(null);
    const t = setTimeout(() => downloadMut.mutate(youtubeId), 200);
    return () => clearTimeout(t);
  }, [youtubeId]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Progress saving ───────────────────────────────────────────────────────
  const followMut = useMutation({
    mutationFn: () => followChannelByUrl({ youtube_channel_id: video?.channel_youtube_id }),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["channels"] }),
  });

  const handleTimeUpdate = useCallback((secs) => {
    setCurrentTime(secs);
    clearTimeout(saveTimerRef.current);
    saveTimerRef.current = setTimeout(() => {
      if (video?.id) {
        const duration = video.duration_seconds ?? 0;
        const watched = duration > 0 && secs >= duration * 0.9;
        updateProgress(video.id, { watch_progress_seconds: secs, watched });
      }
    }, 10_000);
  }, [video]);

  const close = useCallback(() => {
    setParams((p) => { p.delete("play"); p.delete("pt"); p.delete("pc"); return p; });
    clearTimeout(saveTimerRef.current);
  }, [setParams]);

  useEffect(() => {
    const handler = (e) => { if (e.key === "Escape") close(); };
    document.addEventListener("keydown", handler);
    return () => document.removeEventListener("keydown", handler);
  }, [close]);

  useEffect(() => () => clearTimeout(saveTimerRef.current), []);

  if (!youtubeId) return null;

  const title       = video?.title       ?? urlTitle   ?? youtubeId;
  const channelName = video?.channel_name ?? urlChannel;
  const startAt     = video?.watch_progress_seconds ?? 0;
  const isDownloading = dlStatus && (dlStatus.status === "pending" || dlStatus.status === "downloading");
  // local_file_url is only set by the backend when the file actually exists on disk
  const localUrl    = video?.local_file_url ?? null;
  const videoLoading = !video;

  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/85 backdrop-blur-sm p-4"
      onClick={(e) => { if (e.target === e.currentTarget) close(); }}
    >
      <div className="relative w-full max-w-4xl flex flex-col gap-3 max-h-[95vh] overflow-y-auto">

        {/* Header */}
        <div className="flex items-start justify-between gap-4">
          <div className="min-w-0">
            <h2 className="font-display font-semibold text-white text-lg leading-snug line-clamp-2">
              {title}
            </h2>
            {channelName && (
              <p className="text-sm text-zinc-400 mt-0.5">{channelName}</p>
            )}
          </div>
          <button onClick={close} className="shrink-0 text-zinc-400 hover:text-white transition-colors p-1">
            <CloseIcon />
          </button>
        </div>

        {/* Player — wait for metadata, then show local file or YouTube embed */}
        {videoLoading ? (
          <div className="w-full aspect-video rounded-lg bg-zinc-900 flex items-center justify-center">
            <svg className="w-8 h-8 animate-spin text-zinc-600" fill="none" viewBox="0 0 24 24">
              <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
              <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
            </svg>
          </div>
        ) : localUrl ? (
          <LocalVideo src={localUrl} startAt={currentTime || startAt} onTimeUpdate={handleTimeUpdate} />
        ) : (
          <YoutubeEmbed youtubeId={youtubeId} startAt={startAt} onTimeUpdate={handleTimeUpdate} />
        )}

        {/* Download progress bar (shows while downloading, disappears when done) */}
        {isDownloading && (
          <DownloadProgress
            pct={dlStatus.progress_percent ?? 0}
            status={dlStatus.status}
          />
        )}

        {/* Status / source indicator */}
        <div className="flex items-center gap-3 flex-wrap">
          {localUrl ? (
            <span className="text-xs text-accent font-medium">▶ Playing local file</span>
          ) : isDownloading ? (
            <span className="text-xs text-zinc-500">Watching on YouTube · switching to local when ready</span>
          ) : dlStatus?.status === "failed" ? (
            <span className="text-xs text-red-400">Download failed — watching on YouTube</span>
          ) : null}

          {/* Follow channel */}
          {video?.channel_youtube_id && (
            <button
              onClick={() => followMut.mutate()}
              disabled={followMut.isPending || followMut.isSuccess}
              className="ml-auto text-xs font-medium px-3 py-1.5 rounded-lg bg-zinc-800 text-zinc-300 hover:bg-zinc-700 transition-colors disabled:opacity-60"
            >
              {followMut.isSuccess ? "Following ✓" : "Follow channel"}
            </button>
          )}

          {/* Duration */}
          {video?.duration_seconds && (
            <span className="text-xs text-zinc-600 font-mono">
              {formatDuration(currentTime || startAt)} / {formatDuration(video.duration_seconds)}
            </span>
          )}
        </div>

        {/* Description */}
        {video?.description && (
          <details>
            <summary className="text-xs text-zinc-500 cursor-pointer hover:text-zinc-300 transition-colors select-none">
              Description
            </summary>
            <p className="text-sm text-zinc-400 mt-2 whitespace-pre-line leading-relaxed max-h-40 overflow-y-auto">
              {video.description}
            </p>
          </details>
        )}
      </div>
    </div>
  );
}
