import expect from 'expect';
import { stub, SinonStub } from 'sinon';
import { InjectedIntl, FormattedMessage, FormattedDate } from 'react-intl';
import { Stat, StyledLayout } from 'twitch-core-ui';

import { partialPropShallowWrapper } from 'mtest/helpers/partialPropWrappers';
import { trackClickMock, testClickTracking } from 'mtest/helpers/tracking';

import { VideoCard, VideoCardProps } from 'mweb/common/components/videoCard';
import { TrackClickHandler } from 'mweb/common/tracking/withTracking';
import { TrackedLink } from 'mweb/common/tracking/trackedLink';
import { CardImageWrapper } from 'mweb/common/components/more-ui/cardImageWrapper';

describe('<VideoCard />', () => {
  const DEFAULT_PROPS: VideoCardProps = {
    title: 'Title',
    imageURL: '//image.url',
    gameName: 'Game',
    viewCount: 1,
    formattedLength: '0:00',
    createdAt: 0,
    borderTop: false,
    linkTo: '/videos/v123',
    trackClick: trackClickMock(),
    intl: ({
      formatNumber: stub().returnsArg(0),
      formatMessage: stub().returns('Text'),
    } as any) as InjectedIntl,
    interactionContent: 'interaction-content',
  };

  const subject = partialPropShallowWrapper(VideoCard, DEFAULT_PROPS);

  it('renders properly', () => {
    const item = subject();

    const image = item.find('.mw-channel-profile-video-card__image');
    expect(
      (DEFAULT_PROPS.intl.formatMessage as SinonStub).getCall(0).args[0].id,
    ).toEqual('video-length');
    expect(image.find(Stat).prop('value')).toEqual(
      DEFAULT_PROPS.formattedLength,
    );

    const thumbnail = image.find(CardImageWrapper);
    expect(thumbnail).toExist();
    expect(thumbnail).toHaveProps({
      latencyTracked: false,
      alt: DEFAULT_PROPS.title,
    });

    const details = item.find('.mw-channel-profile-video-card__details');
    expect(
      details
        .childAt(0)
        .childAt(0)
        .text(),
    ).toEqual(DEFAULT_PROPS.title);

    const microDetails = details.childAt(1);
    expect(microDetails.childAt(0).text()).toEqual(DEFAULT_PROPS.gameName);
    expect(microDetails.find(FormattedMessage).prop('values')).toEqual({
      viewCount: DEFAULT_PROPS.viewCount,
      formattedViewCount: DEFAULT_PROPS.viewCount,
    });
    expect(microDetails.find(FormattedDate).prop('value')).toEqual(
      DEFAULT_PROPS.createdAt,
    );
  });

  describe('top border', () => {
    it('does not show when appropriate', () => {
      const layout = subject({}).find(StyledLayout);

      expect(layout.prop('borderTop')).toEqual(false);
    });

    it('does show when appropriate', () => {
      const layout = subject({ borderTop: true }).find(StyledLayout);

      expect(layout.prop('borderTop')).toEqual(true);
    });
  });

  describe('link', () => {
    it('is rendered as router Link component for vods', () => {
      const item = subject();
      expect(item.find(TrackedLink).prop('to')).toEqual(DEFAULT_PROPS.linkTo);
      expect(item.find('a').length).toEqual(0);
    });

    it('is rendered as anchor for clips', () => {
      const linkTo = 'https://clips/wtf';
      const item = subject({ linkTo });
      expect(item.find('a').prop('href')).toEqual(linkTo);
      expect(item.find(TrackedLink).length).toEqual(0);
    });
  });

  testClickTracking([
    {
      title: 'tracks clicks for in-app content',
      expectedPayload: {
        interactionContent: DEFAULT_PROPS.interactionContent,
        interactionTargetPath: DEFAULT_PROPS.linkTo,
      },
      clickTargetBuilder: () => subject().find(TrackedLink),
    },
    {
      title: 'tracks clicks for external content',
      expectedPayload: {
        interactionContent: DEFAULT_PROPS.interactionContent,
        interactionTargetPath: '/clips/wtf',
      },
      clickTargetBuilder: (trackClick: TrackClickHandler) =>
        subject({ trackClick, linkTo: 'https://clips.twitch.tv/wtf' }).find(
          'a',
        ),
    },
  ]);
});
