'use client';

import { useRouter } from 'next/navigation';
import type { RefObject } from 'react';
import { useCallback, useEffect, useRef } from 'react';

type UseClickableCardType<T extends HTMLElement> = {
  card: {
    ref: RefObject<T | null>;
  };
  link: {
    ref: RefObject<HTMLAnchorElement | null>;
  };
};

interface Props {
  external?: boolean;
  newTab?: boolean;
  scroll?: boolean;
}

function useClickableCard<T extends HTMLElement>({
  external = false,
  newTab = false,
  scroll = true,
}: Props): UseClickableCardType<T> {
  const router = useRouter();
  const card = useRef<T>(null);
  const link = useRef<HTMLAnchorElement>(null);
  const timeDown = useRef<number>(0);
  const hasActiveParent = useRef<boolean>(false);
  const pressedButton = useRef<number>(0);

  const handleMouseDown = useCallback(
    (e: MouseEvent) => {
      if (e.target) {
        const target = e.target as Element;

        const timeNow = +new Date();
        const parent = target?.closest('a');

        pressedButton.current = e.button;

        if (!parent) {
          hasActiveParent.current = false;
          timeDown.current = timeNow;
        } else {
          hasActiveParent.current = true;
        }
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [router, card, link, timeDown]
  );

  const handleMouseUp = useCallback(
    (e: MouseEvent) => {
      if (link.current?.href) {
        const timeNow = +new Date();
        const difference = timeNow - timeDown.current;

        if (link.current?.href && difference <= 250) {
          if (!hasActiveParent.current && pressedButton.current === 0 && !e.ctrlKey) {
            if (external) {
              const target = newTab ? '_blank' : '_self';
              window.open(link.current.href, target);
            } else {
              router.push(link.current.href, { scroll });
            }
          }
        }
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [router, card, link, timeDown]
  );

  useEffect(() => {
    const cardNode = card.current;

    const abortController = new AbortController();

    if (cardNode) {
      cardNode.addEventListener('mousedown', handleMouseDown, {
        signal: abortController.signal,
      });
      cardNode.addEventListener('mouseup', handleMouseUp, {
        signal: abortController.signal,
      });
    }

    return () => {
      abortController.abort();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [card, link, router]);

  return {
    card: {
      ref: card,
    },
    link: {
      ref: link,
    },
  };
}

export default useClickableCard;
