import expect from 'expect';
import omit from 'lodash-es/omit';

import { expectEqualWithoutSpadeBaseAndTime } from 'mtest/helpers/trackingSelectors';
import createTestState from 'mtest/helpers/createTestState';

import {
  getBaseSubscribeButtonSpadeData,
  getSubscribeButtonData,
  getChannelSubscribeButtonSpadeData,
  getChannelProfileSubscribeButtonSpadeData,
  getVODSubscribeButtonSpadeData,
  SubscribeButtonSpadeData,
  SubscribeLocation,
  SUBSCRIBE_BUTTON_ACTION,
} from 'mweb/common/selectors/tracking/subscribe';
import { RootState } from 'mweb/common/reducers/root';
import { Location } from 'mweb/common/reducers/app';
import { VideoType } from 'mweb/common/reducers/data/baseVideoDetails';
import { VODDetails } from 'mweb/common/reducers/data/vods';

const BaseSubscibeKeys = Object.keys(
  getBaseSubscribeButtonSpadeData(createTestState()),
);
function expectEqualWithBaseSubscribeData(
  actual: SubscribeButtonSpadeData | undefined,
  expected: Object,
): void {
  expect(omit(actual, BaseSubscibeKeys)).toEqual(expected);
}

describe('subscribe selectors', () => {
  it('getBaseSubscribeButtonSpadeData', () => {
    const state = createTestState();
    expectEqualWithoutSpadeBaseAndTime(getBaseSubscribeButtonSpadeData(state), {
      action: SUBSCRIBE_BUTTON_ACTION,
      can_subscribe: false,
      has_prime: false,
      has_sub_credit: false,
      is_menu_open: false,
      is_subscribed: false,
      logged_in: false,
      modal: false,
      show_prime_content: false,
      show_resub: false,
    });
  });

  const channelDetails = {
    name: 'voxel',
    id: '12345',
  };

  const vodDetails: Partial<VODDetails> = {
    id: '67890',
    videoType: VideoType.Archive,
    channel: 'voxel',
  };

  interface SubscribeTestCase {
    location: Location;
    selector: Function;
    stateSeed: DeepPartial<RootState>;
    expectedData: Object;
  }

  const testCases: SubscribeTestCase[] = [
    {
      location: Location.Channel,
      selector: getChannelSubscribeButtonSpadeData,
      stateSeed: {
        pages: {
          channelViewer: {
            currentChannel: channelDetails.name,
          },
        },
        data: {
          channels: {
            channelDetails: {
              [channelDetails.name]: channelDetails,
            },
          },
        },
      },
      expectedData: {
        sub_location: SubscribeLocation.Channel,
        channel: channelDetails.name,
        channel_id: parseInt(channelDetails.id),
      },
    },
    {
      location: Location.ChannelProfile,
      selector: getChannelProfileSubscribeButtonSpadeData,
      stateSeed: {
        pages: {
          channelProfile: {
            currentChannel: channelDetails.name,
          },
        },
        data: {
          channels: {
            channelDetails: {
              [channelDetails.name]: channelDetails,
            },
          },
        },
      },
      expectedData: {
        sub_location: SubscribeLocation.ChannelProfile,
        channel: channelDetails.name,
        channel_id: parseInt(channelDetails.id),
      },
    },
    {
      location: Location.VOD,
      selector: getVODSubscribeButtonSpadeData,
      stateSeed: {
        pages: {
          vodViewer: {
            currentVODid: vodDetails.id,
          },
        },
        data: {
          channels: {
            channelDetails: {
              [channelDetails.name]: channelDetails,
            },
          },
          vods: {
            vodDetails: {
              [vodDetails.id!]: vodDetails,
            },
          },
        },
      },
      expectedData: {
        sub_location: SubscribeLocation.VOD,
        channel: channelDetails.name,
        channel_id: parseInt(channelDetails.id),
        vod_id: parseInt(vodDetails.id!),
        vod_type: vodDetails.videoType,
      },
    },
  ];

  testCases.forEach(({ location, selector, stateSeed, expectedData }) => {
    const state = createTestState({ ...stateSeed, app: { location } });
    describe(`for location ${location}`, () => {
      it('generates the proper payload for the target selector', () => {
        expectEqualWithBaseSubscribeData(selector(state), expectedData);
      });

      it(`getSubscribeButtonData uses selector ${selector.name}`, () => {
        expectEqualWithBaseSubscribeData(
          getSubscribeButtonData(state),
          expectedData,
        );
      });
    });
  });
});
