import { type ButtonHTMLAttributes, type ReactNode } from "react";

export type ButtonVariant =
  | "default"
  | "primary"
  | "secondary"
  | "success"
  | "danger"
  | "ghost";
type ButtonSize = "sm" | "md" | "lg" | "nav";

const variantStyles: Record<ButtonVariant, string> = {
  default:
    "border border-neutral-40 bg-neutral-10 text-neutral-100 hover:bg-neutral-20 hover:border-neutral-70",
  primary:
    "bg-primary-500 text-neutral-10 hover:bg-primary-700",
  secondary:
    "bg-secondary-500 text-neutral-10 hover:bg-secondary-700",
  success:
    "bg-success-500 text-neutral-10 hover:bg-success-700",
  danger:
    "bg-danger-500 text-neutral-10 hover:bg-danger-700",
  ghost: "bg-transparent text-neutral-80 hover:bg-neutral-20",
};

const sizeStyles: Record<ButtonSize, string> = {
  sm: "text-s-regular h-[29px] px-3 py-1.5",
  md: "text-m-regular h-10 px-3 py-1.5",
  lg: "text-l-medium h-[52px] px-4 py-2",
  nav: "text-m-medium h-auto p-0",
};

const iconSizeStyles: Record<ButtonSize, string> = {
  sm: "gap-2 [&_svg]:size-4",
  md: "gap-2 [&_svg]:size-5",
  lg: "gap-2 [&_svg]:size-5",
  nav: "gap-1 [&_svg]:size-5",
};

type SharedButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
  variant?: ButtonVariant;
  size?: ButtonSize;
};

function getButtonClassName({
  variant = "primary",
  size = "sm",
  withIcon = false,
  className,
}: {
  variant?: ButtonVariant;
  size?: ButtonSize;
  withIcon?: boolean;
  className?: string;
}) {
  return [
    "inline-flex shrink-0 cursor-pointer items-center justify-center rounded-lg transition-colors duration-150",
    "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
    variantStyles[variant],
    sizeStyles[size],
    withIcon ? iconSizeStyles[size] : "",
    className,
  ]
    .filter(Boolean)
    .join(" ");
}

export type ButtonProps = SharedButtonProps;

export function Button({
  variant = "primary",
  size = "md",
  className,
  children,
  type = "button",
  ...props
}: ButtonProps) {
  return (
    <button
      type={type}
      className={getButtonClassName({ variant, size, className })}
      {...props}
    >
      {children}
    </button>
  );
}

export type IconButtonProps = SharedButtonProps & {
  icon: ReactNode;
  iconPosition?: "start" | "end";
};

export function IconButton({
  icon,
  iconPosition = "start",
  variant = "primary",
  size = "sm",
  className,
  children,
  type = "button",
  ...props
}: IconButtonProps) {
  return (
    <button
      type={type}
      className={getButtonClassName({ variant, size, withIcon: true, className })}
      {...props}
    >
      {iconPosition === "start" ? icon : null}
      {children}
      {iconPosition === "end" ? icon : null}
    </button>
  );
}

export type ActionIconButtonVariant = "default" | "danger";

const actionIconVariantStyles: Record<ActionIconButtonVariant, string> = {
  default:
    "border border-neutral-40 bg-neutral-20 text-neutral-100 hover:bg-neutral-40/50",
  danger:
    "border border-danger-400 bg-danger-50 text-danger-400 hover:bg-danger-100",
};

export type ActionIconButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
  icon: ReactNode;
  variant?: ActionIconButtonVariant;
};

export function ActionIconButton({
  icon,
  variant = "default",
  className,
  type = "button",
  ...props
}: ActionIconButtonProps) {
  return (
    <button
      type={type}
      className={[
        "flex size-7 shrink-0 cursor-pointer items-center justify-center rounded border p-2 transition-colors duration-150",
        "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
        actionIconVariantStyles[variant],
        className,
      ]
        .filter(Boolean)
        .join(" ")}
      {...props}
    >
      {icon}
    </button>
  );
}

export type PaginationPageButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
  active?: boolean;
};

export function PaginationPageButton({
  active = false,
  className,
  children,
  type = "button",
  ...props
}: PaginationPageButtonProps) {
  return (
    <button
      type={type}
      className={[
        "text-s-medium flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors duration-150",
        "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
        active
          ? "bg-secondary-500 text-neutral-100"
          : "bg-neutral-10 text-neutral-100 hover:bg-neutral-20",
        className,
      ]
        .filter(Boolean)
        .join(" ")}
      {...props}
    >
      {children}
    </button>
  );
}

export type PaginationNavButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
  icon: ReactNode;
  iconPosition?: "start" | "end";
};

export function PaginationNavButton({
  icon,
  iconPosition = "start",
  className,
  children,
  type = "button",
  ...props
}: PaginationNavButtonProps) {
  return (
    <button
      type={type}
      className={[
        "inline-flex shrink-0 cursor-pointer items-center gap-1 rounded-md px-1 py-1",
        "text-m-medium leading-none text-neutral-80 transition-colors duration-150",
        "hover:bg-neutral-20",
        "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-40",
        "[&_svg]:block [&_svg]:size-5 [&_svg]:shrink-0",
        className,
      ]
        .filter(Boolean)
        .join(" ")}
      {...props}
    >
      {iconPosition === "start" ? icon : null}
      {children}
      {iconPosition === "end" ? icon : null}
    </button>
  );
}
