import analyticsMixin from '@/mixins/analytics-mixin';
import { setupCookies } from '@/helpers/unit-test-helper.js';
import {
    analyticsPageEvents,
    GaCategories,
    GaActions,
    GaLabels,
    ValueToLogTypes
} from '@/constants/analytics';
import { useMainStore } from '@/store';

describe('analyticsMixin.js', () => {
    test('logPageView: calls dispatch with type and payload', () => {
        const payload = {};

        const testCookieValue = {
            sid: '10000000-0000-0000-0000-000000000001'
        };

        setupCookies({ funnelCookieValue: JSON.stringify(testCookieValue) });

        useMainStore().logPageView(payload);

        expect(useMainStore().logPageView).toBeCalled();
    });

    test('logCustomEvent: calls dispatch with type and payload', () => {
        useMainStore().logCustomEvent('someCat', 'someAction', 'someLabel', 'someVal');

        expect(useMainStore().logCustomEvent).toBeCalled();
    });

    test('pushEventToGA, should call dataLayer push and logCustomEvent too', () => {
        // Arrange
        window.dataLayer = [];
        const mockDataLayer = [];
        mockDataLayer.push({
            event: 'event',
            category: 'category',
            action: 'action',
            label: 'label',
            value: undefined,
            path: '/iss/?issPage='
        });

        // Act
        analyticsMixin.methods.pushEventToGA('category', 'action', 'label', true);

        // Assert
        expect(mockDataLayer).toEqual(expect.arrayContaining(window.dataLayer));
    });

    test('pushEventToGA, should call dataLayer push and ValueToLogTypes.LAST_5 only logs last 5 of label', () => {
        // Arrange
        window.dataLayer = [];
        const expectedDataLayer = [];
        expectedDataLayer.push({
            event: 'event',
            category: 'category',
            action: 'action',
            label: '33333',
            value: undefined,
            path: '/iss/?issPage='
        });

        // Act
        analyticsMixin.methods.pushEventToGA(
            'category',
            'action',
            '1111122222333333',
            false,
            ValueToLogTypes.LAST_5
        );

        // Assert
        expect(expectedDataLayer).toEqual(expect.arrayContaining(window.dataLayer));
    });

    // eslint-disable-next-line max-len
    test('pushEventToGA, should call dataLayer push and ValueToLogTypes.LAST_5 logs only the last 3 characters for a 3 character string', () => {
        // Arrange
        window.dataLayer = [];
        const expectedDataLayer = [];
        expectedDataLayer.push({
            event: 'event',
            category: 'category',
            action: 'action',
            label: '111',
            value: undefined,
            path: '/iss/?issPage='
        });

        // Act
        analyticsMixin.methods.pushEventToGA(
            'category',
            'action',
            '111',
            false,
            ValueToLogTypes.LAST_5
        );

        // Assert
        expect(expectedDataLayer).toEqual(expect.arrayContaining(window.dataLayer));
    });

    test('Experiments, should push to dataLayer with default Google Custom Dimension Index', () => {
        // Arrange
        const store = useMainStore();

        window.dataLayer = [];

        const mockExperimentData = [
            {
                settings: {},
                variationName: 'test',
                universeName: 'testUniverse'
            }
        ];

        store.applicationUserObj.experiments = mockExperimentData;

        // Act
        analyticsMixin.methods.pushExperimentsToDataLayer(mockExperimentData);

        // Assert
        expect(window.dataLayer).toEqual([
            {
                experimentId_99: undefined,
                variationId_99: undefined,
                experimentName_99: 'testUniverse',
                variationName_99: 'test',
                customDimension_99: 'undefined_undefined_testUniverse_test'
            }
        ]);
    });

    test('Experiments, should push to dataLayer with custom Google Custom Dimension Index', () => {
        // Arrange
        const store = useMainStore();

        window.dataLayer = [];

        const mockExperimentData = [
            {
                settings: { 'Google Custom Dimension Index': '5' },
                variationName: 'test',
                universeName: 'testUniverse'
            }
        ];

        store.applicationUserObj.experiments = mockExperimentData;

        // Act
        analyticsMixin.methods.pushExperimentsToDataLayer(mockExperimentData);

        // Assert
        expect(window.dataLayer).toEqual([
            {
                experimentId_5: undefined,
                variationId_5: undefined,
                experimentName_5: 'testUniverse',
                variationName_5: 'test',
                customDimension_5: 'undefined_undefined_testUniverse_test'
            }
        ]);
    });

    test('Obj is not null after action prepended', () => {
        // Arrange
        const obj = { baseMethodName: 'testMethodName', data: 'testData' };
        const method = { name: 'testMethodName', data: 'testData' };
        const action = 'testAction';

        // Act
        analyticsMixin.methods.prependActionToMethod(obj, method, action);

        // Assert
        expect(obj != null);
    });
    test('Obj method name does not include bound', () => {
        // Arrange
        const obj = { baseMethodName: 'testMethodName', data: 'testData' };
        const method = { name: 'testMethodName', data: 'testData' };
        const action = 'testAction';

        // Act
        analyticsMixin.methods.prependActionToMethod(obj, method, action);

        // Assert
        expect(method.name.startsWith('bound ')).toBe(false);
    });
    test('Prepended action does not include bound', () => {
        // Arrange
        const obj = { baseMethodName: 'testMethodName', data: 'testData' };
        const method = { name: 'testMethodName', data: 'testData' };
        const action = 'testAction';

        // Act
        analyticsMixin.methods.prependActionToMethod(obj, method, action);

        // Assert
        expect(action.startsWith('bound ')).toBe(false);
    });

    test('analyticsPageEvents returns constants analyticsPageEvents', () => {
        // Act
        const analyticsPE = analyticsMixin.computed.analyticsPageEvents();

        // Assert
        expect(analyticsPE).toEqual(analyticsPageEvents);
    });

    test('GaActions returns constants GaActions', () => {
        // Act
        const gaActions = analyticsMixin.computed.GaActions();

        // Assert
        expect(gaActions).toEqual(GaActions);
    });

    test('GaCategories returns constants GaCategories', () => {
        // Act
        const gaCategories = analyticsMixin.computed.GaCategories();

        // Assert
        expect(gaCategories).toEqual(GaCategories);
    });

    test('GaLabels returns constants GaLabels', () => {
        // Act
        const gaLabels = analyticsMixin.computed.GaLabels();

        // Assert
        expect(gaLabels).toEqual(GaLabels);
    });
});
