import { Button as ButtonPrimitive } from "@base-ui/react/button";
import { cva, type VariantProps } from "class-variance-authority";

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

/**
 * Brand CTA chrome, shared by the `cta*` and `link-arrow` variants
 * (`docs/brand.md` § Components > Buttons : charcoal plein, coins vifs,
 * Label-Caps).
 *
 * It neutralises the shadcn chrome carried by the `cva` base — `rounded-lg`,
 * `text-sm`/`font-medium`, `whitespace-nowrap`, the `border` hairline, the
 * `focus-visible` ring, the `active` 1px press shift and `transition-all`.
 * `cva` only concatenates, so the neutralisation is resolved by `tailwind-merge`:
 * ALWAYS wrap the result in `cn()`.
 *
 * `outline-solid` is mandatory: the base sets `--tw-outline-style: none` via
 * `outline-none`, which would otherwise swallow the `outline-2` focus ring.
 *
 * `min-h-11` gives every CTA a 44px target (WCAG 2.5.8, comfortable size).
 */
const ctaBase =
  "h-auto min-h-11 rounded-none border-0 text-label font-semibold whitespace-normal uppercase transition-none motion-safe:transition-colors active:not-aria-[haspopup]:translate-y-0 focus-visible:border-transparent focus-visible:ring-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid";

const buttonVariants = cva(
  "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
        outline:
          "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
        secondary:
          "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
        ghost:
          "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
        destructive:
          "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
        link: "text-primary underline-offset-4 hover:underline",

        /** Primary CTA: solid charcoal, gold on hover. */
        cta: `${ctaBase} bg-foreground text-background hover:bg-gold hover:text-foreground focus-visible:outline-foreground`,
        /**
         * Secondary CTA: 1px charcoal hairline, inverted on hover.
         *
         * `focus-visible:border-foreground` re-states what `ctaBase` neutralises:
         * the base kills the shadcn focus chrome with
         * `focus-visible:border-transparent`, which for this variant — the only
         * one whose border IS the button — erased the outline on keyboard focus.
         * It comes after `ctaBase` in the string, so `tailwind-merge` keeps it.
         */
        "cta-outline": `${ctaBase} border border-foreground bg-transparent text-foreground hover:bg-foreground hover:text-background focus-visible:border-foreground focus-visible:outline-foreground`,
        /** CTA laid on a dark surface (`bg-foreground`, `bg-inverse-surface`). */
        "cta-inverse": `${ctaBase} bg-background text-foreground hover:bg-gold hover:text-foreground focus-visible:outline-background`,
        /**
         * Label-Caps text link. Typography, hover and focus only — the arrow
         * itself lands with `ui/ArrowLink` (ADVMF-46).
         */
        "link-arrow": `${ctaBase} bg-transparent text-foreground hover:text-gold-text focus-visible:outline-foreground`,
      },
      size: {
        default:
          "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
        xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
        sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
        lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
        icon: "size-8",
        "icon-xs":
          "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
        "icon-sm":
          "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
        "icon-lg": "size-9",

        /**
         * CTA paddings. `size` defaults to the shadcn `default`, so a `cta*`
         * variant MUST be paired with one of these.
         */
        /** Header « Inquire ». */
        cta: "px-cta-x py-3.5",
        /** Compact CTA of the blog sidebar. */
        "cta-sm": "px-6 py-3",
        /** Hero CTAs. */
        "cta-lg": "px-6 py-4.5 lg:px-8",
        /** Wide CTA of the gallery closer. */
        "cta-xl": "gap-3 px-8 py-[17px]",
        /** Arrow link: no horizontal padding, it is a text link. */
        "cta-link": "gap-2.5 px-0 py-2",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  },
);

/**
 * For a link, style a real `<a>` / `<Link>` with `buttonVariants()` — never
 * `<Button render={<a />} nativeButton={false} />`: Base UI then forces
 * `role="button"` onto the anchor (`useButton`, `nativeButton: false` branch),
 * which destroys the link semantics for assistive technology. This is the
 * shadcn Base UI guidance.
 */
function Button({
  className,
  variant = "default",
  size = "default",
  ...props
}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
  return (
    <ButtonPrimitive
      data-slot="button"
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  );
}

/**
 * `Button` renders a native `<button>`; it is the shadcn surface for form
 * controls and future dialogs — `NewsletterForm` is its current consumer.
 * `buttonVariants` covers the CTAs that are links, which must stay anchors.
 */
export { Button, buttonVariants };
