import * as React from 'react';
import { Slot } from '@radix-ui/react-slot';
import { cva, type VariantProps } from 'class-variance-authority';

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

/**
 * shadcn "new-york" button, retuned to PIG's tokens (spec §9).
 *
 * Note `accent` in tailwind.config.js is the SUBTLE hover surface, not the
 * brand — that mapping is deliberate and documented there. So the solid CTA
 * uses `bg-brand text-accent-on`, never `bg-accent`.
 *
 * Every variant carries a 1px border (transparent where it has no colour) so
 * the variants line up to the pixel when they sit in one row; a borderless
 * ghost next to a bordered outline is otherwise 2px shorter.
 *
 * The solid CTA's hover differs by theme on purpose. In dark the fill has a
 * darker sibling (`brand/90`). In light the neon green has none — darkening it
 * reads brown — so the hover flips to the subtle ground with the text green,
 * and the accent-edge border is what keeps it reading as the same control.
 */
const buttonVariants = cva(
  'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md border border-transparent font-sans text-sm font-medium transition-colors duration-1 ease-enter focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
  {
    variants: {
      variant: {
        default:
          'border-accent-edge bg-brand text-accent-on hover:bg-accent-subtle hover:text-accent-fg dark:hover:bg-brand/90 dark:hover:text-accent-on',
        secondary: 'bg-surface-2 text-fg hover:bg-surface-3',
        outline: 'border-border-strong bg-surface text-fg hover:bg-surface-2',
        ghost: 'text-fg hover:bg-surface-2',
        subtle: 'bg-accent-subtle text-accent-fg hover:border-accent-edge',
        destructive: 'bg-danger text-danger-on hover:bg-danger/90',
        link: 'text-accent-fg underline-offset-4 hover:underline',
      },
      size: {
        // `h-9` is 36px, which is fine for a mouse and too small for a thumb.
        // Anything a phone visitor taps gets `size="touch"` or the `.tap`
        // helper on top — see SiteHeader.
        sm: 'h-8 px-3 text-[0.8125rem] [&_svg]:size-3.5',
        default: 'h-9 px-4 py-2 [&_svg]:size-4',
        lg: 'h-11 px-6 [&_svg]:size-4',
        touch: 'min-h-11 px-4 py-2 [&_svg]:size-4',
        icon: 'size-9 [&_svg]:size-4',
        'icon-touch': 'size-11 [&_svg]:size-[1.125rem]',
      },
    },
    defaultVariants: { variant: 'default', size: 'default' },
  },
);

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
}

function Button({ className, variant, size, asChild = false, ...props }: ButtonProps) {
  const Comp = asChild ? Slot : 'button';
  return <Comp className={cn(buttonVariants({ variant, size }), className)} {...props} />;
}

export { Button, buttonVariants };
