"use client";

import { type ReactNode, useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";

interface SelectPopoverTriggerContext {
  open: boolean;
  isMobile: boolean;
  toggle: () => void;
  close: () => void;
}

interface SelectPopoverPanelContext {
  isMobile: boolean;
  close: () => void;
}

interface SelectPopoverProps {
  trigger: (ctx: SelectPopoverTriggerContext) => ReactNode;
  children: (ctx: SelectPopoverPanelContext) => ReactNode;
  sheetTitle?: string;
  disabled?: boolean;
  panelClassName?: string;
  onOpen?: () => void;
}

const MOBILE_QUERY = "(max-width: 639px)";

export function SelectPopover({
  trigger,
  children,
  sheetTitle,
  disabled = false,
  panelClassName = "",
  onOpen,
}: SelectPopoverProps) {
  type DesktopRect = {
    left: number;
    top: number;
    width: number;
    maxHeight: number;
    direction: "up" | "down";
  };

  const containerRef = useRef<HTMLDivElement | null>(null);
  const panelRef = useRef<HTMLDivElement | null>(null);
  const desktopScrollRef = useRef<HTMLDivElement | null>(null);
  const mobileScrollRef = useRef<HTMLDivElement | null>(null);
  const [open, setOpen] = useState(false);
  const [isMobile, setIsMobile] = useState(false);
  const [desktopRect, setDesktopRect] = useState<DesktopRect | null>(null);
  const isOpen = open && !disabled;

  const canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";

  useEffect(() => {
    if (typeof window === "undefined") return;

    const mq = window.matchMedia(MOBILE_QUERY);
    const handleChange = () => setIsMobile(mq.matches);
    handleChange();

    if (mq.addEventListener) {
      mq.addEventListener("change", handleChange);
      return () => mq.removeEventListener("change", handleChange);
    }

    mq.addListener(handleChange);
    return () => mq.removeListener(handleChange);
  }, []);

  useEffect(() => {
    if (!isOpen || isMobile) return;

    const handlePointerDown = (event: MouseEvent) => {
      if (canUseDOM && document.querySelector("[data-video-preview-open='true']")) {
        return;
      }

      const target = event.target as Node;
      const clickedTrigger = containerRef.current?.contains(target) ?? false;
      const clickedPanel = panelRef.current?.contains(target) ?? false;
      if (!clickedTrigger && !clickedPanel) {
        setOpen(false);
      }
    };

    document.addEventListener("mousedown", handlePointerDown);
    return () => document.removeEventListener("mousedown", handlePointerDown);
  }, [isOpen, isMobile, canUseDOM]);

  useEffect(() => {
    if (!isOpen) return;

    const handleKeyDown = (event: KeyboardEvent) => {
      const previewOpen = canUseDOM && Boolean(document.querySelector("[data-video-preview-open='true']"));
      if (event.key === "Escape" && !previewOpen) {
        setOpen(false);
      }
    };

    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [isOpen, canUseDOM]);

  useEffect(() => {
    if (isOpen) {
      onOpen?.();
    }
  }, [isOpen, onOpen]);

  useEffect(() => {
    if (!isOpen || !canUseDOM) return;

    let raf1 = 0;
    let raf2 = 0;
    const scrollSelectedIntoView = () => {
      const container = isMobile ? mobileScrollRef.current : desktopScrollRef.current;
      if (!container) return;

      const selectedEl = container.querySelector<HTMLElement>(
        "[data-popover-selected='true'], [aria-selected='true']",
      );
      selectedEl?.scrollIntoView({ block: "nearest", behavior: "auto" });
    };

    raf1 = window.requestAnimationFrame(() => {
      raf2 = window.requestAnimationFrame(scrollSelectedIntoView);
    });

    return () => {
      if (raf1) window.cancelAnimationFrame(raf1);
      if (raf2) window.cancelAnimationFrame(raf2);
    };
  }, [isOpen, isMobile, canUseDOM]);

  useEffect(() => {
    if (!isOpen || isMobile || !canUseDOM) return;

    const updateDesktopRect = () => {
      const triggerEl = containerRef.current;
      if (!triggerEl) return;

      const viewportPadding = 8;
      const gap = 8;
      const preferredMaxHeight = 352;
      const rect = triggerEl.getBoundingClientRect();
      const width = rect.width;
      const maxLeft = Math.max(viewportPadding, window.innerWidth - width - viewportPadding);
      const left = Math.min(Math.max(viewportPadding, rect.left), maxLeft);

      const spaceBelow = window.innerHeight - rect.bottom - gap - viewportPadding;
      const spaceAbove = rect.top - gap - viewportPadding;
      const openUp = spaceBelow < 220 && spaceAbove > spaceBelow;
      const direction: "up" | "down" = openUp ? "up" : "down";
      const chosenSpace = openUp ? spaceAbove : spaceBelow;
      const maxHeight = Math.max(120, Math.min(preferredMaxHeight, Math.floor(chosenSpace)));
      const top = openUp
        ? Math.max(viewportPadding, rect.top - gap)
        : Math.min(rect.bottom + gap, window.innerHeight - viewportPadding);

      setDesktopRect({ left, top, width, maxHeight, direction });
    };

    updateDesktopRect();
    window.addEventListener("resize", updateDesktopRect);
    window.addEventListener("scroll", updateDesktopRect, true);

    return () => {
      window.removeEventListener("resize", updateDesktopRect);
      window.removeEventListener("scroll", updateDesktopRect, true);
    };
  }, [isOpen, isMobile, canUseDOM]);

  const close = () => setOpen(false);
  const toggle = () => {
    if (disabled) return;
    setOpen((prev) => !prev);
  };

  const desktopPanel = canUseDOM && isOpen && !isMobile && desktopRect
    ? createPortal(
      <div
        ref={panelRef}
        className={`fixed z-[260] overflow-hidden rounded-2xl border border-white/20 bg-[#130f20]/95 backdrop-blur-md shadow-[0_20px_48px_rgba(8,10,20,0.5)] ${panelClassName}`}
        style={{
          left: desktopRect.left,
          top: desktopRect.top,
          width: desktopRect.width,
          transform: desktopRect.direction === "up" ? "translateY(-100%)" : undefined,
        }}
        role="dialog"
        aria-modal="false"
      >
        <div ref={desktopScrollRef} className="hide-scrollbar overflow-y-auto p-2" style={{ maxHeight: desktopRect.maxHeight }}>
          {children({ isMobile: false, close })}
        </div>
      </div>,
      document.body,
    )
    : null;

  const mobileSheet = canUseDOM && isOpen && isMobile
    ? createPortal(
      <div
        className="fixed inset-0 z-[220] bg-black/60"
        onMouseDown={close}
        role="dialog"
        aria-modal="true"
      >
        <div
          className="fixed inset-x-0 bottom-0 max-h-[78dvh] overflow-hidden rounded-t-3xl border-t border-white/20 bg-[#130f20]/95"
          onMouseDown={(e) => e.stopPropagation()}
        >
          <div className="mx-auto mt-2 h-1.5 w-12 rounded-full bg-white/20" />
          {sheetTitle && (
            <div className="px-5 pt-3 pb-2 text-sm font-medium text-gray-300">{sheetTitle}</div>
          )}
          <div ref={mobileScrollRef} className="hide-scrollbar max-h-[calc(78dvh-56px)] overflow-y-auto p-3">{children({ isMobile: true, close })}</div>
        </div>
      </div>,
      document.body,
    )
    : null;

  return (
    <div className="relative" ref={containerRef}>
      {trigger({ open: isOpen, isMobile, toggle, close })}
      {desktopPanel}
      {mobileSheet}
    </div>
  );
}
