'use client';

import { forwardRef } from 'react';
import Link from 'next/link';
import { cn } from '@/lib/utils';

type ButtonVariant = 'primary' | 'secondary' | 'ghost';
type ButtonSize = 'sm' | 'md' | 'lg';

interface ButtonBaseProps {
  variant?: ButtonVariant;
  size?: ButtonSize;
  className?: string;
  arrow?: boolean;
  children: React.ReactNode;
}

interface ButtonAsButtonProps
  extends ButtonBaseProps,
    Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof ButtonBaseProps> {
  href?: undefined;
}

interface ButtonAsLinkProps extends ButtonBaseProps {
  href: string;
  target?: string;
  rel?: string;
}

type ButtonProps = ButtonAsButtonProps | ButtonAsLinkProps;

const sizeClasses: Record<ButtonSize, string> = {
  sm: 'px-4 py-2 text-sm gap-1.5',
  md: 'px-6 py-3 text-sm gap-2',
  lg: 'px-8 py-4 text-base gap-2.5',
};

// Primary gradient is applied via inline style on the rendered element
// because bg-gradient-cta (a custom Tailwind backgroundImage utility) does not
// reliably compile in Tailwind v4 without explicit CSS variable support.
const PRIMARY_GRADIENT_STYLE: React.CSSProperties = {
  background: 'linear-gradient(135deg, #006494, #5BA4D9)',
};

const variantClasses: Record<ButtonVariant, string> = {
  primary: [
    'text-white font-medium',
    'shadow-[0_4px_16px_rgba(0,100,148,0.25)]',
    'hover:shadow-[0_8px_24px_rgba(0,100,148,0.35)]',
    'active:shadow-[0_2px_8px_rgba(0,100,148,0.2)]',
    'focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2',
  ].join(' '),
  secondary: [
    'bg-transparent text-primary-dark font-medium',
    'ring-1 ring-inset ring-primary',
    'hover:bg-primary/5',
    'active:bg-primary/10',
    'focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2',
  ].join(' '),
  ghost: [
    'bg-transparent text-on-surface font-medium',
    'hover:bg-on-surface/5',
    'active:bg-on-surface/10',
    'focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2',
  ].join(' '),
};

const baseClasses = [
  'inline-flex items-center justify-center',
  'rounded-xl',
  'transition-all duration-200 ease-out',
  'hover:-translate-y-px active:translate-y-0',
  'cursor-pointer select-none',
  'whitespace-nowrap',
  'outline-none',
  'disabled:opacity-50 disabled:pointer-events-none',
].join(' ');

const ArrowIcon = () => (
  <span aria-hidden="true" className="transition-transform duration-200 group-hover:translate-x-0.5">
    →
  </span>
);

const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  (
    {
      variant = 'primary',
      size = 'md',
      className,
      arrow = false,
      children,
      ...props
    },
    ref,
  ) => {
    const classes = cn(
      baseClasses,
      sizeClasses[size],
      variantClasses[variant],
      'group',
      className,
    );

    const gradientStyle = variant === 'primary' ? PRIMARY_GRADIENT_STYLE : undefined;

    if ('href' in props && props.href !== undefined) {
      const { href, target, rel, ...linkProps } = props as ButtonAsLinkProps;
      // Strip non-anchor props before passing to Link
      void linkProps;

      return (
        <Link
          href={href}
          target={target}
          rel={rel}
          className={classes}
          style={gradientStyle}
        >
          {children}
          {arrow && <ArrowIcon />}
        </Link>
      );
    }

    const { href: _href, ...buttonProps } = props as ButtonAsButtonProps & { href?: undefined };
    void _href;

    return (
      <button ref={ref} className={classes} style={gradientStyle} {...buttonProps}>
        {children}
        {arrow && <ArrowIcon />}
      </button>
    );
  },
);

Button.displayName = 'Button';

export default Button;
export type { ButtonProps, ButtonVariant, ButtonSize };
