import type { ReactElement, ReactNode } from 'react';
import React from 'react';
import type { StyleProp, ViewStyle } from 'react-native';
import type { AvatarProps } from '../Avatar';
import {
  StyledAvatar,
  StyledSurplusContainer,
  StyledWrapper,
} from './StyledAvatarStack';
import { useAvatarColors } from './utils';

export interface AvatarStackProps extends Pick<AvatarProps, 'size'> {
  /**
   * Avatar elements to be rendered.
   */
  children: ReactElement<Omit<AvatarProps, 'size' | 'style'>>[];
  /**
   * Max avatars to show.
   */
  max?: number;
  /**
   * The total number of avatars. Used for calculating the number of extra avatars.
   */
  total?: number;
  /**
   * Custom renderer of extraAvatars.
   */
  renderSurplus?: (value: number) => ReactNode;
  /**
   * Additional style.
   */
  style?: StyleProp<ViewStyle>;
  /**
   * Testing id of the component.
   */
  testID?: string;
  /**
   * Variant of the avatar stack.
   */
  variant?: 'horizontal' | 'vertical';
}

type SurplusProps = {
  value: number;
  renderSurplus?: AvatarStackProps['renderSurplus'];
  size?: AvatarStackProps['size'];
  variant?: AvatarStackProps['variant'];
  index: number;
  backgroundColor: string;
};

const Surplus = ({
  value,
  renderSurplus,
  size,
  variant = 'horizontal',
  index,
  backgroundColor,
}: SurplusProps) => {
  if (value > 0) {
    if (renderSurplus) {
      return (
        <StyledSurplusContainer
          testID="surplus-container"
          themeSize={size}
          themeVariant={variant}
          themeIndex={index}
          style={{ backgroundColor }}
        >
          {renderSurplus(value)}
        </StyledSurplusContainer>
      );
    }

    return (
      <StyledAvatar
        testID="surplus-container"
        themeVariant={variant}
        title={`+${value}`}
        size={size}
        themeIndex={index}
        style={{ backgroundColor }}
      />
    );
  }

  return null;
};

const AvatarStack = ({
  children,
  max,
  size = 'small',
  style,
  testID,
  variant = 'horizontal',
  total,
  renderSurplus,
}: AvatarStackProps) => {
  const colors = useAvatarColors();
  const avatars = children.slice(0, max);

  const remainingAvatar = (() => {
    let remain = 0;

    // Remaining value will prioritize total prop if it exists
    if (total && total > children.length) {
      remain = total - avatars.length;
    } else if (max && children.length > max) {
      remain = children.length - max;
    }

    return remain;
  })();

  return (
    <StyledWrapper
      themeSize={size}
      themeAvatarCount={avatars.length}
      themeHasSurplus={remainingAvatar > 0}
      style={style}
      testID={testID}
      themeVariant={variant}
    >
      {avatars.map((avt, index) => (
        <StyledAvatar
          themeVariant={variant}
          {...avt.props}
          size={size}
          themeIndex={index}
          style={{ backgroundColor: colors[index % colors.length] }}
        />
      ))}

      <Surplus
        value={remainingAvatar}
        index={avatars.length}
        size={size}
        variant={variant}
        renderSurplus={renderSurplus}
        backgroundColor={colors[avatars.length % colors.length]}
      />
    </StyledWrapper>
  );
};

export default AvatarStack;
