import type { ReactElement } from 'react';
import React, { isValidElement } from 'react';
import type {
  ViewProps,
  ImageSourcePropType,
  ImageProps as RNImageProps,
} from 'react-native';
import type { SuccessVariant } from './StyledSuccess';
import {
  StyledSuccessImage,
  StyledSuccessContainer,
  StyledSuccessContent,
  StyledSuccessImageContainer,
  StyledSuccessTitle,
  StyledSuccessDescription,
  StyledSuccessButtonContainer,
  StyledSuccessModal,
  StyledSuccessIconContainer,
  StyledSuccessButtonSecondary,
} from './StyledSuccess';
import type { ImageProps } from '../../Image';
import { noop } from '../../../utils/functions';
import type { IllustrationName } from '../../Illustration';
import Illustration from '../../Illustration';
import Button from '../../Button';

interface SuccessProps extends ViewProps {
  /**
   * Image to be displayed.
   * @deprecated The `image` prop is deprecated and will be removed in the next major version. Use the `icon` prop instead.
   */
  image?:
    | ReactElement<ImageProps | RNImageProps>
    | ImageSourcePropType
    | string;
  /**
   * Success's title.
   */
  title: string | ReactElement;
  /**
   * Success's description.
   */
  description?: string | ReactElement;
  /**
   * Success's variant.
   */
  variant?: SuccessVariant;
  /**
   * Action button text
   */
  ctaText?: string;
  /**
   * Callback when the action button is pressed.
   */
  onCtaPress?: () => void;
  /**
   * Secondary button text.
   */
  secondaryCtaText?: string;
  /**
   * Callback when the secondary button is pressed.
   */
  onSecondaryCtaPress?: () => void;
  /**
   * Testing id of the component.
   */
  testID?: string;
  /**
   * Status icon to be displayed, this will replace the deprecated image prop.
   */
  icon?: IllustrationName;
}

const renderImage = (
  image: ReactElement<ImageProps | RNImageProps> | ImageSourcePropType | string
) => {
  if (isValidElement(image)) {
    return React.cloneElement(image, {
      testID: 'success-image',
    });
  }

  return (
    <StyledSuccessImage
      source={typeof image === 'string' ? { uri: image } : image}
      testID="success-image"
    />
  );
};

const renderImageOrIcon = ({
  image,
  icon,
}: {
  image?:
    | ReactElement<ImageProps | RNImageProps>
    | ImageSourcePropType
    | string;
  icon?: IllustrationName;
}) => {
  if (icon) {
    return (
      <StyledSuccessIconContainer>
        <Illustration name={icon} testID="success-icon" />
      </StyledSuccessIconContainer>
    );
  }

  if (image) {
    return (
      <StyledSuccessImageContainer>
        {renderImage(image)}
      </StyledSuccessImageContainer>
    );
  }

  return null;
};

const SuccessPage = ({
  variant = 'in-page',
  title,
  description,
  image,
  testID,
  ctaText,
  onCtaPress = noop,
  secondaryCtaText,
  onSecondaryCtaPress,
  icon,
  ...nativeProps
}: SuccessProps): ReactElement => {
  const showSecondaryButton = secondaryCtaText && onSecondaryCtaPress;

  return (
    <StyledSuccessContainer
      testID={testID}
      themeVariant={variant}
      {...nativeProps}
    >
      <StyledSuccessContent>
        {renderImageOrIcon({ image, icon })}
        <StyledSuccessTitle level="h4" typeface="playful">
          {title}
        </StyledSuccessTitle>
        {typeof description === 'string' ? (
          <StyledSuccessDescription>{description}</StyledSuccessDescription>
        ) : (
          description
        )}
      </StyledSuccessContent>

      {!!ctaText && (
        <StyledSuccessButtonContainer>
          <Button text={ctaText} onPress={onCtaPress} />
          {!!showSecondaryButton && (
            <StyledSuccessButtonSecondary
              variant="text"
              text={secondaryCtaText}
              onPress={onSecondaryCtaPress}
            />
          )}
        </StyledSuccessButtonContainer>
      )}
    </StyledSuccessContainer>
  );
};

/**
 * Renders success page
 *
 * @param {SuccessProps} props
 * @return {*}  {ReactElement}
 */
const Success = (props: SuccessProps): ReactElement => {
  const { variant } = props;
  if (variant === 'full-screen') {
    return (
      <StyledSuccessModal animationType="slide">
        <SuccessPage {...props} />
      </StyledSuccessModal>
    );
  }

  return <SuccessPage {...props} />;
};
export default Success;
