import { forwardRef, type ReactNode } from 'react';
import { Text, View, type TextProps, type ViewProps } from 'react-native';
import { Check, CheckIndeterminateSmall } from '@cdx-ui/icons';
import {
  CheckboxRoot as CheckboxRootPrimitive,
  CheckboxGroup as CheckboxGroupPrimitive,
  Slot,
  dataAttributes,
  mergeDataAttributes,
  useCheckboxContext,
  type ICheckboxProps,
} from '@cdx-ui/primitives';
import { cn } from '@cdx-ui/utils';
import { Icon, IconProps } from '../Icon';
import {
  checkboxGroupVariants,
  checkboxIconVariants,
  checkboxIndicatorVariants,
  checkboxLabelVariants,
  checkboxRootVariants,
} from './styles';

// =============================================================================
// CHECKBOX ROOT
// =============================================================================

export interface CheckboxProps extends ICheckboxProps {
  className?: string;
  children?: ReactNode;
}

const CheckboxRoot = forwardRef<View, CheckboxProps>(
  ({ className, isIndeterminate, children, style, ...props }, ref) => {
    const computedClassName = cn(checkboxRootVariants(), className);

    return (
      <CheckboxRootPrimitive
        ref={ref as any}
        className={computedClassName}
        isIndeterminate={isIndeterminate}
        style={style}
        {...props}
        {...mergeDataAttributes(props, dataAttributes({ slot: 'checkbox' }))}
      >
        <CheckboxIndicator>
          <CheckboxIconSlot isIndeterminate={isIndeterminate} />
        </CheckboxIndicator>
        {children}
      </CheckboxRootPrimitive>
    );
  },
);

CheckboxRoot.displayName = 'Checkbox';

// =============================================================================
// CHECKBOX INDICATOR (styled-only, reads context for data-* styling)
// =============================================================================

/** Compound check × invalid × active state for native Uniwind selectors (single data-field-state). */
const INDICATOR_STATES = {
  'unchecked:false:false': 'idle',
  'unchecked:true:false': 'invalid',
  'unchecked:false:true': 'active',
  'unchecked:true:true': 'invalid-active',
  'checked:false:false': 'checked',
  'checked:true:false': 'checked-invalid',
  'checked:false:true': 'checked-active',
  'checked:true:true': 'checked-invalid-active',
  'indeterminate:false:false': 'indeterminate',
  'indeterminate:true:false': 'indeterminate-invalid',
  'indeterminate:false:true': 'indeterminate-active',
  'indeterminate:true:true': 'indeterminate-invalid-active',
} as const;

export interface CheckboxIndicatorProps extends ViewProps {
  asChild?: boolean;
  className?: string;
  children?: ReactNode;
}

const CheckboxIndicator = forwardRef<View, CheckboxIndicatorProps>(
  ({ asChild, className, children, style, ...props }, ref) => {
    const {
      isChecked,
      isDisabled,
      isHovered,
      isInvalid,
      isReadOnly,
      isPressed,
      isFocused,
      isIndeterminate,
      isFocusVisible,
    } = useCheckboxContext();

    const checkState = isIndeterminate ? 'indeterminate' : isChecked ? 'checked' : 'unchecked';
    const fieldState =
      INDICATOR_STATES[
        `${checkState}:${isInvalid ? 'true' : 'false'}:${isPressed ? 'true' : 'false'}`
      ];

    const computedClassName = cn(checkboxIndicatorVariants(), className);
    const Comp = asChild ? Slot : View;

    return (
      <Comp
        ref={ref}
        className={computedClassName}
        style={style}
        {...props}
        {...mergeDataAttributes(
          props,
          dataAttributes({
            slot: 'checkbox-indicator',
            hover: isHovered,
            checked: isChecked,
            disabled: isDisabled,
            focusVisible: isFocusVisible,
            invalid: isInvalid,
            readonly: isReadOnly,
            active: isPressed,
            focused: isFocused,
            indeterminate: isIndeterminate,
            fieldState,
          }),
        )}
      >
        {children}
      </Comp>
    );
  },
);

CheckboxIndicator.displayName = 'Checkbox.Indicator';

// =============================================================================
// CHECKBOX ICON (styled-only, reads context for conditional mount)
// =============================================================================

export interface CheckboxIconProps extends Omit<IconProps, 'children'> {}

const CheckboxIcon = ({ className, style, ...props }: CheckboxIconProps) => {
  const computedClassName = cn(checkboxIconVariants(), className);

  return (
    <Icon
      className={computedClassName}
      style={style}
      {...props}
      {...mergeDataAttributes(props, dataAttributes({ slot: 'checkbox-icon' }))}
    />
  );
};

CheckboxIcon.displayName = 'Checkbox.Icon';

// Internal helper that reads context for conditional rendering
const CheckboxIconSlot = ({
  isIndeterminate: isIndeterminateProp,
}: {
  isIndeterminate?: boolean;
}) => {
  const { isChecked, isIndeterminate } = useCheckboxContext();
  const showIcon = isChecked || isIndeterminateProp || isIndeterminate;

  if (!showIcon) return null;

  return (
    <CheckboxIcon as={isIndeterminate || isIndeterminateProp ? CheckIndeterminateSmall : Check} />
  );
};

// =============================================================================
// CHECKBOX LABEL (styled-only)
// =============================================================================

export interface CheckboxLabelProps extends TextProps {
  asChild?: boolean;
  className?: string;
  children?: ReactNode;
}

const CheckboxLabel = forwardRef<Text, CheckboxLabelProps>(
  ({ asChild, className, children, style, ...props }, ref) => {
    const { isDisabled } = useCheckboxContext();
    const computedClassName = cn(checkboxLabelVariants(), className);
    const Comp = asChild ? Slot : Text;

    return (
      <Comp
        ref={ref}
        className={computedClassName}
        style={style}
        {...props}
        {...mergeDataAttributes(
          props,
          dataAttributes({
            slot: 'checkbox-label',
            disabled: isDisabled,
          }),
        )}
      >
        {children}
      </Comp>
    );
  },
);

CheckboxLabel.displayName = 'Checkbox.Label';

// =============================================================================
// CHECKBOX GROUP (wraps the primitive)
// =============================================================================

export interface CheckboxGroupProps extends ViewProps {
  className?: string;
  children?: ReactNode;
  value?: string[];
  onChange?: (value: string[]) => void;
  isDisabled?: boolean;
  isInvalid?: boolean;
  isReadOnly?: boolean;
  direction?: 'column' | 'row';
}

const CheckboxGroup = forwardRef<View, CheckboxGroupProps>(
  (
    {
      className,
      children,
      style,
      direction = 'column',
      value,
      onChange,
      isDisabled,
      isInvalid,
      isReadOnly,
      ...viewProps
    },
    ref,
  ) => {
    const computedClassName = cn(checkboxGroupVariants({ direction }), className);

    return (
      <CheckboxGroupPrimitive
        ref={ref}
        className={computedClassName}
        style={style}
        value={value ?? []}
        onChange={onChange}
        isDisabled={isDisabled}
        isInvalid={isInvalid}
        isReadOnly={isReadOnly}
        {...mergeDataAttributes(viewProps, dataAttributes({ slot: 'checkbox-group' }))}
      >
        {children}
      </CheckboxGroupPrimitive>
    );
  },
);

CheckboxGroup.displayName = 'Checkbox.Group';

// =============================================================================
// COMPOUND COMPONENT
// =============================================================================

type CheckboxCompoundComponent = typeof CheckboxRoot & {
  Indicator: typeof CheckboxIndicator;
  Icon: typeof CheckboxIcon;
  Label: typeof CheckboxLabel;
  Group: typeof CheckboxGroup;
};

export const Checkbox = Object.assign(CheckboxRoot, {
  Indicator: CheckboxIndicator,
  Icon: CheckboxIcon,
  Label: CheckboxLabel,
  Group: CheckboxGroup,
}) as CheckboxCompoundComponent;
