import { forwardRef, type ReactNode } from 'react';
import { View, type ViewProps } from 'react-native';
import { Slot, dataAttributes, mergeDataAttributes } from '@cdx-ui/primitives';
import { cn } from '@cdx-ui/utils';
import { Text, type TextProps } from '../Text';
import { dividerLabelVariants, dividerLineVariants, dividerRootVariants } from './styles';

const lineA11yProps = {
  accessibilityElementsHidden: true,
  importantForAccessibility: 'no-hide-descendants' as const,
  'aria-hidden': true,
};

export interface DividerProps extends ViewProps {
  className?: string;
  /** Renders a vertical divider instead of the default horizontal orientation. */
  vertical?: boolean;
  children?: ReactNode;
}

export interface DividerLabelProps extends TextProps {
  asChild?: boolean;
  className?: string;
}

const DividerLine = ({ vertical, flex }: { vertical: boolean; flex: boolean }) => (
  <View className={dividerLineVariants({ vertical, flex })} {...lineA11yProps} />
);

const DividerRoot = forwardRef<View, DividerProps>(
  ({ vertical = false, className, style, children, ...props }, ref) => {
    const hasLabel = !!children;
    const computedClassName = cn(dividerRootVariants({ vertical, hasLabel }), className);

    if (!hasLabel) {
      return (
        <View
          ref={ref}
          className={computedClassName}
          style={style}
          {...props}
          {...mergeDataAttributes(props, dataAttributes({ slot: 'divider' }))}
          {...lineA11yProps}
        >
          <DividerLine vertical={vertical} flex={false} />
        </View>
      );
    }

    return (
      <View
        ref={ref}
        className={computedClassName}
        style={style}
        {...props}
        {...mergeDataAttributes(props, dataAttributes({ slot: 'divider' }))}
      >
        <DividerLine vertical={vertical} flex />
        {children}
        <DividerLine vertical={vertical} flex />
      </View>
    );
  },
);

DividerRoot.displayName = 'Divider';

const DividerLabel = forwardRef<Text, DividerLabelProps>(
  ({ asChild, className, style, children, ...props }, ref) => {
    const Comp = asChild ? Slot : Text;

    return (
      <Comp
        ref={ref}
        className={cn(dividerLabelVariants(), className)}
        style={style}
        {...props}
        {...mergeDataAttributes(props, dataAttributes({ slot: 'divider-label' }))}
      >
        {children}
      </Comp>
    );
  },
);

DividerLabel.displayName = 'Divider.Label';

type DividerCompoundComponent = typeof DividerRoot & {
  Label: typeof DividerLabel;
};

export const Divider = Object.assign(DividerRoot, {
  Label: DividerLabel,
}) as DividerCompoundComponent;
