import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
  type PropsWithChildren,
} from "react";
import { createPortal } from "react-dom";
import { X } from "lucide-react";
import type { Attachment } from "../../../types/post";
import { AttachmentDownloadPill } from "../AttachmentDownloadPill";
import { MessageInlineVideo } from "../MessageInlineVideo";

type OnClose = (finalTime: number) => void;

type PlayerState = {
  attachment: Attachment;
  currentTime: number;
  onClose?: OnClose;
  /** Post the video belongs to, needed for the download pill. */
  postId?: string;
} | null;

type Ctx = {
  /**
   * Open the fullscreen player. `onClose` (optional) is invoked with the
   * playhead at the moment the user dismisses the overlay, so callers can
   * sync the original inline `<video>` back to the time the user actually
   * watched until.
   */
  openVideo: (
    attachment: Attachment,
    currentTime?: number,
    onClose?: OnClose,
    postId?: string,
  ) => void;
  closeVideo: () => void;
};

const VideoPlayerContext = createContext<Ctx | null>(null);

export function useVideoPlayer(): Ctx {
  const ctx = useContext(VideoPlayerContext);
  if (!ctx)
    throw new Error("useVideoPlayer must be used inside VideoPlayerProvider");
  return ctx;
}

export function VideoPlayerProvider({ children }: PropsWithChildren) {
  const [state, setState] = useState<PlayerState>(null);

  const openVideo = useCallback(
    (
      attachment: Attachment,
      currentTime = 0,
      onClose?: OnClose,
      postId?: string,
    ) => setState({ attachment, currentTime, onClose, postId }),
    [],
  );
  const closeVideo = useCallback(() => setState(null), []);

  return (
    <VideoPlayerContext.Provider value={{ openVideo, closeVideo }}>
      {children}
      {state ? (
        <PlayerView
          attachment={state.attachment}
          startAt={state.currentTime}
          postId={state.postId}
          onClose={(finalTime) => {
            state.onClose?.(finalTime);
            setState(null);
          }}
        />
      ) : null}
    </VideoPlayerContext.Provider>
  );
}

function PlayerView({
  attachment,
  startAt,
  postId,
  onClose,
}: {
  attachment: Attachment;
  startAt: number;
  postId?: string;
  onClose: (finalTime: number) => void;
}) {
  // Track the playhead reported by the embedded `MessageInlineVideo` so we
  // can hand it back to the caller when the user dismisses the overlay.
  const lastTimeRef = useRef<number>(startAt);

  const close = useCallback(() => {
    const finalTime = Number.isFinite(lastTimeRef.current)
      ? lastTimeRef.current
      : startAt;
    onClose(finalTime);
  }, [onClose, startAt]);

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") close();
    };
    window.addEventListener("keydown", onKey);

    // iOS-compatible scroll lock: pin the body in place at the current scroll
    // offset, then restore both styles and scroll position on cleanup. Plain
    // `overflow: hidden` doesn't work on iOS Safari and can reset scroll to 0.
    const scrollY = window.scrollY;
    const body = document.body;
    const prev = {
      position: body.style.position,
      top: body.style.top,
      left: body.style.left,
      right: body.style.right,
      width: body.style.width,
      overflow: body.style.overflow,
    };
    body.style.position = "fixed";
    body.style.top = `-${scrollY}px`;
    body.style.left = "0";
    body.style.right = "0";
    body.style.width = "100%";
    body.style.overflow = "hidden";

    return () => {
      window.removeEventListener("keydown", onKey);
      body.style.position = prev.position;
      body.style.top = prev.top;
      body.style.left = prev.left;
      body.style.right = prev.right;
      body.style.width = prev.width;
      body.style.overflow = prev.overflow;
      window.scrollTo(0, scrollY);
    };
  }, [close]);

  return createPortal(
    <div
      className="fixed inset-0 z-[100] flex items-center justify-center bg-black/95"
      onClick={close}
      role="dialog"
      aria-modal="true"
    >
      {postId ? (
        <AttachmentDownloadPill
          postId={postId}
          attachment={attachment}
          size="lg"
          className="absolute left-4 top-4 z-10"
        />
      ) : null}
      <button
        type="button"
        onClick={(e) => {
          e.stopPropagation();
          close();
        }}
        className="absolute right-4 top-4 z-10 flex h-11 w-11 items-center justify-center rounded-full bg-white/10 text-white shadow-lg ring-1 ring-white/15 backdrop-blur-md transition hover:bg-white/20"
        aria-label="Close"
      >
        <X className="h-6 w-6" />
      </button>
      <div
        className="relative h-full w-full"
        onClick={(e) => e.stopPropagation()}
      >
        <MessageInlineVideo
          postId={postId ?? ""}
          attachment={attachment}
          initialTime={startAt}
          autoPlay
          hideDownload
          hideFullscreen
          size="lg"
          onTimeUpdate={(t) => {
            lastTimeRef.current = t;
          }}
        />
      </div>
    </div>,
    document.body,
  );
}
