import Link from "next/link";
import type { AnchorHTMLAttributes, ButtonHTMLAttributes, ReactNode } from "react";

import { cn } from "@/lib/utils";

type BaseButtonProps = {
  children: ReactNode;
  className?: string;
  size?: "sm" | "md" | "lg";
  variant?: "primary" | "secondary" | "outline" | "ghost" | "darkOutline";
};

type ButtonAsLink = BaseButtonProps & {
  href: string;
} & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "className" | "href">;

type ButtonAsButton = BaseButtonProps & {
  href?: never;
} & ButtonHTMLAttributes<HTMLButtonElement>;

const variants = {
  primary:
    "bg-primary text-white shadow-[0_14px_34px_rgb(0_105_204_/_0.24)] hover:-translate-y-0.5 hover:bg-primary-700 hover:shadow-[0_18px_42px_rgb(0_105_204_/_0.26)] focus-visible:outline-primary",
  secondary:
    "bg-[#111111] text-white shadow-[0_12px_30px_rgb(15_23_42_/_0.14)] hover:-translate-y-0.5 hover:bg-slate-800 focus-visible:outline-slate-900",
  outline:
    "border border-slate-200 bg-white/90 text-slate-900 shadow-[0_10px_28px_rgb(15_23_42_/_0.05)] hover:-translate-y-0.5 hover:border-primary/45 hover:bg-white hover:text-primary focus-visible:outline-primary",
  ghost:
    "bg-transparent text-slate-700 hover:bg-slate-100 hover:text-slate-950 focus-visible:outline-slate-500",
  darkOutline:
    "border border-white/15 bg-white/[0.055] text-white shadow-[inset_0_1px_0_rgb(255_255_255_/_0.08)] hover:-translate-y-0.5 hover:border-primary/45 hover:bg-white/[0.08] hover:text-white focus-visible:outline-primary",
};

const sizes = {
  sm: "h-9 px-3 text-sm",
  md: "h-11 px-4 text-sm",
  lg: "h-12 px-5 text-base",
};

function getButtonClassName({
  className,
  size = "md",
  variant = "primary",
}: Pick<BaseButtonProps, "className" | "size" | "variant">) {
  return cn(
    "inline-flex items-center justify-center rounded-lg font-semibold transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2",
    variants[variant],
    sizes[size],
    className,
  );
}

function ButtonLink({
  children,
  className,
  href,
  size,
  variant,
  ...linkProps
}: ButtonAsLink) {
  const isContactCta = href === "/kontakt";

  return (
    <Link
      href={href}
      className={getButtonClassName({ className, size, variant })}
      {...(isContactCta ? { "data-contact-cta": "true" } : {})}
      {...linkProps}
    >
      {children}
    </Link>
  );
}

function NativeButton({
  children,
  className,
  size,
  type = "button",
  variant,
  ...buttonProps
}: ButtonAsButton) {
  return (
    <button
      className={getButtonClassName({ className, size, variant })}
      type={type}
      {...buttonProps}
    >
      {children}
    </button>
  );
}

function isLinkButton(props: ButtonAsLink | ButtonAsButton): props is ButtonAsLink {
  return typeof props.href === "string";
}

export function Button(props: ButtonAsLink | ButtonAsButton) {
  if (isLinkButton(props)) {
    return <ButtonLink {...props} />;
  }

  return <NativeButton {...props} />;
}
