import { Clock } from '@transferwise/icons';
import { mockMatchMedia, render, screen } from '../../test-utils';
import { InlinePrompt, InlinePromptProps } from './InlinePrompt';
import { Sentiment } from '../../common';

mockMatchMedia();

const MEDIA = <span data-testid="custom-media">Custom Media</span>;

describe('InlinePrompt', () => {
  const defaultProps: InlinePromptProps = {
    children: 'Prompt message',
  };

  it('renders children', () => {
    render(<InlinePrompt {...defaultProps}>Hello world</InlinePrompt>);
    expect(screen.getByText('Hello world')).toBeInTheDocument();
  });

  it('renders with GiftBox icon as default for `proposition` sentiment', () => {
    render(<InlinePrompt {...defaultProps} sentiment="proposition" />);
    expect(screen.getByText('Prompt message')).toBeInTheDocument();
    expect(screen.getByTestId('gift-box-icon')).toBeInTheDocument();
  });

  [
    { sentiment: Sentiment.NEGATIVE as const, statusIconLabel: 'Error:' },
    { sentiment: Sentiment.WARNING as const, statusIconLabel: 'Warning:' },
    { sentiment: Sentiment.NEUTRAL as const, statusIconLabel: 'Information:' },
    { sentiment: Sentiment.POSITIVE as const, statusIconLabel: 'Success:' },
    { sentiment: 'proposition' as const, statusIconLabel: '' },
  ].forEach(({ sentiment, statusIconLabel }) => {
    describe(sentiment, () => {
      if (statusIconLabel) {
        it('should render StatusIcon', () => {
          render(<InlinePrompt {...defaultProps} sentiment={sentiment} />);
          expect(screen.getByLabelText(statusIconLabel)).toBeInTheDocument();
        });
      }

      describe('muted state', () => {
        it('should render icon and apply css', () => {
          render(<InlinePrompt {...defaultProps} muted sentiment={sentiment} />);
          expect(screen.getByText('Prompt message').parentElement?.parentElement).toHaveClass(
            'wds-inline-prompt--muted',
          );
          expect(screen.getByTestId('InlinePrompt_Muted')).toBeInTheDocument();
        });

        it('should trump `media`', () => {
          render(<InlinePrompt {...defaultProps} muted sentiment={sentiment} media={MEDIA} />);
          expect(screen.getByTestId('InlinePrompt_Muted')).toBeInTheDocument();
          expect(screen.queryByTestId('custom-media')).not.toBeInTheDocument();
        });
      });

      describe('loading state', () => {
        it('should render icon and apply css', () => {
          render(<InlinePrompt {...defaultProps} sentiment={sentiment} loading />);
          expect(screen.getByText('Prompt message').parentElement?.parentElement).toHaveClass(
            'wds-inline-prompt--loading',
          );
          expect(screen.getByTestId('InlinePrompt_ProcessIndicator')).toBeInTheDocument();
        });

        it('should trump `media`', () => {
          render(<InlinePrompt {...defaultProps} sentiment={sentiment} loading media={MEDIA} />);
          expect(screen.getByTestId('InlinePrompt_ProcessIndicator')).toBeInTheDocument();
          expect(screen.queryByTestId('custom-media')).not.toBeInTheDocument();
        });
      });

      describe('custom media', () => {
        it('should respect `media`', () => {
          render(<InlinePrompt {...defaultProps} sentiment={sentiment} media={MEDIA} />);
          expect(screen.getByTestId('custom-media')).toBeInTheDocument();
        });
      });

      describe('mediaLabel', () => {
        const mediaLabel = 'Custom icon label';

        if (!statusIconLabel) {
          it('should not have accessible name for the icon', () => {
            const { container } = render(<InlinePrompt {...defaultProps} sentiment={sentiment} />);
            expect(container.querySelector('svg')).not.toHaveAccessibleName();
          });
        } else {
          it('should use default aria label', () => {
            render(<InlinePrompt {...defaultProps} sentiment={sentiment} />);
            expect(screen.getByLabelText(statusIconLabel)).toBeInTheDocument();
          });
        }

        it('should allow for customisation of aria label for StatusIcon', () => {
          render(<InlinePrompt {...defaultProps} sentiment={sentiment} mediaLabel={mediaLabel} />);
          expect(screen.getByLabelText(mediaLabel)).toBeInTheDocument();
        });

        it('should allow for customisation of aria label for a custom Icon', () => {
          render(
            <InlinePrompt
              {...defaultProps}
              sentiment={sentiment}
              media={<Clock title={mediaLabel} />}
            />,
          );
          expect(screen.getByLabelText(mediaLabel)).toBeInTheDocument();
        });

        it('should retain custom label while muted', () => {
          render(
            <InlinePrompt {...defaultProps} sentiment={sentiment} mediaLabel={mediaLabel} muted />,
          );
          expect(screen.getByLabelText(mediaLabel)).toBeInTheDocument();
        });
      });
    });
  });

  it('forwards props to PrimitivePrompt', () => {
    render(<InlinePrompt {...defaultProps} className="custom-class" data-testid="custom-test" />);
    const el = screen.getByTestId('custom-test');
    expect(el).toHaveClass('custom-class');
    expect(el).toBeInTheDocument();
  });

  describe('width', () => {
    it('defaults to auto width (no full-width class)', () => {
      render(<InlinePrompt {...defaultProps} data-testid="prompt" />);
      expect(screen.getByTestId('prompt')).not.toHaveClass('wds-inline-prompt--full-width');
    });

    it('applies auto width (no full-width class) when explicitly set', () => {
      render(<InlinePrompt {...defaultProps} width="auto" data-testid="prompt" />);
      expect(screen.getByTestId('prompt')).not.toHaveClass('wds-inline-prompt--full-width');
    });

    describe('width', () => {
      it('applies auto width class by default', () => {
        render(<InlinePrompt {...defaultProps} data-testid="prompt" />);
        expect(screen.getByTestId('prompt')).toHaveClass('wds-inline-prompt--auto-width');
      });

      it('strips the class if `width` is set to `full`', () => {
        render(<InlinePrompt {...defaultProps} width="full" data-testid="prompt" />);
        expect(screen.getByTestId('prompt')).not.toHaveClass('wds-inline-prompt--auto-width');
      });
    });
  });
});
