import expect from 'expect';

import createTestState from 'mtest/helpers/createTestState';

import { Action } from 'mweb/common/actions/root';
import { channelViewerPage } from 'mweb/common/reducers/pages/channelViewer';
import {
  CHANNEL_VIEWER_PAGE_CHANNEL_UPDATED_ACTION_TYPE,
  CHANNEL_VIEWER_PAGE_LIVE_TO_VOD_PARAMS_CAPTURED_ACTION_TYPE,
  CHANNEL_VIEWER_PAGE_LIVE_TO_VOD_REDIRECTED_ACTION_TYPE,
  CHANNEL_VIEWER_PAGE_LIVE_TO_VOD_STREAM_ID_CLEARED_ACTION_TYPE,
} from 'mweb/common/actions/pages/channelViewer';
import {
  CHANNELS_DATA_CHANNEL_HOSTING_STATUS_UPDATED_ACTION_TYPE,
  CHANNELS_DATA_CHANNEL_LOADED_ACTION_TYPE,
} from 'mweb/common/actions/data/channels';
import {
  ChannelOnlineStatus,
  ChannelDetails,
} from 'mweb/common/reducers/data/channels';
import { CHANNEL_DETAILS } from 'test/fetchMocks/channel';

describe('channelViewerPage reducer', () => {
  it('sets defaults', () => {
    expect(channelViewerPage(undefined, { type: 'NOOP' })).toEqual({
      currentChannel: '',
      hostedChannel: '',
      showChat: undefined,
      liveToVODStreamID: undefined,
      liveToVODTargetVODid: '',
    });
  });

  it('updates current channel and resets meta except for showChat', () => {
    const initialState = createTestState({
      pages: {
        channelViewer: {
          currentChannel: 'voxel',
          hostedChannel: 'monstercat',
          showChat: true,
          liveToVODStreamID: '1234',
        },
      },
    }).pages.channelViewer;

    const action: Action = {
      type: CHANNEL_VIEWER_PAGE_CHANNEL_UPDATED_ACTION_TYPE,
      payload: {
        channel: 'forks',
      },
    };

    const newState = channelViewerPage(initialState, action);
    expect(newState.currentChannel).toEqual('forks');
    expect(newState.hostedChannel).toEqual('');
    expect(newState.showChat).toEqual(true);
    expect(newState.liveToVODStreamID).toEqual(undefined);
  });

  describe('when channel data is loaded', () => {
    describe('when the channel is the current channel', () => {
      it('toggles the state when the channel goes online', () => {
        const initialState = createTestState({
          pages: {
            channelViewer: {
              currentChannel: CHANNEL_DETAILS.name,
              showChat: false,
              liveToVODStreamID: '1234',
            },
          },
        }).pages.channelViewer;

        const action: Action = {
          type: CHANNELS_DATA_CHANNEL_LOADED_ACTION_TYPE,
          payload: {
            channel: CHANNEL_DETAILS,
            hostedChannel: undefined,
            videos: undefined,
            clips: undefined,
          },
        };

        expect(channelViewerPage(initialState, action).showChat).toEqual(true);
      });

      it('does nothing when the channel goes offline', () => {
        const initialState = createTestState({
          pages: {
            channelViewer: {
              currentChannel: CHANNEL_DETAILS.name,
              showChat: true,
            },
          },
        }).pages.channelViewer;

        const action: Action = {
          type: CHANNELS_DATA_CHANNEL_LOADED_ACTION_TYPE,
          payload: {
            channel: {
              ...CHANNEL_DETAILS,
              status: ChannelOnlineStatus.Offline,
            },
            hostedChannel: undefined,
            videos: undefined,
            clips: undefined,
          },
        };

        expect(channelViewerPage(initialState, action).showChat).toEqual(true);
      });
      it('does nothing when the channel remains offline', () => {
        const channel: ChannelDetails = {
          ...CHANNEL_DETAILS,
          onlineStatus: ChannelOnlineStatus.Offline,
        };

        const initialState = createTestState({
          pages: {
            channelViewer: {
              currentChannel: CHANNEL_DETAILS.name,
              showChat: false,
            },
          },
          data: {
            channels: {
              [channel.name]: channel,
            },
          },
        }).pages.channelViewer;

        const action: Action = {
          type: CHANNELS_DATA_CHANNEL_LOADED_ACTION_TYPE,
          payload: {
            videos: undefined,
            clips: undefined,
            hostedChannel: undefined,
            channel,
          },
        };

        expect(channelViewerPage(initialState, action).showChat).toEqual(false);
      });
    });

    describe('when the channel is not the current channel', () => {
      it('does nothing', () => {
        const initialState = createTestState({
          pages: {
            channelViewer: {
              currentChannel: `${CHANNEL_DETAILS.name}SomeDifferentText`,
              showChat: false,
            },
          },
        }).pages.channelViewer;

        const action: Action = {
          type: CHANNELS_DATA_CHANNEL_LOADED_ACTION_TYPE,
          payload: {
            channel: {
              ...CHANNEL_DETAILS,
              status: ChannelOnlineStatus.Offline,
            },
            hostedChannel: undefined,
            videos: undefined,
            clips: undefined,
          },
        };

        expect(channelViewerPage(initialState, action).showChat).toEqual(false);
      });
    });
  });

  it('records hosted channel', () => {
    const initialState = createTestState({
      pages: {
        channelViewer: {
          currentChannel: 'voxel',
        },
      },
    }).pages.channelViewer;
    const action: Action = {
      type: CHANNELS_DATA_CHANNEL_HOSTING_STATUS_UPDATED_ACTION_TYPE,
      payload: {
        channel: 'voxel',
        hostedChannel: 'monstercat',
      },
    };

    const newState = channelViewerPage(initialState, action);
    expect(newState.currentChannel).toEqual('voxel');
    expect(newState.hostedChannel).toEqual('monstercat');
  });

  describe('capturing LiveToVOD params', () => {
    it('converts to number and stores', () => {
      const initialState = createTestState().pages.channelViewer;

      const action: Action = {
        type: CHANNEL_VIEWER_PAGE_LIVE_TO_VOD_PARAMS_CAPTURED_ACTION_TYPE,
        payload: {
          stream_id: '1234',
        },
      };

      expect(channelViewerPage(initialState, action).liveToVODStreamID).toEqual(
        '1234',
      );
    });
  });

  describe('LiveToVOD status actions', () => {
    it('sets target vod for offline stream', () => {
      const initialState = createTestState().pages.channelViewer;

      const action: Action = {
        type: CHANNEL_VIEWER_PAGE_LIVE_TO_VOD_REDIRECTED_ACTION_TYPE,
        payload: {
          channel: 'channel',
          channelID: '22',
          streamID: '33',
          vodID: 'v12345',
        },
      };

      expect(
        channelViewerPage(initialState, action).liveToVODTargetVODid,
      ).toEqual('v12345');
    });

    it('clears stream id when stream is verified online', () => {
      const initialState = createTestState({
        pages: {
          channelViewer: {
            liveToVODStreamID: '4',
          },
        },
      }).pages.channelViewer;

      const action: Action = {
        type: CHANNEL_VIEWER_PAGE_LIVE_TO_VOD_STREAM_ID_CLEARED_ACTION_TYPE,
        payload: {
          channel: 'channel',
          channelID: '22',
          streamID: '33',
        },
      };

      expect(channelViewerPage(initialState, action).liveToVODStreamID).toEqual(
        undefined,
      );
    });
  });
});
