'use client';

import * as React from 'react';
import { ToggleGroup as ToggleGroupPrimitive } from '@base-ui-components/react/toggle-group';
import { Toggle as TogglePrimitive } from '@base-ui-components/react/toggle';
import {
  type HTMLMotionProps,
  type Transition,
  motion,
  AnimatePresence,
} from 'motion/react';
import { cva, type VariantProps } from 'class-variance-authority';

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

const toggleVariants = cva(
  "cursor-pointer inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:text-muted-foreground text-accent-foreground transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 data-[pressed]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none focus:outline-none aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
  {
    variants: {
      type: {
        single: '',
        multiple: 'data-[pressed]:bg-accent',
      },
      variant: {
        default: 'bg-transparent',
        outline: 'border border-input bg-transparent shadow-xs',
      },
      size: {
        default: 'h-9 px-2 min-w-9',
        sm: 'h-8 px-1.5 min-w-8',
        lg: 'h-10 px-2.5 min-w-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  },
);

type ToggleGroupContextProps = VariantProps<typeof toggleVariants> & {
  type?: 'single' | 'multiple';
  transition?: Transition;
  activeClassName?: string;
  globalId: string;
};

const ToggleGroupContext = React.createContext<
  ToggleGroupContextProps | undefined
>(undefined);

const useToggleGroup = (): ToggleGroupContextProps => {
  const context = React.useContext(ToggleGroupContext);
  if (!context) {
    throw new Error('useToggleGroup must be used within a ToggleGroup');
  }
  return context;
};

type ToggleGroupProps = React.ComponentProps<typeof ToggleGroupPrimitive> &
  Omit<VariantProps<typeof toggleVariants>, 'type'> & {
    transition?: Transition;
    activeClassName?: string;
  };

function ToggleGroup({
  className,
  variant,
  size,
  children,
  transition = { type: 'spring', bounce: 0, stiffness: 200, damping: 25 },
  activeClassName,
  ...props
}: ToggleGroupProps) {
  const globalId = React.useId();

  return (
    <ToggleGroupContext.Provider
      value={{
        variant,
        size,
        type: props.toggleMultiple ? 'multiple' : 'single',
        transition,
        activeClassName,
        globalId,
      }}
    >
      <ToggleGroupPrimitive
        data-slot="toggle-group"
        className={cn(
          'flex items-center justify-center gap-1 relative',
          className,
        )}
        {...props}
      >
        {children}
      </ToggleGroupPrimitive>
    </ToggleGroupContext.Provider>
  );
}

type ToggleGroupItemProps = Omit<
  React.ComponentProps<typeof TogglePrimitive>,
  'render'
> &
  Omit<VariantProps<typeof toggleVariants>, 'type'> & {
    children?: React.ReactNode;
    buttonProps?: HTMLMotionProps<'button'>;
    spanProps?: React.ComponentProps<'span'>;
  };

function ToggleGroupItem({
  ref,
  className,
  children,
  variant,
  size,
  buttonProps,
  spanProps,
  ...props
}: ToggleGroupItemProps) {
  const {
    activeClassName,
    transition,
    type,
    variant: contextVariant,
    size: contextSize,
    globalId,
  } = useToggleGroup();
  const itemRef = React.useRef<HTMLButtonElement | null>(null);
  React.useImperativeHandle(ref, () => itemRef.current as HTMLButtonElement);
  const [isActive, setIsActive] = React.useState(false);

  React.useEffect(() => {
    const node = itemRef.current;
    if (!node) return;
    const observer = new MutationObserver(() => {
      setIsActive(node.getAttribute('data-pressed') === '');
    });
    observer.observe(node, {
      attributes: true,
      attributeFilter: ['data-pressed'],
    });
    setIsActive(node.getAttribute('data-pressed') === '');
    return () => observer.disconnect();
  }, [setIsActive]);

  return (
    <TogglePrimitive
      ref={itemRef}
      {...props}
      render={
        <motion.button
          data-slot="toggle-group-item"
          initial={{ scale: 1 }}
          whileTap={{ scale: 0.9 }}
          {...buttonProps}
          className={cn('relative', buttonProps?.className)}
        >
          <span
            {...spanProps}
            {...(isActive ? { 'data-pressed': '' } : {})}
            className={cn(
              'relative z-[1]',
              toggleVariants({
                variant: variant || contextVariant,
                size: size || contextSize,
                type,
              }),
              className,
              spanProps?.className,
            )}
          >
            {children}
          </span>

          <AnimatePresence initial={false}>
            {isActive && type === 'single' && (
              <motion.span
                layoutId={`active-toggle-group-item-${globalId}`}
                data-slot="active-toggle-group-item"
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                transition={transition}
                className={cn(
                  'absolute inset-0 z-0 rounded-md bg-muted',
                  activeClassName,
                )}
              />
            )}
          </AnimatePresence>
        </motion.button>
      }
    />
  );
}

export {
  ToggleGroup,
  ToggleGroupItem,
  type ToggleGroupProps,
  type ToggleGroupItemProps,
};
