import { getPartnerEngineConfig } from "@boldpenguin/sdk-redux";
import { newSpecPage } from "@stencil/core/testing";
import { BpSdkBusinessClassificationSelectorContainer } from "./bp-sdk-business-classification-selector-container";
const seedState = (store = {}) => {
    var _a, _b, _c, _d, _e;
    return (Object.assign(Object.assign({}, store), { application: Object.assign(Object.assign({}, ((_a = store === null || store === void 0 ? void 0 : store.application) !== null && _a !== void 0 ? _a : {})), { choices: Object.assign({}, ((_c = (_b = store === null || store === void 0 ? void 0 : store.application) === null || _b === void 0 ? void 0 : _b.choices) !== null && _c !== void 0 ? _c : {})) }), auth: Object.assign({}, ((_d = store === null || store === void 0 ? void 0 : store.auth) !== null && _d !== void 0 ? _d : {})), config: Object.assign({}, ((_e = store === null || store === void 0 ? void 0 : store.config) !== null && _e !== void 0 ? _e : {})) }));
};
const setupPage = async () => {
    const page = await newSpecPage({
        html: '<bp-sdk-business-classification-selector-container question_id="one"></bp-sdk-business-classification-selector-container>',
        components: [BpSdkBusinessClassificationSelectorContainer],
    });
    return page;
};
const setupInstance = (page, fakeStore) => {
    const state = seedState(fakeStore);
    const instance = page.rootInstance;
    instance.config = getPartnerEngineConfig(state);
    jest.spyOn(instance, 'searchChoices').mockImplementation(jest.fn());
    jest.spyOn(instance, 'searchChoicesWithNudges').mockImplementation(jest.fn());
    jest.spyOn(instance, 'removeActiveAnswerId').mockImplementation(jest.fn());
    instance.storeUnsubscribe = jest.fn();
    return instance;
};
describe('bp-sdk-business-classification-selector-container', () => {
    afterEach(() => {
        jest.resetAllMocks();
    });
    it('renders', async () => {
        const page = await setupPage();
        await page.waitForChanges();
        const element = page.root.querySelector('bp-sdk-business-classification-selector');
        expect(element).toBeTruthy();
        expect(page.root.querySelector('bp-sdk-external-business-classification-selector-container')).toBeFalsy();
    });
    it('should render when questionId matches available choices', async () => {
        const page = await setupPage();
        const fakeStore = {
            application: {
                choices: {
                    '1': {
                        list: ['some', 'items'],
                        timestamp: 100,
                    },
                },
            },
        };
        const instance = setupInstance(page, fakeStore);
        instance.questionId = '1';
        instance.remoteChoices = fakeStore.application.choices[instance.questionId].list;
        await page.waitForChanges();
        expect(instance._searchChoices).toEqual(instance.remoteChoices);
    });
    it('renders external component if defined', async () => {
        const whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
        const page = await setupPage();
        await page.waitForChanges();
        expect(page.root.querySelector('bp-sdk-external-business-classification-selector-container')).toBeTruthy();
        whenDefinedMock.mockRestore();
    });
    describe('doSearchChoices', () => {
        it('calls searchChoices', async () => {
            const fakeStore = {};
            const page = await setupPage();
            const instance = setupInstance(page, fakeStore);
            jest.spyOn(Date, 'now').mockReturnValue(100);
            instance.questionId = 'an id';
            const filterValue = 'some filter';
            instance._currentSearchValue = filterValue;
            jest.spyOn(instance, 'searchChoices').mockImplementation(jest.fn());
            instance.doSearchChoices();
            expect(instance.searchChoices).toBeCalledTimes(1);
            expect(instance.searchChoices).toBeCalledWith({
                config: getPartnerEngineConfig(seedState(fakeStore)),
                questionId: instance.questionId,
                filter: filterValue,
                refilter: null,
                timestamp: 100,
            });
        });
        it('does not call searchChoices when external is enabled', async () => {
            const fakeStore = {};
            const page = await setupPage();
            const instance = setupInstance(page, fakeStore);
            instance.useExternal = true;
            jest.spyOn(Date, 'now').mockReturnValue(100);
            instance.questionId = 'an id';
            const filterValue = 'some filter';
            instance._currentSearchValue = filterValue;
            instance.doSearchChoices();
            expect(instance.searchChoices).not.toHaveBeenCalled();
        });
    });
    describe('onFilterUpdate', () => {
        it('makes expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.doSearchChoices = jest.fn();
            const filterValue = 'some filter';
            instance.onFilterUpdate({
                detail: {
                    value: filterValue,
                },
            });
            expect(instance.doSearchChoices).toBeCalledTimes(1);
        });
        it('disables on useExternal', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.doSearchChoices = jest.fn();
            instance.useExternal = true;
            const filterValue = 'some filter';
            instance.onFilterUpdate({
                detail: {
                    value: filterValue,
                },
            });
            expect(instance.doSearchChoices).not.toHaveBeenCalled();
        });
    });
    describe('onValueUpdate', () => {
        it('resets show choices to false', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.showChoices = true;
            instance.onValueUpdate();
            expect(instance.showChoices).toBeFalsy();
        });
        it('does not change showChoices if useExternal is true', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.useExternal = true;
            instance.showChoices = true;
            instance.onValueUpdate();
            expect(instance.showChoices).toBeTruthy();
        });
        it('calls removeActiveAnswerId', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.onValueUpdate();
            expect(instance.removeActiveAnswerId).toHaveBeenCalled();
        });
        it('does not call removeActiveAnswerId when useExternal is true', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.useExternal = true;
            instance.onValueUpdate();
            expect(instance.removeActiveAnswerId).not.toHaveBeenCalled();
        });
    });
    describe('disconnectedCallback', () => {
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toHaveBeenCalledTimes(1);
        });
    });
    describe('onChoiceMapUpdate', () => {
        it('update expected properties with expected result', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.questionId = '1';
            instance.choiceId = '2';
            const questionChoices = [
                { id: '0', value: '0' },
                { id: '1', value: '1' },
            ];
            const choiceChoices = [{ id: '1', value: '1', description: 'bob', order: '0' }];
            instance.remoteChoices = choiceChoices;
            instance.onChoiceMapUpdate({
                '2': questionChoices,
            });
            await page.waitForChanges();
            expect(instance._searchChoices).toEqual([...choiceChoices]);
            expect(instance._selectedChoices).toEqual([...questionChoices]);
        });
        it('have expected fallbacks', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.questionId = '0';
            instance.choiceId = '0';
            const choiceChoices = [{ id: '1', value: '1' }];
            instance.remoteChoices = [];
            instance.onChoiceMapUpdate({
                '2': choiceChoices,
            });
            await page.waitForChanges();
            expect(instance._searchChoices).toEqual([]);
        });
    });
    describe('onChoicesUpdate', () => {
        it('update expected properties with expected result', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.questionId = '1';
            instance.choiceId = '2';
            const answerChoices = [{ id: '0', value: '0' }];
            const searchChoices = [
                { id: '0', value: '0', description: 'bob' },
                { id: '1', value: '1', description: 'alice' },
            ];
            instance.choiceMap = {
                '2': answerChoices,
            };
            instance.onChoicesUpdate(searchChoices);
            expect(instance._searchChoices).toEqual([...searchChoices]);
        });
        it('have expected fallbacks', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.questionId = '0';
            instance.choiceId = '0';
            const choiceChoices = [{ id: '1', value: '1' }];
            instance.remoteChoices = [];
            instance.choiceMap = {
                '2': choiceChoices,
            };
            instance.onChoicesUpdate([]);
            expect(instance._searchChoices).toEqual([]);
        });
    });
    describe('componentWillLoad', () => {
        it('has fallbacks', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance, 'onChoicesChange');
            instance.choices = undefined;
            expect(instance.onChoicesChange).toBeCalledTimes(1);
            instance.componentWillLoad();
            expect(instance.onChoicesChange).toBeCalledTimes(2);
            expect(instance.onChoicesChange).toBeCalledWith([]);
        });
    });
    describe('mapStateToProps', () => {
        it('returns remoteChoices', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.questionId = 'test123';
            const fakeStore = seedState({
                application: {
                    choices: {
                        test123: {
                            list: ['items'],
                        },
                    },
                },
            });
            const result = instance.mapStateToProps(fakeStore);
            expect(result.remoteChoices).toEqual(fakeStore.application.choices['test123'].list);
        });
        it('returns config', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const fakeStore = seedState({
                auth: {
                    token: 'token123',
                },
                config: {
                    env: 'test',
                    uri: 'http://test.local',
                },
            });
            const result = instance.mapStateToProps(seedState(fakeStore));
            expect(result.config).toEqual(Object.assign(Object.assign({}, fakeStore.config), { token: fakeStore.auth.token }));
        });
    });
});
