"use client";

import { type ButtonProps, buttonVariants } from "@/components/ui/button";
import { defaultLocale, type Locale, transformPathLocale } from "@/lib/locale";
import { cn } from "@/lib/utils";
import Link, { type LinkProps } from "next/link";
import { useParams, useRouter } from "next/navigation";
import {
  type ComponentProps,
  forwardRef,
  MouseEvent,
  useTransition,
} from "react";

export interface NextLinkProps
  extends Pick<ComponentProps<"a">, "target">,
    Pick<LinkProps, "prefetch" | "scroll" | "onClick" | "replace">,
    Pick<
      ButtonProps,
      "className" | "style" | "variant" | "size" | "disabled" | "children"
    > {
  disabled?: boolean;
  noStyle?: boolean;
  href: string;
}

export const NextLink = forwardRef<HTMLAnchorElement, NextLinkProps>(
  (
    {
      className,
      noStyle = false,
      disabled: propDisabled,
      onClick,
      href,
      replace,
      scroll,
      variant,
      size,
      prefetch = false,
      ...props
    },
    ref
  ) => {
    const locale =
      (useParams<{ lang?: string }>()?.lang as Locale) ?? defaultLocale;
    const [navigating, startTransition] = useTransition();
    const router = useRouter();

    const disabled = navigating || !!propDisabled;

    const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {
      if (props.target) {
        return;
      }
      if (disabled) {
        event.preventDefault();
        return;
      }
      if (event.ctrlKey || event.shiftKey || event.metaKey || event.altKey) {
        event.persist();
        return;
      }
      onClick?.(event);
      if (event.defaultPrevented) {
        return;
      }
      event.preventDefault();

      startTransition(() => {
        if (replace) {
          router.replace(href, { scroll });
        } else {
          router.push(href, { scroll });
        }
      });
    };

    const isOuterLink = /^https?:\/\//.test(href);
    const isRelativeLink = !isOuterLink && !href.startsWith("/");

    return (
      <Link
        {...props}
        prefetch={prefetch}
        onClick={handleClick}
        className={cn(
          !noStyle && buttonVariants({ variant, size }),
          "cursor-pointer aria-disabled:pointer-events-none aria-disabled:opacity-50",
          navigating && "cursor-wait!",
          className
        )}
        replace={replace}
        aria-disabled={disabled}
        href={
          isOuterLink && !isRelativeLink
            ? href
            : transformPathLocale(href, locale)
        }
        scroll={scroll}
        ref={ref}
        role="button"
      />
    );
  }
);

NextLink.displayName = "NextLink";
