import expect from 'expect';
import { match } from 'react-router-dom';
import { Location, History } from 'history';

import { partialPropShallowWrapper } from 'mtest/helpers/partialPropWrappers';
import { VOD_DETAILS } from 'mtest/fetchMocks/vods';
import { CLIP_DETAILS } from 'mtest/fetchMocks/clips';
import { CHANNEL_DETAILS } from 'mtest/fetchMocks/channel';

import {
  ChannelProfile,
  ChannelProfileProps,
  ChannelProfileMatchParams,
} from 'mweb/common/containers/channelProfile';
import { FeaturedContentCard } from 'mweb/common/components/featuredContentCard';
import { ChannelProfileVideoList } from 'mweb/common/components/channelProfileVideoList';
import { ProfileEmptyState } from 'mweb/common/components/profileEmptyState';
import { getProfileContentTargetVideoCounts } from 'mweb/common/selectors/pages/channelProfile';
import { ChannelInfoCard } from 'mweb/common/components/channelInfoCard';
import { ChannelOnlineStatus } from 'mweb/common/reducers/data/channels';
import { BranchUpsellExperiment } from 'mweb/common/components/branchUpsell';
import { BranchJourneyType } from 'branch-io';

describe('<ChannelProfile />', () => {
  const DEFAULT_PROPS: ChannelProfileProps = {
    channel: CHANNEL_DETAILS,
    hostedChannel: undefined,
    content: {
      featuredContent: undefined,
      infoCardVideo: undefined,
      targetVideoCounts: getProfileContentTargetVideoCounts(),
      recentClips: [],
      archives: [],
      recentHighlights: [],
      otherVideos: [],
    },
    showChannelOfflineToast: false,
    showProfileEmptyState: false,
    hasReceivedVodsAndClipsForChannel: true,
    transition: () => undefined,
    match: {
      params: {
        channel: CHANNEL_DETAILS.name,
      },
    } as match<ChannelProfileMatchParams>,
    location: { pathname: '/voxel', search: '' } as Location,
    history: {} as History,
  };

  const subject = partialPropShallowWrapper(ChannelProfile, DEFAULT_PROPS);
  describe('<FeaturedContentCard/>', () => {
    it('hides when there is no featured content', () => {
      const profile = subject({ channel: undefined });
      expect(profile).toNotContain(FeaturedContentCard);
    });

    it('shows when there is featured offline content', () => {
      const profile = subject({
        channel: {
          ...CHANNEL_DETAILS,
          onlineStatus: ChannelOnlineStatus.Offline,
        },
        content: { featuredContent: VOD_DETAILS },
      });
      expect(
        profile.find('#channel-profile-most-recent-broadcast'),
      ).toBeTruthy();
    });

    it('shows live content when the streamer is live', () => {
      const profile = subject({
        content: { featuredContent: CHANNEL_DETAILS },
      });
      expect(profile).toContain(FeaturedContentCard);
      expect(profile.find('#channel-profile-live')).toBeTruthy();
    });

    it('shows hosted content when the streamer is hosting', () => {
      const profile = subject({
        content: {
          featuredContent: {
            ...CHANNEL_DETAILS,
            hostedChannel: CHANNEL_DETAILS,
          },
        },
      });
      expect(profile).toContain(FeaturedContentCard);
      expect(profile.find('#channel-profile-hosting')).toBeTruthy();
    });
  });

  describe('<ProfileEmptyState />', () => {
    it('shows when showProfileEmptyState is true', () => {
      expect(subject({ showProfileEmptyState: true })).toContain(
        ProfileEmptyState,
      );
    });

    it('hides when showProfileEmptyState is false', () => {
      expect(subject()).toNotContain(ProfileEmptyState);
    });

    it('hides when hasReceivedVodsAndClipsForChannel is false, even if showProfileEmptyState is true', () => {
      expect(
        subject({
          showProfileEmptyState: true,
          hasReceivedVodsAndClipsForChannel: false,
        }),
      ).toNotContain(ProfileEmptyState);
    });
  });

  describe('<ChannelInfoCard />', () => {
    it('passes down info card video for clips and vods', () => {
      expect(
        subject({ content: { infoCardVideo: CLIP_DETAILS } }).find(
          ChannelInfoCard,
        ),
      ).toHaveProp('video', CLIP_DETAILS);

      expect(
        subject({ content: { infoCardVideo: VOD_DETAILS } }).find(
          ChannelInfoCard,
        ),
      ).toHaveProp('video', VOD_DETAILS);
    });
  });

  describe('<ChannelProfileVideoList/>', () => {
    it('hides all lists when given empty lists of videos', () => {
      expect(subject()).toNotContain(ChannelProfileVideoList);
    });

    it('shows archives when given a non-empty lists of archives', () => {
      const archives = [VOD_DETAILS];
      const videoList = subject({ content: { archives } }).find(
        ChannelProfileVideoList,
      );
      expect(videoList.length).toEqual(1);
      expect(videoList).toHaveProp('videos', archives);
    });

    it('shows recent clips when given a non-empty lists of clips', () => {
      const recentClips = [CLIP_DETAILS];
      const videoList = subject({ content: { recentClips } }).find(
        ChannelProfileVideoList,
      );
      expect(videoList.length).toEqual(1);
      expect(videoList).toHaveProp('videos', recentClips);
    });

    it('shows recent highlights when given a non-empty lists of highlights', () => {
      const recentHighlights = [VOD_DETAILS];
      const videoList = subject({ content: { recentHighlights } }).find(
        ChannelProfileVideoList,
      );
      expect(videoList.length).toEqual(1);
      expect(videoList).toHaveProp('videos', recentHighlights);
    });

    it('shows recent premieres/uploads when given a non-empty lists of premieres/uploads', () => {
      const otherVideos = [VOD_DETAILS];
      const videoList = subject({
        content: { otherVideos },
      }).find(ChannelProfileVideoList);
      expect(videoList.length).toEqual(1);
      expect(videoList).toHaveProp('videos', otherVideos);
    });

    it('hides if showProfileEmptyState is true, even with videos', () => {
      const recentHighlights = [VOD_DETAILS];
      expect(
        subject({
          content: { recentHighlights },
          showProfileEmptyState: true,
        }),
      ).toNotContain(ChannelProfileVideoList);
    });

    it('hides if hasReceivedVodsAndClipsForChannel is false,', () => {
      const recentHighlights = [VOD_DETAILS];
      expect(
        subject({
          content: { recentHighlights },
          hasReceivedVodsAndClipsForChannel: false,
        }),
      ).toNotContain(ChannelProfileVideoList);
    });
  });

  describe('<BranchUpsellExperiment />', () => {
    it('shows upsell with short delay if no offline toast', () => {
      const profile = subject();
      expect(profile).toContain(BranchUpsellExperiment);
      expect(profile.find(BranchUpsellExperiment)).toHaveProps({
        delaySecondsUntilUpsell: 5,
        journey: {
          type: BranchJourneyType.Profile,
          channel: CHANNEL_DETAILS.displayName,
        },
      });
    });

    it('shows upsell with long delay if offline toast', () => {
      const profile = subject({ showChannelOfflineToast: true });
      expect(profile).toContain(BranchUpsellExperiment);
      expect(profile.find(BranchUpsellExperiment)).toHaveProps({
        delaySecondsUntilUpsell: 30,
        journey: {
          type: BranchJourneyType.Profile,
          channel: CHANNEL_DETAILS.displayName,
        },
      });
    });
  });
});
