import expect from 'expect';

import createTestState from 'mtest/helpers/createTestState';
import { CHANNEL_DETAILS } from 'mtest/fetchMocks/channel';
import { PREMIERE_EVENT_PAYLOAD } from 'mtest/fetchMocks/event';

import { Action } from 'mweb/common/actions/root';
import { buildVODsReducer, VODDetails } from 'mweb/common/reducers/data/vods';
import { VODS_DATA_VOD_LOADED_ACTION_TYPE } from 'mweb/common/actions/data/vods';
import { CHANNELS_DATA_CHANNEL_LOADED_ACTION_TYPE } from 'mweb/common/actions/data/channels';
import { EVENTS_DATA_EVENT_LOADED_ACTION_TYPE } from 'mweb/common/actions/data/events';
import { VideoType } from 'mweb/common/reducers/data/baseVideoDetails';

describe('vodDetails reducer', () => {
  const VOD_1_DETAILS: VODDetails = {
    videoType: VideoType.Archive,
    channel: 'channel1',
    description: '',
    game: 'Game 1',
    id: '1',
    title: '',
    thumbnailURL: '//preview.url',
    date: 0,
    viewCount: 0,
    length: 0,
    formattedLength: '0:00',
  };

  const VOD_2_DETAILS: VODDetails = {
    videoType: VideoType.Archive,
    channel: 'channel2',
    description: '',
    game: 'Game 2',
    id: '2',
    title: '',
    thumbnailURL: '//preview.url',
    date: 0,
    viewCount: 0,
    length: 0,
    formattedLength: '0:00',
  };

  it('sets defaults', () => {
    const state = buildVODsReducer()(undefined, { type: 'NOOP' });
    expect(state.vodDetails).toEqual({});
    expect(state.vodsByChannelLoadStatus).toEqual({});
  });

  describe('vod loading', () => {
    it('adds vod data to an empty list', () => {
      const initialState = createTestState().data.vods;
      const action: Action = {
        type: VODS_DATA_VOD_LOADED_ACTION_TYPE,
        payload: {
          vod: VOD_1_DETAILS,
          channel: undefined,
        },
      };

      const newState = buildVODsReducer()(initialState, action);
      expect(Object.keys(newState.vodDetails).length).toEqual(1);
      expect(newState.vodDetails[VOD_1_DETAILS.id]).toEqual(VOD_1_DETAILS);
      expect(Object.keys(newState.vodsByChannelLoadStatus).length).toEqual(0);
    });

    it('adds vod data to an existing list', () => {
      const initialState = createTestState({
        data: {
          vods: {
            vodDetails: {
              [VOD_2_DETAILS.id]: VOD_2_DETAILS,
            },
          },
        },
      }).data.vods;
      const action: Action = {
        type: VODS_DATA_VOD_LOADED_ACTION_TYPE,
        payload: {
          vod: VOD_1_DETAILS,
          channel: undefined,
        },
      };

      const newState = buildVODsReducer()(initialState, action);
      expect(Object.keys(newState.vodDetails).length).toEqual(2);
      expect(newState.vodDetails[VOD_1_DETAILS.id]).toEqual(VOD_1_DETAILS);
      expect(newState.vodDetails[VOD_2_DETAILS.id]).toEqual(VOD_2_DETAILS);
      expect(Object.keys(newState.vodsByChannelLoadStatus).length).toEqual(0);
    });
  });

  it('adds VODs when they come with a channel load', () => {
    const initialState = createTestState().data.vods;
    const action: Action = {
      type: CHANNELS_DATA_CHANNEL_LOADED_ACTION_TYPE,
      payload: {
        channel: CHANNEL_DETAILS,
        hostedChannel: undefined,
        videos: {
          [VOD_1_DETAILS.id]: VOD_1_DETAILS,
          [VOD_2_DETAILS.id]: VOD_2_DETAILS,
        },
        clips: {},
      },
    };

    const newState = buildVODsReducer()(initialState, action);
    expect(Object.keys(newState.vodDetails).length).toEqual(2);
    expect(newState.vodDetails[VOD_1_DETAILS.id]).toEqual(VOD_1_DETAILS);
    expect(newState.vodDetails[VOD_2_DETAILS.id]).toEqual(VOD_2_DETAILS);
    expect(Object.keys(newState.vodsByChannelLoadStatus).length).toEqual(1);
    expect(newState.vodsByChannelLoadStatus[CHANNEL_DETAILS.name]).toBeTruthy();
  });

  it('adds VODs when they come with a premiere event', () => {
    const initialState = createTestState().data.vods;
    const action: Action = {
      type: EVENTS_DATA_EVENT_LOADED_ACTION_TYPE,
      payload: PREMIERE_EVENT_PAYLOAD,
    };
    const newState = buildVODsReducer()(initialState, action);
    expect(Object.keys(newState.vodDetails).length).toEqual(1);
    expect(newState.vodDetails[PREMIERE_EVENT_PAYLOAD.vod!.id]).toEqual(
      PREMIERE_EVENT_PAYLOAD.vod,
    );
    expect(Object.keys(newState.vodsByChannelLoadStatus).length).toEqual(0);
  });
});
