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

import Body from '../../body';
import Button from '../../button';
import { Typography } from '../../common';
import { ButtonProps } from '../../button/Button.types';
import { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';
import { renderPromptMedia, PromptMedia } from '../helpers/promptMedia';

export type ActionPromptProps = {
  title: ReactNode;
  description?: ReactNode;
  /** @default {} */
  media?: PromptMedia;
  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://docs.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 mediaId = useId();
  const titleId = useId();
  const descId = useId();

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

  const renderMedia = () =>
    renderPromptMedia({
      media,
      sentiment,
      mediaId,
      imgClassName: 'wds-action-prompt--media-image',
    });

  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
              className="wds-action-prompt__action"
              v2
              size="md"
              priority="secondary"
              href={actionSecondary.href}
              onClick={actionSecondary?.onClick}
            >
              {actionSecondary.label}
            </Button>
          )}
          {/* @ts-expect-error onClick type mismatch */}
          <Button
            className="wds-action-prompt__action"
            v2
            size="md"
            priority="primary"
            href={action.href}
            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;
