import { render, fireEvent, screen } from '@testing-library/react';
import React from 'react';

import PromoCard, { PromoCardProps, PromoCardCheckedProps, PromoCardLinkProps } from './PromoCard';

describe('PromoCard', () => {
  const defaultProps = {
    title: 'Test Title',
    imageSource: 'test.jpg',
    imageAlt: 'Test Image',
    description: 'Test Description',
    indicatorLabel: 'Test Indicator Label',
    testId: 'test-promo-card',
    children: 'Test Content',
  };

  let rerenderPromoCard: (props?: PromoCardProps) => void;

  beforeEach(() => {
    const { rerender } = render(<PromoCard {...defaultProps} />);

    rerenderPromoCard = (props?: PromoCardProps) => {
      rerender(<PromoCard {...defaultProps} {...props} />);
    };
  });

  it('matches snapshot', () => {
    const { container } = render(<PromoCard {...defaultProps} id="test-promo-card" />);

    expect(container.firstChild).toMatchSnapshot();
  });

  it('renders', () => {
    const props = {
      ...defaultProps,
      title: 'Test text',
    };
    expect(screen.getByTestId('test-promo-card')).toBeInTheDocument();
    expect(screen.getByTestId('test-promo-card')).toHaveClass('np-Card--promoCard');

    // Change props
    rerenderPromoCard(props);

    expect(screen.getByText('Test text')).toBeInTheDocument();
  });

  it('renders title as an `h3`', () => {
    const props: PromoCardProps = {
      ...defaultProps,
      headingLevel: 'h4',
    };
    expect(screen.getByRole('heading', { level: 3 })).toBeInTheDocument();
    expect(screen.queryByRole('heading', { level: 4 })).not.toBeInTheDocument();

    // Change props
    rerenderPromoCard(props);

    expect(screen.getByRole('heading', { level: 4 })).toBeInTheDocument();
    expect(screen.queryByRole('heading', { level: 3 })).not.toBeInTheDocument();
  });

  it('renders as an link element', () => {
    const props: PromoCardLinkProps = {
      ...defaultProps,
      href: 'https://wise.com/',
    };
    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('np-Card--link');
    expect(screen.getByText('Test Title')).not.toHaveAttribute('href');

    // Change props
    rerenderPromoCard(props);

    expect(screen.getByTestId('test-promo-card')).toHaveClass('np-Card--link');
    expect(screen.getByText('Test Title')).toHaveAttribute('href');
  });

  it('renders the component with checkbox props', () => {
    const props: PromoCardCheckedProps = {
      ...defaultProps,
      type: 'checkbox', // or 'radio'
    };
    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('np-Card--checked');
    expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();

    // Change props
    rerenderPromoCard(props);

    expect(screen.getByTestId('test-promo-card')).toHaveClass('np-Card--checked');
    expect(screen.getByRole('checkbox')).toBeInTheDocument();
  });

  it('renders the component with radio props', () => {
    const props: PromoCardCheckedProps = {
      ...defaultProps,
      type: 'radio', // or 'checkbox'
    };
    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('np-Card--checked');
    expect(screen.queryByRole('radio')).not.toBeInTheDocument();

    // Change props
    rerenderPromoCard(props);

    expect(screen.getByTestId('test-promo-card')).toHaveClass('np-Card--checked');
    expect(screen.getByRole('radio')).toBeInTheDocument();
  });

  it('doesnt render as a link or checked card when `herf` or `type` has been set', () => {
    const props = {
      ...defaultProps,
      type: 'radio', // or 'checkbox'
      href: 'https://wise.com/',
    };
    // Change props
    rerenderPromoCard(props as any);

    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('np-Card--checked');
    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('np-Card--link');
    expect(screen.queryByRole('radio')).not.toBeInTheDocument();
    expect(screen.getByText('Test Title')).not.toHaveAttribute('href');
  });

  it('is set with class by the `className` prop', () => {
    const props = {
      ...defaultProps,
      className: 'test-custom',
    };
    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('test-custom');

    // Change props
    rerenderPromoCard(props);

    expect(screen.getByTestId('test-promo-card')).toHaveClass('test-custom');
  });

  it('applies `is-disabled` class when isDisabled is true', () => {
    const props: PromoCardProps = {
      ...defaultProps,
      isDisabled: true,
    };
    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('is-disabled');

    // Change props
    rerenderPromoCard(props);

    expect(screen.getByTestId('test-promo-card')).toHaveClass('is-disabled');
  });

  it('calls the onClick function when the checkbox is clicked', () => {
    const checkedProps: PromoCardCheckedProps = {
      ...defaultProps,
      type: 'checkbox',
      isChecked: false,
    };
    // Change props
    rerenderPromoCard(checkedProps);

    expect(screen.getByTestId('test-promo-card')).not.toHaveClass('is-checked');
    fireEvent.click(screen.getByRole('checkbox'));
    expect(screen.getByTestId('test-promo-card')).toHaveClass('is-checked');
  });
});
