import type { ComponentProps } from "react";
import { useCallback, useEffect, useRef } from "react";
import { cn } from "@/shared/ui/cn";
import { Button } from "@/shared/ui/button";

export type SuggestionsProps = ComponentProps<"div">;

const SCROLL_EASING = 0.28;
const SCROLL_END_THRESHOLD = 0.5;

export const Suggestions = ({ className, children, ...props }: SuggestionsProps) => {
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const element = containerRef.current;
    if (!element) {
      return;
    }

    let animationFrameId: number | null = null;
    let targetScrollLeft = element.scrollLeft;

    const animateScroll = () => {
      const distance = targetScrollLeft - element.scrollLeft;
      if (Math.abs(distance) <= SCROLL_END_THRESHOLD) {
        element.scrollLeft = targetScrollLeft;
        animationFrameId = null;
        return;
      }

      element.scrollLeft += distance * SCROLL_EASING;
      animationFrameId = window.requestAnimationFrame(animateScroll);
    };

    const handleWheel = (event: globalThis.WheelEvent) => {
      const maxScrollLeft = element.scrollWidth - element.clientWidth;
      const rawDelta = Math.abs(event.deltaY) >= Math.abs(event.deltaX) ? event.deltaY : event.deltaX;
      const delta =
        event.deltaMode === 1
          ? rawDelta * 16
          : event.deltaMode === 2
            ? rawDelta * element.clientWidth
            : rawDelta;
      const canScroll = delta > 0 ? element.scrollLeft < maxScrollLeft : element.scrollLeft > 0;

      if (maxScrollLeft <= 0 || delta === 0 || !canScroll) {
        return;
      }

      event.preventDefault();
      targetScrollLeft = Math.min(maxScrollLeft, Math.max(0, targetScrollLeft + delta));

      if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
        element.scrollLeft = targetScrollLeft;
        return;
      }

      if (animationFrameId === null) {
        animationFrameId = window.requestAnimationFrame(animateScroll);
      }
    };

    element.addEventListener("wheel", handleWheel, { passive: false });
    return () => {
      element.removeEventListener("wheel", handleWheel);
      if (animationFrameId !== null) {
        window.cancelAnimationFrame(animationFrameId);
      }
    };
  }, []);

  return (
    <div
      ref={containerRef}
      className={cn(
        "flex w-full flex-nowrap items-center gap-2 overflow-x-auto overscroll-x-contain pb-0.5 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
        className
      )}
      {...props}
    >
      {children}
    </div>
  );
};

export type SuggestionProps = Omit<ComponentProps<typeof Button>, "onClick"> & {
  suggestion: string;
  onClick?: (suggestion: string) => void;
};

export const Suggestion = ({
  suggestion,
  onClick,
  className,
  variant = "outline",
  size = "sm",
  children,
  ...props
}: SuggestionProps) => {
  const handleClick = useCallback(() => {
    onClick?.(suggestion);
  }, [onClick, suggestion]);

  return (
    <Button
      className={cn("shrink-0 cursor-pointer rounded-full px-3.5", className)}
      onClick={handleClick}
      size={size}
      type="button"
      variant={variant}
      {...props}
    >
      {children || suggestion}
    </Button>
  );
};
