import { clsx } from '@trail-ui/shared-utils';
import type { CheckboxGroupSlots, CheckboxVariantProps, SlotsToClasses } from '@trail-ui/theme';
import { checkboxGroup } from '@trail-ui/theme';
import type { Orientation } from '@react-types/shared';
import { ForwardedRef, ReactNode, createContext, forwardRef, useMemo } from 'react';
import type { CheckboxGroupProps as AriaCheckboxGroupProps } from 'react-aria-components';
import { CheckboxGroup as AriaCheckboxGroup, Label, Text } from 'react-aria-components';
import { CheckboxProps } from './checkbox';
import { ErrorIcon } from '@trail-ui/icons';

export interface CheckboxGroupProps
  extends AriaCheckboxGroupProps,
    Partial<Pick<CheckboxProps, 'lineThrough' | 'isDisabled'>> {
  /**
   * The axis the checkbox group items should align with.
   * @default "vertical"
   */
  orientation?: Orientation;
  label?: ReactNode;
  description?: string;
  errorMessage?: string;
  errorId?: string;
  /**
   * Classes object to style the checkbox group and its children.
   */
  classNames?: SlotsToClasses<CheckboxGroupSlots>;
  className?: string;
}

export const CheckboxGroupThemeContext = createContext<CheckboxVariantProps>({});

function CheckboxGroup(props: CheckboxGroupProps, ref: ForwardedRef<HTMLDivElement>) {
  const {
    lineThrough,
    orientation = 'vertical',
    label,
    className,
    classNames,
    isInvalid,
    children,
    errorId,
    ...otherProps
  } = props;

  const slots = useMemo(() => checkboxGroup(), []);

  const baseStyles = clsx(classNames?.base, className);

  return (
    <AriaCheckboxGroup ref={ref} className={slots.base({ class: baseStyles })} {...otherProps}>
      {(renderProps) => (
        <>
          {label && <Label className={slots.label({ class: classNames?.label })}>{label}</Label>}
          {children && (
            <div
              data-orientation={orientation}
              className={slots.wrapper({ class: classNames?.wrapper })}
            >
              <CheckboxGroupThemeContext.Provider value={{ isInvalid, lineThrough }}>
                {typeof children === 'function' ? children(renderProps) : children}
              </CheckboxGroupThemeContext.Provider>
            </div>
          )}

          {props.errorMessage ? (
            <Text
              id={errorId}
              slot="errorMessage"
              aria-live="polite"
              elementType="div"
              className={`${slots.errorMessage({ class: classNames?.errorMessage })} flex flex-row items-center gap-0.5`}
            >
              <ErrorIcon
                role="img"
                aria-label="Error"
                aria-hidden="false"
                className="h-4 w-4 text-red-600"
              />
              {props.errorMessage}
            </Text>
          ) : props.description ? (
            <Text
              slot="description"
              className={slots.description({ class: classNames?.description })}
            >
              {props.description}
            </Text>
          ) : null}
        </>
      )}
    </AriaCheckboxGroup>
  );
}

/**
 * A checkbox group allows a user to select multiple items from a list of options.
 */
const _CheckboxGroup = forwardRef(CheckboxGroup);

export { _CheckboxGroup as CheckboxGroup };
