'use client';

import Link from 'next/link';
import { forwardRef } from 'react';
import type { ReactNode, MouseEventHandler } from 'react';
import ArrowRight from 'lucide-react/dist/esm/icons/arrow-right';
import ArrowUpRight from 'lucide-react/dist/esm/icons/arrow-up-right';

export type CTAVariant = 'primary' | 'secondary' | 'ghost' | 'link';
export type CTASize = 'sm' | 'md' | 'lg';
export type CTAArrow = 'up-right' | 'right' | 'none';

type BaseProps = {
  variant?: CTAVariant;
  size?: CTASize;
  arrow?: CTAArrow;
  full?: boolean;
  children: ReactNode;
  className?: string;
  ariaLabel?: string;
};

type AnchorProps = BaseProps & {
  href: string;
  external?: boolean;
  download?: boolean | string;
  type?: never;
  onClick?: MouseEventHandler<HTMLAnchorElement>;
  disabled?: never;
};

type ButtonProps = BaseProps & {
  href?: undefined;
  type?: 'button' | 'submit' | 'reset';
  onClick?: MouseEventHandler<HTMLButtonElement>;
  disabled?: boolean;
};

export type CTAButtonProps = AnchorProps | ButtonProps;

const arrowIcon = (arrow: CTAArrow, size: CTASize) => {
  if (arrow === 'none') return null;
  const px = size === 'sm' ? 12 : size === 'lg' ? 15 : 13;
  return (
    <span className="cta-arrow" aria-hidden="true">
      {arrow === 'up-right' ? <ArrowUpRight size={px} /> : <ArrowRight size={px} />}
    </span>
  );
};

const classFor = (variant: CTAVariant, size: CTASize, full: boolean, extra?: string) =>
  [
    'cta-btn',
    `cta-${variant}`,
    `cta-${size}`,
    full ? 'cta-full' : '',
    extra ?? '',
  ]
    .filter(Boolean)
    .join(' ');

export const CTAButton = forwardRef<HTMLAnchorElement | HTMLButtonElement, CTAButtonProps>(
  function CTAButton(props, ref) {
    const {
      variant = 'primary',
      size = 'md',
      arrow = 'up-right',
      full = false,
      children,
      className,
      ariaLabel,
    } = props;

    const cls = classFor(variant, size, full, className);
    const inner = (
      <>
        <span className="cta-label">{children}</span>
        {arrowIcon(arrow, size)}
      </>
    );

    if ('href' in props && props.href) {
      const isExternal = props.external || /^https?:\/\//.test(props.href);
      if (isExternal) {
        return (
          <a
            ref={ref as React.Ref<HTMLAnchorElement>}
            href={props.href}
            target="_blank"
            rel="noopener noreferrer"
            className={cls}
            data-arrow={arrow}
            aria-label={ariaLabel}
            onClick={props.onClick}
          >
            {inner}
          </a>
        );
      }
      return (
        <Link
          ref={ref as React.Ref<HTMLAnchorElement>}
          href={props.href}
          className={cls}
          data-arrow={arrow}
          aria-label={ariaLabel}
          onClick={props.onClick}
        >
          {inner}
        </Link>
      );
    }

    const btnProps = props as ButtonProps;
    return (
      <button
        ref={ref as React.Ref<HTMLButtonElement>}
        type={btnProps.type ?? 'button'}
        onClick={btnProps.onClick}
        disabled={btnProps.disabled}
        className={cls}
        data-arrow={arrow}
        aria-label={ariaLabel}
      >
        {inner}
      </button>
    );
  },
);

CTAButton.displayName = 'CTAButton';
