// Components
import { shallowMount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import entryPage from '@/layouts/entry-page/entry-page.vue';

// Supporting Files
import baseMixin from '@/mixins/base-mixin';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import { useMainStore } from '@/store';
import settleAllPromises from '@/helpers/layout-helper.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import * as clientAuthHelper from '@/helpers/clientauth-helper';

// Mock our module for promises.
jest.mock('@/helpers/layout-helper.js', () => jest.fn());

// Mock fetchCmsContentForPage
jest.mock('@/helpers/cms-content-helper', () => ({
    fetchCmsContentForPage: jest.fn(),
    setupModalLinks: jest.fn()
}));

function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRunAfterInitializingStore = () => {}) {
    const mountOptions = getMountOptions({
        router: {
            navigate: jest.fn()
        }
    });

    const testingPinia = createTestingPinia({
        initialState: {
            main: mainInitialState
        }
    });
    useMainStore(testingPinia);
    methodToRunAfterInitializingStore();

    mountOptions.global.plugins = [testingPinia];
    mountOptions.data = () => (initialData);

    const apiResponses = { cmsContent: {} };

    settleAllPromises.mockImplementation(() => apiResponses);
    fetchCmsContentForPage.mockImplementation(() => Promise.resolve());

    const wrapper = shallowMount(entryPage, mountOptions);
    wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {});
    wrapper.vm.setCmsContent = jest.fn();
    wrapper.vm.$router.navigateWithSpinner = jest.fn();
    wrapper.vm.navigateForward = baseMixin.methods.navigateForward;

    return { wrapper };
}

describe('entry-page.vue', () => {
    test('shows unauthorized message when not authorized', async () => {
        const wrapper = shallowMount(entryPage, getMountOptions());
        wrapper.setData({ unauthorized: true });
        await wrapper.vm.$nextTick();
        expect(wrapper.find('#message').isVisible()).toBe(true);
        expect(wrapper.text()).toContain('Unauthorized Access.');
    });
    describe('validateClientTagOnEntry', () => {
        let wrapper;
        beforeEach(() => {
            const mainInitialState = { issConfig: {} };
            wrapper = getMountedComponent(mainInitialState).wrapper;
        });

        it('returns unauthorized if no clienttag', async () => {
            const result = await wrapper.vm.validateClientTagOnEntry({});
            expect(result.isAuthorized).toBe(false);
        });

        it('returns unauthorized if validateISSClientTag returns falsy', async () => {
            jest.spyOn(clientAuthHelper, 'validateISSClientTag').mockResolvedValueOnce(null);
            const result = await wrapper.vm.validateClientTagOnEntry({ clienttag: 'abc' });
            expect(result.isAuthorized).toBe(false);
        });

        it('returns authorized and clientData if valid and not RSAToken', async () => {
            const resp = {
                active: true,
                accountName: 'Client',
                authentication: '',
                parentAccountNumber: 'P',
                styleSheet: '',
                coverageEnabled: true,
                siteType: ''
            };
            jest.spyOn(clientAuthHelper, 'validateISSClientTag').mockResolvedValueOnce(resp);
            const result = await wrapper.vm.validateClientTagOnEntry({ clienttag: 'abc' });
            expect(result.isAuthorized).toBe(true);
            expect(result.clientData).toEqual(resp);
        });

        it('handles RSAToken with valid signature and EncParams', async () => {
            const resp = {
                active: true,
                accountName: 'Client',
                authentication: 'RSAToken EncParams',
                parentAccountNumber: 'P',
                styleSheet: '',
                coverageEnabled: true,
                siteType: ''
            };
            const decryptedData = 'foo=bar&from=yesterday';
            jest.spyOn(clientAuthHelper, 'validateISSClientTag').mockResolvedValueOnce(resp);
            jest.spyOn(clientAuthHelper, 'validateISSClientSignature').mockResolvedValueOnce({ valid: true, decryptedData });
            const result = await wrapper.vm.validateClientTagOnEntry({ clienttag: 'abc', token: 'tok', signature: 'sig' });
            expect(result.isAuthorized).toBe(true);
            expect(result.clientData).toEqual(resp);
            expect(result.decryptedParams).toEqual({ foo: 'bar', from: 'yesterday' });
        });

        it('handles RSAToken with invalid signature', async () => {
            const resp = {
                active: true,
                accountName: 'Client',
                authentication: 'RSAToken',
                parentAccountNumber: 'P',
                styleSheet: '',
                coverageEnabled: true,
                siteType: ''
            };
            jest.spyOn(clientAuthHelper, 'validateISSClientTag').mockResolvedValueOnce(resp);
            jest.spyOn(clientAuthHelper, 'validateISSClientSignature').mockResolvedValueOnce({ valid: false });
            const result = await wrapper.vm.validateClientTagOnEntry({ clienttag: 'abc', token: 'tok', signature: 'sig' });
            expect(result.isAuthorized).toBe(false);
        });
    });
    test('populateISSConfigValues sets issConfig fields and parses clientFlags', () => {
        const mainInitialState = {
            issConfig: {}
        };
        const { wrapper } = getMountedComponent(mainInitialState);
        const data = {
            accountName: 'TestClient',
            parentAccountNumber: '12345',
            styleSheet: 'test-style',
            coverageEnabled: true,
            siteType: 'test-site',
            clientFlags: JSON.stringify({
                TPAEnabled: true,
                ClientFullName: 'Full Name',
                ClientDisplayName: 'Display Name',
                ClaimRegistrationRequired: true,
                EnableNoCompQuote: true
            })
        };
        wrapper.vm.populateISSConfigValues(data);
        const { issConfig } = wrapper.vm.mainStore;
        expect(issConfig.clientName).toBe('TestClient');
        expect(issConfig.clientFullName).toBe('Full Name');
        expect(issConfig.clientDisplayName).toBe('Display Name');
        expect(issConfig.parentAccountNumber).toBe('12345');
        expect(issConfig.styleSheet).toBe('test-style');
        expect(issConfig.isCoverageEnabled).toBe(true);
        expect(issConfig.siteType).toBe('test-site');
        expect(issConfig.enableTPAFlow).toBe(true);
        expect(issConfig.isClaimRegistrationRequired).toBe(true);
        expect(issConfig.enableNoCompQuote).toBe(true);
    });
    describe('combineClientParameters', () => {
        let wrapper;
        beforeEach(() => {
            wrapper = getMountedComponent({ issConfig: {} }).wrapper;
        });

        it('returns correct params from config and query', () => {
            const configParams = JSON.stringify(['PolicyNbr', 'DateOfLoss', 'Unused']);
            const queryStringParams = { policynbr: '123', dateofloss: '2022-01-01', somethingelse: 'no' };
            const result = wrapper.vm.combineClientParameters(configParams, queryStringParams);
            expect(result).toEqual({ policynbr: '123', dateofloss: '2022-01-01' });
        });

        it('returns empty object if configParams is not valid JSON', () => {
            const configParams = 'notjson';
            const queryStringParams = { policynbr: '123' };
            const result = wrapper.vm.combineClientParameters(configParams, queryStringParams);
            expect(result).toEqual({});
        });

        it('ignores params not present in query', () => {
            const configParams = JSON.stringify(['PolicyNbr', 'MissingParam']);
            const queryStringParams = { policynbr: '123' };
            const result = wrapper.vm.combineClientParameters(configParams, queryStringParams);
            expect(result).toEqual({ policynbr: '123' });
        });
    });
    test('populates store items from params', async () => {
        const mainInitialState = {
            issConfig: { disabledFields: {} },
            order: { policy: {} }
        };
        const params = {
            policynumber: 'ABC123',
            policyzipcode: '90210',
            dateofloss: '2022-01-01',
            returnurl: 'http://success',
            returnurl2: 'http://fail'
        };
        const { wrapper } = getMountedComponent(mainInitialState);
        wrapper.vm.populateStoreItemsFromParams(params);
        expect(wrapper.vm.mainStore.order.policy.policyNumber).toBe('ABC123');
        expect(wrapper.vm.mainStore.order.policy.policyZipCode).toBe('90210');
        expect(wrapper.vm.mainStore.order.policy.dateOfLoss).toBe('2022-01-01');
        expect(wrapper.vm.mainStore.issConfig.successReturnURL).toBe('http://success');
        expect(wrapper.vm.mainStore.issConfig.failureReturnURL).toBe('http://fail');
    });
});
