import expect from 'expect';

import createTestState from 'mtest/helpers/createTestState';
import {
  redirectedAsOffline,
  showChannelOfflineToast,
  showProfileEmptyState,
  hasReceivedVodsAndClipsForChannel,
  getProfilePageContent,
  getProfileContentTargetVideoCounts,
} from 'mweb/common/selectors/pages/channelProfile';
import {
  VideoType,
  BaseVideoDetails,
} from 'mweb/common/reducers/data/baseVideoDetails';
import { ChannelOnlineStatus } from 'mweb/common/reducers/data/channels';

describe('hasReceivedVodsAndClipsForChannel', () => {
  const channel = 'BigAndy';
  it('returns true if received both clips and vods', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
          redirectedAsOffline: true,
        },
      },
      data: {
        vods: {
          vodsByChannelLoadStatus: {
            [channel]: true,
          },
        },
        clips: {
          clipsByChannelLoadStatus: {
            [channel]: true,
          },
        },
      },
    });
    expect(hasReceivedVodsAndClipsForChannel(state)).toBe(true);
  });
  it('returns false if not received both clips and vods', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
          redirectedAsOffline: true,
        },
      },
      data: {
        clips: {
          clipsByChannelLoadStatus: {
            [channel]: true,
          },
        },
        vods: {
          vodsByChannelLoadStatus: {},
        },
      },
    });
    expect(hasReceivedVodsAndClipsForChannel(state)).toBe(false);
    const state2 = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
          redirectedAsOffline: true,
        },
      },
      data: {
        clips: {
          clipsByChannelLoadStatus: {},
        },
        vods: {
          vodsByChannelLoadStatus: {
            [channel]: true,
          },
        },
      },
    });
    expect(hasReceivedVodsAndClipsForChannel(state2)).toBe(false);
  });

  it('returns false if received clips and vods but for a different channel', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
          redirectedAsOffline: true,
        },
      },
      data: {
        vods: {
          vodsByChannelLoadStatus: {
            BiggerAndy: true,
          },
        },
        clips: {
          clipsByChannelLoadStatus: {
            BiggerAndy: true,
          },
        },
      },
    });
    expect(hasReceivedVodsAndClipsForChannel(state)).toBe(false);
  });
});

describe('showProfileEmptyState', () => {
  const channel = 'BigAndy';
  it('shows profile empty state if no vods exist', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
          redirectedAsOffline: true,
        },
      },
      data: {
        vods: {
          vodDetails: {
            vod1: {
              channel: 'NotAndy',
              videoType: VideoType.Archive,
              date: 0,
            },
          },
        },
      },
    });
    expect(showProfileEmptyState(state)).toBe(true);
  });

  it('does not shows profile empty state if vods exists', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
          redirectedAsOffline: true,
        },
      },
      data: {
        vods: {
          vodDetails: {
            vod1: {
              channel,
              videoType: VideoType.Archive,
              date: 0,
            },
          },
        },
      },
    });
    expect(showProfileEmptyState(state)).toBe(false);
  });

  it('does not shows profile empty state if recent clips exists', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
          redirectedAsOffline: true,
        },
      },
      data: {
        clips: {
          clipDetails: {
            clip1: {
              channel,
              viewCount: 1,
              date: new Date().valueOf(),
            },
          },
        },
      },
    });
    expect(showProfileEmptyState(state)).toBe(false);
  });
});

describe('redirectedAsOffline', () => {
  it('returns true if redirected as offline', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          redirectedAsOffline: true,
        },
      },
    });
    expect(redirectedAsOffline(state)).toEqual(true);
  });

  it('returns false if not redirected as offline', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          redirectedAsOffline: false,
        },
      },
    });
    expect(redirectedAsOffline(state)).toEqual(false);
  });
});

describe('showChannelOfflineToast', () => {
  it('shows the toast when the channel is offline, vods exist, and redirect happened', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: 'mastercat',
          redirectedAsOffline: true,
        },
      },
      data: {
        channels: {
          channelDetails: {
            mastercat: {
              onlineStatus: ChannelOnlineStatus.Offline,
            },
          },
        },
        vods: {
          vodDetails: {
            vod1: {
              channel: 'mastercat',
              videoType: VideoType.Archive,
              date: 0,
            },
          },
        },
      },
    });
    expect(showChannelOfflineToast(state)).toBe(true);
  });

  it('shows no toast when the channel is offline, vods dont exist, and redirect happened', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: 'mastercat',
          redirectedAsOffline: true,
        },
      },
      data: {
        channels: {
          channelDetails: {
            mastercat: {
              onlineStatus: ChannelOnlineStatus.Offline,
            },
          },
        },
      },
    });
    expect(showChannelOfflineToast(state)).toBe(false);
  });

  it('shows no toast when the channel is online', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: 'mastercat',
          redirectedAsOffline: true,
        },
      },
      data: {
        channels: {
          channelDetails: {
            mastercat: {
              onlineStatus: ChannelOnlineStatus.Online,
            },
          },
        },
      },
    });
    expect(showChannelOfflineToast(state)).toBe(false);
  });

  it('shows no toast when the channel is not known', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: 'mastercat',
          redirectedAsOffline: true,
        },
      },
      data: {
        channels: {
          channelDetails: {
            mastercat: {
              onlineStatus: ChannelOnlineStatus.Unknown,
            },
          },
        },
        vods: {
          vodDetails: {
            vod1: {
              channel: 'mastercat',
              videoType: VideoType.Archive,
              date: 0,
            },
          },
        },
      },
    });
    expect(showChannelOfflineToast(state)).toBe(false);
  });

  it('shows no toast when the user was not redirected here', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: 'mastercat',
          redirectedAsOffline: false,
        },
      },
      data: {
        channels: {
          channelDetails: {
            mastercat: {
              onlineStatus: ChannelOnlineStatus.Offline,
            },
          },
        },
      },
    });
    expect(showChannelOfflineToast(state)).toBe(false);
  });
});

describe('getProfilePageContent', () => {
  it('returns the right content when there is relevant data in store', () => {
    const channel = 'ghoulcat';
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: channel,
        },
      },
      data: {
        vods: {
          vodDetails: {
            vod1: {
              channel: channel,
              videoType: VideoType.Archive,
              date: 0,
              viewCount: 3,
            },
            vod2: {
              channel: channel,
              videoType: VideoType.Archive,
              date: 1,
              viewCount: 2,
            },
            vod3: {
              channel: channel,
              videoType: VideoType.Archive,
              date: 2,
              viewCount: 1,
            },
            vod4: {
              channel: channel,
              videoType: VideoType.Highlight,
              date: 0,
              viewCount: 0,
            },
            vod5: {
              channel: channel,
              videoType: VideoType.Highlight,
              date: new Date().valueOf(),
              viewCount: 5,
            },
            vod6: {
              channel: 'ghostfeline',
              videoType: VideoType.Archive,
              date: 0,
            },
            vod7: {
              channel: channel,
              videoType: VideoType.PastPremiere,
              date: new Date().valueOf(),
              viewCount: 5,
            },
            vod8: {
              channel: channel,
              videoType: VideoType.Upload,
              date: new Date().valueOf(),
              viewCount: 5,
            },
            vod9: {
              channel: channel,
              videoType: VideoType.Upload,
              date: new Date().valueOf(),
              viewCount: 10,
            },
          },
        },
        clips: {
          clipDetails: {
            clip1: {
              channel,
              viewCount: 1,
              date: new Date().valueOf(),
            },
            clip2: {
              channel,
              viewCount: 2,
              date: 0,
            },
          },
        },
      },
    });

    const content = getProfilePageContent(state);
    expect(content.targetVideoCounts).toEqual(
      getProfileContentTargetVideoCounts(),
    );

    const featuredVideo = content.featuredContent as BaseVideoDetails;
    expect(featuredVideo!.date).toEqual(2);
    expect(featuredVideo!.viewCount).toEqual(1);
    expect(featuredVideo!.videoType).toEqual(VideoType.Archive);
    expect(content.infoCardVideo!.viewCount).toEqual(5);
    expect(content.infoCardVideo!.videoType).toEqual(VideoType.Highlight);

    expect(content.archives.length).toEqual(2);

    // "recent" clips only includes within last week
    expect(content.recentClips.length).toEqual(1);

    // "recent" highlights includes all highlights
    expect(content.recentHighlights.length).toEqual(2);

    expect(content.otherVideos.length).toEqual(3);
    content.otherVideos.forEach(vod =>
      expect(
        vod.videoType === VideoType.Upload ||
          vod.videoType === VideoType.PastPremiere,
      ),
    );
  });

  it('returns the right content when there is not data in store', () => {
    const state = createTestState({
      pages: {
        channelProfile: {
          currentChannel: 'voxel',
        },
      },
    });

    const content = getProfilePageContent(state);
    expect(content.targetVideoCounts).toEqual(
      getProfileContentTargetVideoCounts(),
    );

    expect(content.featuredContent).toNotExist();
    expect(content.infoCardVideo).toNotExist();
    expect(content.archives.length).toEqual(0);
    expect(content.recentClips.length).toEqual(0);
    expect(content.recentHighlights.length).toEqual(0);
    expect(content.otherVideos.length).toEqual(0);
  });
});

describe('getProfileContentTargetVideoCounts', () => {
  it('generates the correct values', () => {
    expect(getProfileContentTargetVideoCounts()).toEqual({
      archives: 7,
      recentClips: 6,
      recentHighlights: 6,
      recentPremieresAndUploads: 6,
      topClips: 1,
      topHighlights: 1,
    });
  });
});
