import { cva, type VariantProps } from "class-variance-authority";
import { splitProps, type JSX } from "solid-js";
import { cn } from "../../lib/cn";

export const buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 rounded-md border text-sm font-semibold transition-colors disabled:cursor-not-allowed disabled:opacity-45",
  {
    variants: {
      variant: {
        primary: "border-brand bg-brand text-white hover:border-brand-strong hover:bg-brand-strong",
        secondary: "border-line bg-white text-ink hover:bg-canvas",
        danger: "border-coral-strong bg-white text-coral-strong hover:bg-coral-soft",
      },
      size: {
        default: "min-h-10 px-4 py-2",
        small: "min-h-9 px-4 py-1.5",
      },
    },
    defaultVariants: {
      variant: "secondary",
      size: "default",
    },
  },
);

export type ButtonProps = JSX.ButtonHTMLAttributes<HTMLButtonElement> &
  VariantProps<typeof buttonVariants>;

/**
 * Standard text or icon-and-text command button.
 *
 * Size variants define a minimum target height instead of fixing the block
 * height, so wrapped labels and enlarged user fonts can grow without clipping.
 * The component defaults to `type="button"` so using it inside a form never
 * submits accidentally. Set `type="submit"` explicitly for form actions.
 */
export function Button(props: ButtonProps) {
  const [local, rest] = splitProps(props, ["variant", "size", "class", "children", "type"]);
  return (
    <button
      {...rest}
      data-slot="button"
      type={local.type ?? "button"}
      class={cn(buttonVariants({ variant: local.variant, size: local.size }), local.class)}
    >
      {local.children}
    </button>
  );
}

export const iconButtonVariants = cva(
  "inline-flex shrink-0 items-center justify-center rounded-md border border-line bg-white text-muted transition-colors hover:bg-canvas hover:text-ink disabled:cursor-not-allowed disabled:opacity-45",
  {
    variants: {
      tone: {
        default: "",
        danger: "text-coral-strong",
      },
      size: {
        default: "size-9",
        small: "size-8",
      },
    },
    defaultVariants: {
      tone: "default",
      size: "default",
    },
  },
);

export type IconButtonProps = Omit<JSX.ButtonHTMLAttributes<HTMLButtonElement>, "aria-label"> &
  VariantProps<typeof iconButtonVariants> & {
    "aria-label": string;
  };

/**
 * Square icon-only button for familiar toolbar and row actions.
 *
 * Callers must provide an accessible `aria-label`; `title` is recommended when
 * the icon's meaning benefits from a visible hover explanation.
 */
export function IconButton(props: IconButtonProps) {
  const [local, rest] = splitProps(props, ["tone", "size", "class", "children", "type"]);
  return (
    <button
      {...rest}
      data-slot="icon-button"
      type={local.type ?? "button"}
      class={cn(iconButtonVariants({ tone: local.tone, size: local.size }), local.class)}
    >
      {local.children}
    </button>
  );
}

export type IconLinkProps = Omit<JSX.AnchorHTMLAttributes<HTMLAnchorElement>, "aria-label"> &
  Pick<VariantProps<typeof iconButtonVariants>, "size"> & {
    "aria-label": string;
  };

/** Anchor counterpart to IconButton for downloads and external navigation. */
export function IconLink(props: IconLinkProps) {
  const [local, rest] = splitProps(props, ["size", "class", "children"]);
  return (
    <a
      {...rest}
      data-slot="icon-link"
      class={cn(iconButtonVariants({ size: local.size }), local.class)}
    >
      {local.children}
    </a>
  );
}
