import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useQuery } from "@tanstack/react-query";
import { qk } from "../lib/queryKeys";
import { api } from "../lib/api";
import ChannelAboutContent from "./ChannelAbout";

const MARGIN = 8;
const POP_W = 480; // the overlay's fixed width (px)

/**
 * A channel-description cell: one truncated line in the table, revealing the FULL channel "About"
 * (the same content as the detail page's About tab — description, links, country, language, topics,
 * keywords) in a portalled glass overlay. The detail is fetched ON DEMAND on hover/focus, sharing
 * the ["channel", id] react-query cache with the channel page, so the list stays light. The overlay
 * is interactive (scrollable, links clickable) via a small hover-bridge; it closes on page scroll
 * (but not when scrolling inside itself) or resize. Shared by the subscribed + discovery tables.
 */
export default function AboutCell({ text, channelId }: { text: string | null; channelId: string }) {
  const preview = (text ?? "").trim();
  const ref = useRef<HTMLSpanElement>(null);
  const popRef = useRef<HTMLDivElement>(null);
  const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const [open, setOpen] = useState(false);
  const [coords, setCoords] = useState<{ left: number; top: number } | null>(null);

  const { data: ch } = useQuery({
    queryKey: qk.channel(channelId),
    queryFn: () => api.channelDetail(channelId),
    enabled: open && !!channelId,
    staleTime: 5 * 60_000,
  });

  function place() {
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    setCoords({
      left: Math.min(Math.max(r.left, MARGIN), window.innerWidth - POP_W - MARGIN),
      top: r.bottom + 6,
    });
  }
  function show() {
    if (hideTimer.current) {
      clearTimeout(hideTimer.current);
      hideTimer.current = null;
    }
    place();
    setOpen(true);
  }
  // Small grace period so the cursor can travel the gap from the cell to the overlay without it
  // vanishing — the overlay's own mouseenter cancels it.
  function scheduleHide() {
    if (hideTimer.current) clearTimeout(hideTimer.current);
    hideTimer.current = setTimeout(() => setOpen(false), 160);
  }
  function cancelHide() {
    if (hideTimer.current) {
      clearTimeout(hideTimer.current);
      hideTimer.current = null;
    }
  }

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

  // Close on page scroll (the fixed overlay would strand at a stale anchor) or resize — but NOT
  // when the scroll happens inside the overlay itself (it is scrollable).
  useEffect(() => {
    if (!open) return;
    const onScroll = (e: Event) => {
      if (popRef.current && e.target instanceof Node && popRef.current.contains(e.target)) return;
      setOpen(false);
    };
    const onResize = () => setOpen(false);
    window.addEventListener("scroll", onScroll, true);
    window.addEventListener("resize", onResize);
    return () => {
      window.removeEventListener("scroll", onScroll, true);
      window.removeEventListener("resize", onResize);
    };
  }, [open]);

  // Flip above the anchor if the overlay would run off the bottom of the viewport.
  useLayoutEffect(() => {
    const pop = popRef.current;
    const el = ref.current;
    if (!open || !coords || !pop || !el) return;
    const r = el.getBoundingClientRect();
    const h = pop.offsetHeight;
    if (r.bottom + 6 + h > window.innerHeight - MARGIN && r.top - 6 - h > MARGIN) {
      const top = r.top - 6 - h;
      if (Math.abs(top - coords.top) > 0.5) setCoords((c) => (c ? { ...c, top } : c));
    }
  }, [open, coords, ch]);

  if (!preview) return <span className="text-muted">—</span>;

  return (
    <span
      ref={ref}
      onMouseEnter={show}
      onMouseLeave={scheduleHide}
      onFocus={show}
      onBlur={scheduleHide}
      tabIndex={0}
      className="block max-w-[22rem] truncate text-muted cursor-help outline-none"
    >
      {preview}
      {open &&
        coords &&
        createPortal(
          <div
            ref={popRef}
            onMouseEnter={cancelHide}
            onMouseLeave={scheduleHide}
            style={{ position: "fixed", left: coords.left, top: coords.top, width: POP_W }}
            className="glass z-tooltip max-h-[28rem] overflow-y-auto px-3.5 py-3 rounded-lg animate-[fadeIn_0.12s_ease]"
          >
            {/* Full About once the detail loads; until then the list's truncated description. */}
            {ch ? (
              <ChannelAboutContent ch={ch} />
            ) : (
              <p className="text-sm whitespace-pre-wrap break-words leading-relaxed">{preview}</p>
            )}
          </div>,
          document.body,
        )}
    </span>
  );
}
