import React from 'react';
import { act, render, fireEvent, waitFor, cleanup } from '@testing-library/react';
import FormModeler from '..';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
// import { request } from '../../../request';
import LocaleProvider from '../../../context/LocaleContext';
import FileSaver from 'file-saver';
import fetchMock from 'fetch-mock';
import { ID_ENDPOINT, FORM_ENDPOINT } from '../../../constants/endpoints';

const successMessageProps = {
    common: {
        successMessage: 'success message',
        open_flash_message: true,
        cleanAlerts: jest.fn(),
    },
};

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const store = mockStore(successMessageProps);

// jest.mock('../../../request.ts');

jest.mock('file-saver', () => ({ saveAs: jest.fn() }));

// const mockedRequest = request as jest.Mocked<typeof request>;

const testData = {
    display: 'form',
    components: [
        {
            defaultValue: '',
            description: '',
            disableOnInvalid: false,
            disabled: false,
            input: true,
            inputType: 'text',
            key: 'mobileNo',
            label: 'mobile no',
            multiple: false,
            placeholder: 'enter mob no',
            type: 'textfield',
        },
    ],
};

const response = {
    success: true,
    data: [
        {
            components: {
                ...testData,
            },
            id: '123',
            name: 'Testname',
            version: 1,
        },
    ],
};

const postResponse = {
    success: true,
    data: {
        components: {
            ...testData,
        },
        id: '123',
        name: 'SingleFormTest',
        version: 1,
    },
};

describe('FormModeler', () => {
    beforeEach(() => {
        jest.resetModules();

        fetchMock.mock(`undefineddocumentType`, {
            success: false,
            data: undefined,
        });
        fetchMock.mock(`/undefined${ID_ENDPOINT}`, {
            success: true,
            data: { id: '123' },
        });
        fetchMock.mock(`/undefined${FORM_ENDPOINT}?include-form-content=false`, response);
    });
    afterEach(() => {
        cleanup;
        fetchMock.reset();
    });
    // beforeAll(() => {
    //     fetchMock.mock(`undefineddocumentType`, {
    //         success: false,
    //         data: undefined,
    //     });
    //     fetchMock.mock(`/undefined${ID_ENDPOINT}`, {
    //         success: true,
    //         data: { id: '123' },
    //     });
    //     fetchMock.mock(`/undefined${FORM_ENDPOINT}?include-form-content=true`, response);
    // });

    test('onClick on Single form', async () => {
        fetchMock.mock('/undefined/form-modeler/v1/forms', { success: true });
        await act(async () => {
            const { getByText, getByTestId, queryByText } = render(
                <LocaleProvider>
                    <Provider store={store}>
                        <FormModeler />
                    </Provider>
                </LocaleProvider>,
            );
            const nameButton = await waitFor(() => getByTestId('testName'));
            await waitFor(() => fetchMock.mock(`/undefined/form-modeler/v1/forms/123`, postResponse));
            fireEvent.click(nameButton);
            expect(getByText('Testname')).toBeInTheDocument();
            await waitFor(() => expect(getByText('Delete')).toBeInTheDocument());
            expect(getByTestId('deploy')).toBeInTheDocument();
            expect(getByTestId('saveButton')).toBeInTheDocument();
            expect(getByTestId('delete')).toBeInTheDocument();
            await waitFor(() => fireEvent.click(getByTestId('saveButton')));
            expect(getByText('Form')).toBeInTheDocument();
            fireEvent.click(getByText('Submit'));
            await waitFor(() => {
                expect(queryByText('Form')).not.toBeInTheDocument();
            });
            await waitFor(() => fireEvent.click(getByTestId('saveButton')));
            await waitFor(() => fireEvent.click(getByText('Cancel')));
            await waitFor(() => {
                expect(queryByText('Form')).not.toBeInTheDocument();
            });
        });
    });

    test('form details api error', async () => {
        await act(async () => {
            const { queryByText, getByTestId } = render(
                <LocaleProvider>
                    <Provider store={store}>
                        <FormModeler />
                    </Provider>
                </LocaleProvider>,
            );
            const nameButton = await waitFor(() => getByTestId('testName'));
            await waitFor(() => fetchMock.mock(`/undefined/form-modeler/v1/forms/123`, { success: false }));
            await waitFor(() => fireEvent.click(nameButton));
            expect(queryByText('mobile no')).not.toBeInTheDocument();
        });
    });

    test('View Form onClick of it', async () => {
        await act(async () => {
            const { getByText, getByTestId } = render(
                <LocaleProvider>
                    <Provider store={store}>
                        <FormModeler />
                    </Provider>
                </LocaleProvider>,
            );
            const nameButton = await waitFor(() => getByTestId('testName'));
            await waitFor(() => fetchMock.mock(`/undefined/form-modeler/v1/forms/123`, postResponse));
            fireEvent.click(nameButton);

            const viewFormButton = await waitFor(() => getByTestId('viewForm'));
            await waitFor(() => fireEvent.click(viewFormButton));
            expect(getByText('Submit')).toBeInTheDocument();
            // expect(getByText('mobileNo')).toBeInTheDocument();
        });
    });

    test('Download File', async () => {
        await act(async () => {
            const { getByTestId } = render(
                <LocaleProvider>
                    <Provider store={store}>
                        <FormModeler />
                    </Provider>
                </LocaleProvider>,
            );

            const downloadButton = await waitFor(() => getByTestId('downloadForm'));
            fireEvent.click(downloadButton);

            await waitFor(() => {
                expect(FileSaver.saveAs).toBeCalled();
            });
        });
    });

    test('Creating NewForm', async () => {
        await act(async () => {
            const { getByText, getByTestId } = render(
                <LocaleProvider>
                    <Provider store={store}>
                        <FormModeler />
                    </Provider>
                </LocaleProvider>,
            );

            const newFormButton = await waitFor(() => getByTestId('createNewForm'));
            fireEvent.click(newFormButton);
            await waitFor(() => {
                //
            });
            expect(getByText('Submit')).toBeInTheDocument();
            expect(getByText('Drag and Drop a form component')).toBeInTheDocument();
        });
    });

    test('Open Form', async () => {
        await act(async () => {
            const { getByText, getByLabelText } = render(
                <LocaleProvider>
                    <Provider store={store}>
                        <FormModeler />
                    </Provider>
                </LocaleProvider>,
            );

            const file = new File(
                [
                    JSON.stringify({
                        ...testData,
                    }),
                ],
                'file.json',
                { type: 'text/json' },
            );
            const uploadButton = getByLabelText('file-upload');
            await waitFor(() =>
                fireEvent.change(uploadButton, {
                    target: { files: [file] },
                }),
            );
            await waitFor(() => expect(getByText('mobile no')).toBeInTheDocument());
        });
    });
});
