import { AriaAttributes, ReactNode, useId } from 'react';
import { clsx } from 'clsx';

import StatusIcon from '../../statusIcon';
import Body from '../../body';
import Button from '../../button';
import { Breakpoint, Typography } from '../../common';
import AvatarView, { AvatarViewProps } from '../../avatarView';
import Image from '../../image';
import { ButtonProps } from '../../button/Button.types';
import { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';
import { BadgeAssetsProps } from '../../badge';
import { GiftBox } from '@transferwise/icons';
import { useScreenSize } from '../../common/hooks/useScreenSize';

export type ActionPromptProps = {
  title: ReactNode;
  description?: ReactNode;
  /** @default {} */
  media?: {
    imgSrc?: string;
    avatar?: Pick<AvatarViewProps, 'imgSrc' | 'profileName' | 'profileType'> & {
      asset?: AvatarViewProps['children'];
      badge?: Pick<BadgeAssetsProps, 'flagCode'>;
    };
    'aria-label'?: string;
    'aria-hidden'?: boolean;
  };
  action: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {
    label: ButtonProps['children'];
  };
  actionSecondary?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {
    label: ButtonProps['children'];
  };
  'aria-label'?: AriaAttributes['aria-label'];
} & Pick<PrimitivePromptProps, 'id' | 'className' | 'data-testid' | 'onDismiss'> & {
    /**
     * The sentiment determines the colour scheme
     * @default 'neutral'
     */
    sentiment?: PrimitivePromptProps['sentiment'];
  };

/**
 * Use an action prompt for optional feedback that doesn't require immediate action, such as feature upsells, warnings, or suggestions. These prompts are typically used outside of core product flows (e.g., Launchpad, Recipient, or Transaction screens) and can be addressed at the user's convenience.
 *
 * If your message is about immediate user feedback (e.g., form submission errors, download failures, missing data warnings), use an [info prompt](https://storybook.wise.design/?path=/docs/prompts-infoprompt--docs) instead.
 *
 * Guidance can be found in the [design system](https://wise.design/components/action-prompt).
 */
export const ActionPrompt = ({
  sentiment = 'neutral',
  title,
  description,
  onDismiss,
  media = {},
  action,
  actionSecondary,
  id,
  className,
  'data-testid': testId,
  'aria-label': ariaLabel,
}: ActionPromptProps) => {
  const isMobile = !useScreenSize(Breakpoint.MEDIUM);

  const mediaId = useId();
  const titleId = useId();
  const descId = useId();

  const ariaLabelledByIds = [
    media['aria-hidden'] ? undefined : mediaId,
    ariaLabel ? undefined : titleId,
  ]
    .filter(Boolean)
    .join(' ');

  const renderMedia = () => {
    if (media?.imgSrc) {
      return (
        <Image
          id={mediaId}
          src={media.imgSrc}
          className="wds-action-prompt--media-image"
          alt={media['aria-label'] ?? ''}
        />
      );
    }
    if (media?.avatar) {
      const badge = media.avatar.badge
        ? media.avatar.badge
        : sentiment === 'proposition'
          ? {}
          : { status: sentiment };
      return (
        <AvatarView
          {...media.avatar}
          badge={badge}
          aria-label={media['aria-label']}
          aria-hidden={media['aria-hidden']}
          id={mediaId}
          size={48}
        >
          {media.avatar.asset}
        </AvatarView>
      );
    }
    return sentiment === 'proposition' ? (
      <AvatarView
        id={mediaId}
        size={48}
        aria-label={media['aria-label']}
        aria-hidden={media['aria-hidden']}
      >
        <GiftBox />
      </AvatarView>
    ) : (
      <StatusIcon
        id={mediaId}
        size={48}
        sentiment={sentiment}
        iconLabel={media['aria-hidden'] ? null : media['aria-label']}
      />
    );
  };

  return (
    <PrimitivePrompt
      id={id}
      sentiment={sentiment}
      data-testid={testId}
      className={clsx(
        'wds-action-prompt',
        { 'wds-action-prompt--with-two-actions': !!actionSecondary },
        className,
      )}
      media={renderMedia()}
      actions={
        <>
          {actionSecondary && (
            // @ts-expect-error onClick type mismatch
            <Button
              v2
              size="md"
              priority="secondary"
              href={actionSecondary.href}
              block={isMobile}
              onClick={actionSecondary?.onClick}
            >
              {actionSecondary.label}
            </Button>
          )}
          {/* @ts-expect-error onClick type mismatch */}
          <Button
            v2
            size="md"
            priority="primary"
            href={action.href}
            block={isMobile}
            onClick={action.onClick}
          >
            {action.label}
          </Button>
        </>
      }
      role="region"
      onDismiss={onDismiss}
      {...(ariaLabel
        ? { 'aria-label': ariaLabel }
        : {
            'aria-labelledby': ariaLabelledByIds,
            'aria-describedby': descId,
          })}
    >
      <div className={clsx('d-flex', 'flex-column', 'justify-content-center')}>
        <Body id={titleId} type={Typography.BODY_LARGE_BOLD} className="wds-action-prompt__content">
          {title}
        </Body>
        {description && (
          <Body id={descId} className="wds-action-prompt__content">
            {description}
          </Body>
        )}
      </div>
    </PrimitivePrompt>
  );
};

export default ActionPrompt;
