"use client";

import gsap from "gsap";
import { useCallback, useContext, useLayoutEffect, useRef } from "react";
import { SortDirection, TableSortContext } from "./tableSortContext";

const prefersReducedMotion = () =>
  typeof window !== "undefined" &&
  window.matchMedia("(prefers-reduced-motion: reduce)").matches;

/**
 * Presenter for a single sortable column header.
 *
 * Owns the interaction logic (which direction to request next) and the GSAP
 * choreography for the animated sort indicator, keeping the `table.tsx` view
 * free of side effects per the architecture guidelines.
 */
export const useSortableHeadPresenter = (
  sortKey: string,
  defaultSortOrder: SortDirection = "desc",
) => {
  const {
    sortKey: activeKey,
    sortOrder,
    onSortChange,
  } = useContext(TableSortContext);

  const isActive = activeKey === sortKey;
  const currentOrder: SortDirection = isActive
    ? sortOrder ?? defaultSortOrder
    : defaultSortOrder;

  const rootRef = useRef<HTMLButtonElement>(null);
  const pillRef = useRef<HTMLSpanElement>(null);
  const upRef = useRef<HTMLSpanElement>(null);
  const downRef = useRef<HTMLSpanElement>(null);
  const sweepRef = useRef<HTMLSpanElement>(null);
  const didMount = useRef(false);

  const handleClick = useCallback(() => {
    if (!onSortChange) return;
    const nextOrder: SortDirection = isActive
      ? currentOrder === "asc"
        ? "desc"
        : "asc"
      : defaultSortOrder;
    onSortChange(sortKey, nextOrder);
  }, [onSortChange, isActive, currentOrder, defaultSortOrder, sortKey]);

  useLayoutEffect(() => {
    const reduced = prefersReducedMotion();

    const ctx = gsap.context(() => {
      const up = upRef.current;
      const down = downRef.current;
      const pill = pillRef.current;
      const sweep = sweepRef.current;
      if (!up || !down || !pill) return;

      const activeArrow = currentOrder === "asc" ? up : down;
      const idleArrow = currentOrder === "asc" ? down : up;

      const activeOpacity = isActive ? 1 : 0.45;
      const idleOpacity = isActive ? 0.2 : 0.45;

      if (reduced) {
        gsap.set(idleArrow, { opacity: idleOpacity, y: 0, scale: 1 });
        gsap.set(activeArrow, { opacity: activeOpacity, y: 0, scale: 1 });
        return;
      }

      // Resting state for whichever chevron is not the requested direction.
      gsap.to(idleArrow, {
        opacity: idleOpacity,
        scale: 0.85,
        y: 0,
        duration: 0.3,
        ease: "power2.out",
      });

      // First paint: settle without the celebratory burst.
      if (!didMount.current) {
        didMount.current = true;
        gsap.set(activeArrow, {
          opacity: activeOpacity,
          scale: isActive ? 1 : 0.85,
          y: 0,
        });
        return;
      }

      gsap.to(activeArrow, {
        opacity: activeOpacity,
        scale: isActive ? 1 : 0.85,
        y: 0,
        duration: 0.35,
        ease: "power2.out",
      });

      if (!isActive) return;

      // Pop the pill and slide the chosen chevron in from its direction.
      gsap.fromTo(
        pill,
        { scale: 0.78 },
        { scale: 1, duration: 0.55, ease: "back.out(3.2)" },
      );
      gsap.fromTo(
        activeArrow,
        { y: currentOrder === "asc" ? 7 : -7, scale: 0.4, opacity: 0 },
        {
          y: 0,
          scale: 1,
          opacity: 1,
          duration: 0.55,
          ease: "back.out(2.6)",
        },
      );

      // A light sweep races across the indicator on every change.
      if (sweep) {
        gsap.fromTo(
          sweep,
          { xPercent: -160, opacity: 0.9 },
          { xPercent: 160, opacity: 0, duration: 0.7, ease: "power2.inOut" },
        );
      }
    }, rootRef);

    return () => ctx.revert();
  }, [isActive, currentOrder]);

  return {
    rootRef,
    pillRef,
    upRef,
    downRef,
    sweepRef,
    isActive,
    currentOrder,
    handleClick,
  };
};
