import { forwardRef, useEffect, useMemo, type ReactNode } from 'react';
import { Text, View, type TextProps } from 'react-native';
import {
  ChipRoot as ChipRootPrimitive,
  Slot,
  dataAttributes,
  mergeDataAttributes,
  type IChipProps,
} from '@cdx-ui/primitives';
import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
import { Avatar, type AvatarProps } from '../Avatar';
import { Icon, type IconProps } from '../Icon';
import { positionToDataIcon, type IconSlotPosition } from '../../utils/positionToDataIcon';
import {
  chipAvatarVariants,
  chipIconVariants,
  chipLabelVariants,
  chipRootVariants,
  type ChipVariantProps,
} from './styles';

const SCOPE = 'CHIP';

const useChipStyleContext = () => useStyleContext(SCOPE) as ChipVariantProps;

// =============================================================================
// ROOT
// =============================================================================

export type ChipVariant = 'subtle' | 'outline';

/** @deprecated Use {@link ChipVariant} (`'subtle'`) instead. */
export type ChipVariantTint = 'tint';

export type ChipColor = 'neutral' | 'action' | 'danger' | 'warning' | 'success' | 'info';

/** @deprecated Use {@link ChipColor} (`'neutral'`) instead. */
export type ChipColorDefault = 'default';

let hasWarnedChipTintVariant = false;
let hasWarnedChipDefaultColor = false;

export interface ChipProps extends IChipProps, Omit<ChipVariantProps, 'variant' | 'color'> {
  /**
   * Visual style variant.
   * @default 'subtle'
   */
  variant?:
    | ChipVariant
    /** @deprecated Use `'subtle'` instead. */
    | 'tint';
  /**
   * Color theme applied to the chip surface and content.
   * @default 'neutral'
   */
  color?:
    | ChipColor
    /** @deprecated Use `'neutral'` instead. */
    | 'default';
  className?: string;
  children?: ReactNode;
}

const ChipRoot = forwardRef<View, ChipProps>(
  (
    {
      children,
      variant: variantProp = 'subtle',
      size = 'default',
      color: colorProp = 'neutral',
      className,
      style,
      ...props
    },
    ref,
  ) => {
    useEffect(() => {
      if (__DEV__ && variantProp === 'tint' && !hasWarnedChipTintVariant) {
        hasWarnedChipTintVariant = true;
        console.warn(
          '[Chip] The `tint` variant is deprecated and will be removed in a future major release. Use `subtle` instead.',
        );
      }
    }, [variantProp]);

    useEffect(() => {
      if (__DEV__ && colorProp === 'default' && !hasWarnedChipDefaultColor) {
        hasWarnedChipDefaultColor = true;
        console.warn(
          '[Chip] The `default` color is deprecated and will be removed in a future major release. Use `neutral` instead.',
        );
      }
    }, [colorProp]);

    const variant = variantProp === 'tint' ? 'subtle' : variantProp;
    const color = colorProp === 'default' ? 'neutral' : colorProp;

    const parent = useParentContext();
    const ctx = useMemo(
      () => ({ ...parent, [SCOPE]: { variant, size, color } }),
      [parent, variant, size, color],
    );

    const computedClassName = cn(chipRootVariants({ variant, size, color }), className);

    return (
      <ParentContext.Provider value={ctx}>
        <ChipRootPrimitive
          ref={ref}
          className={computedClassName}
          style={style}
          {...props}
          {...mergeDataAttributes(props, dataAttributes({ slot: 'chip' }))}
        >
          {children}
        </ChipRootPrimitive>
      </ParentContext.Provider>
    );
  },
);

ChipRoot.displayName = 'Chip';

// =============================================================================
// LABEL
// =============================================================================

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

const ChipLabel = forwardRef<Text, ChipLabelProps>(
  ({ asChild, className, children, style, ...props }, ref) => {
    const { size, variant, color } = useChipStyleContext();
    const computedClassName = cn(chipLabelVariants({ size, variant, color }), className);
    const Comp = asChild ? Slot : Text;

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

ChipLabel.displayName = 'Chip.Label';

// =============================================================================
// ICON
// =============================================================================

export interface ChipIconProps extends Omit<IconProps, 'children' | 'as'> {
  asChild?: boolean;
  /**
   * Forge icon component to render. Required unless `asChild` is set, in which
   * case the consumer's substituted element is rendered instead.
   */
  as?: IconProps['as'];
  /**
   * Position hint that emits `data-icon="inline-start"` or `data-icon="inline-end"`.
   * CVA uses this attribute to apply leading/trailing margin offsets logically
   * (RTL-aware). Omit when the icon is freely positioned within a custom layout.
   */
  position?: IconSlotPosition;
}

const ChipIcon = ({ asChild, className, style, as, position, ...props }: ChipIconProps) => {
  const { size, color } = useChipStyleContext();
  const computedClassName = cn(chipIconVariants({ size, color }), className);

  if (asChild) {
    return (
      <Slot
        className={computedClassName}
        style={style}
        {...props}
        {...mergeDataAttributes(
          props,
          dataAttributes({ slot: 'chip-icon' }),
          positionToDataIcon(position),
        )}
      />
    );
  }

  if (!as) {
    return null;
  }

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

ChipIcon.displayName = 'Chip.Icon';

// =============================================================================
// AVATAR
// =============================================================================

export interface ChipAvatarProps extends Omit<AvatarProps, 'size'> {}

const ChipAvatar = ({ className, style, children, ...props }: ChipAvatarProps) => {
  const { size } = useChipStyleContext();
  // chipAvatarVariants sets w/h and the leading-edge negative margin.
  // Avatar renders with size="sm" (its smallest named size) but chipAvatarVariants
  // overrides the w/h via tailwind-merge so the chip size wins.
  const computedClassName = cn(chipAvatarVariants({ size }), className);

  return (
    <Avatar size="sm" className={computedClassName} style={style} {...props}>
      {children}
    </Avatar>
  );
};

ChipAvatar.displayName = 'Chip.Avatar';

// =============================================================================
// COMPOUND EXPORT
// =============================================================================

type ChipCompoundComponent = typeof ChipRoot & {
  Label: typeof ChipLabel;
  Icon: typeof ChipIcon;
  Avatar: typeof ChipAvatar;
};

export const Chip = Object.assign(ChipRoot, {
  Label: ChipLabel,
  Icon: ChipIcon,
  Avatar: ChipAvatar,
}) as ChipCompoundComponent;

export { type ChipVariantProps } from './styles';
