import {
  BranchEvent,
  BranchJourney,
  BranchJourneyType,
  fetchBranchURL,
  showBranchJourney,
  trackBranchEvent,
} from './branchUtils';

interface BranchJourneyTestCase {
  inputData: BranchJourney;
  inputSessionID: string;
  inputDeviceID: string;
  expectedData: object;
  expectedPageViewData: object;
}

describe('branchUtils', () => {
  afterAll(() => {
    delete window.branch;
  });

  describe('trachBranchEvent', () => {
    it('works with our without a provided data object', () => {
      const track = jest.fn();
      window.branch = {
        track,
        addListener: () => undefined,
        closeJourney: () => undefined,
        init: () => undefined,
        link: () => undefined,
        removeListener: () => undefined,
        setBranchViewData: () => undefined,
      };

      const event = BranchEvent.FiveMinutePlay;
      trackBranchEvent(event);
      expect(track.mock.calls[0][0]).toEqual(event);

      const metadata = { some: 'meta', data: 'set' };
      trackBranchEvent(event, metadata);
      expect(track.mock.calls[1][0]).toEqual(event);
      expect(track.mock.calls[1][1]).toEqual(metadata);
    });
  });

  describe('fetchBranchURL', () => {
    it('passes proper data to branch.link', () => {
      let capture: object;
      window.branch = {
        addListener: () => undefined,
        closeJourney: () => undefined,
        init: () => undefined,
        link: (data, callback) => {
          capture = data;
          callback(undefined, 'url');
        },
        removeListener: () => undefined,
        setBranchViewData: () => undefined,
        track: () => undefined,
      };

      return fetchBranchURL('location', '123', '321').then(url => {
        expect(url).toEqual('url');
        expect(capture).toEqual({
          channel: 'mobile_web',
          data: {
            app_session_id: '123',
            device_id: '321',
          },
          feature: 'location',
        });
      });
    });
  });

  describe('showBranchJourney', () => {
    const game = 'Alecs really fun game';
    const channel = 'BigAndy';

    const testCases: BranchJourneyTestCase[] = [
      {
        expectedData: {
          channel,
          app_session_id: '123',
          device_id: '321',
        },
        expectedPageViewData: {
          app_session_id: '123',
          device_id: '321',
          eligible_for: BranchJourneyType.Live,
        },
        inputData: {
          channel,
          type: BranchJourneyType.Live,
        },
        inputDeviceID: '321',
        inputSessionID: '123',
      },
      {
        expectedData: {
          app_session_id: '007',
          device_id: '700',
        },
        expectedPageViewData: {
          app_session_id: '007',
          device_id: '700',
          eligible_for: BranchJourneyType.MainDir,
        },
        inputData: {
          type: BranchJourneyType.MainDir,
        },
        inputDeviceID: '700',
        inputSessionID: '007',
      },
      {
        expectedData: {
          game,
          app_session_id: '1',
          device_id: '2',
        },
        expectedPageViewData: {
          app_session_id: '1',
          device_id: '2',
          eligible_for: BranchJourneyType.GameDir,
        },
        inputData: {
          game,
          type: BranchJourneyType.GameDir,
        },
        inputDeviceID: '2',
        inputSessionID: '1',
      },
      {
        expectedData: {
          channel,
          app_session_id: '1',
          device_id: '2',
        },
        expectedPageViewData: {
          app_session_id: '1',
          device_id: '2',
          eligible_for: BranchJourneyType.Vod,
        },
        inputData: {
          channel,
          type: BranchJourneyType.Vod,
        },
        inputDeviceID: '2',
        inputSessionID: '1',
      },
      {
        expectedData: {
          channel,
          app_session_id: '1',
          device_id: '2',
        },
        expectedPageViewData: {
          app_session_id: '1',
          device_id: '2',
          eligible_for: BranchJourneyType.Profile,
        },
        inputData: {
          channel,
          type: BranchJourneyType.Profile,
        },
        inputDeviceID: '2',
        inputSessionID: '1',
      },
    ];

    testCases.forEach(testCase => {
      it(`casts the incantation necessary to summon a ${
        testCase.inputData.type
      } branch journey`, () => {
        const setBranchViewData = jest.fn();
        const track = jest.fn();
        window.branch = {
          setBranchViewData,
          track,
          addListener: () => undefined,
          closeJourney: () => undefined,
          init: () => undefined,
          link: () => undefined,
          removeListener: () => undefined,
        };

        showBranchJourney(
          testCase.inputData,
          testCase.inputSessionID,
          testCase.inputDeviceID,
        );

        expect(setBranchViewData.mock.calls[0][0]).toEqual({
          data: testCase.expectedData,
        });

        expect(track.mock.calls[0][0]).toEqual(BranchEvent.PageView);
        expect(track.mock.calls[0][1]).toEqual(testCase.expectedPageViewData);
      });
    });
  });
});
