import {
    CORE_API_ENDPOINT,
    FORM_API_ENDPOINT,
    FORM_DEPLOY_API_ENDPOINT,
    generateUniqueID,
    searchForms,
    deleteForm,
    fetchFormDetails,
    getAllForms,
    deployForm,
    saveForm,
} from '../FormService';
import { request } from '../../request';

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

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

const response = { success: true, message: 'Hello World', data: ['mock'] };
const falseResponse = { success: false, message: 'Hello World', data: [] };

describe('generateUniqueID', () => {
    afterEach(jest.clearAllMocks);
    test('fetches successfully data from an API', async () => {
        const response = {
            success: true,
            data: { id: 123 },
        };
        mockedRequest.get.mockResolvedValue(response);
        const result = await generateUniqueID();
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(result).toEqual(response);
    });

    test('generateUniqueID() should call wilth proper Request URL', async () => {
        await generateUniqueID();
        expect(mockedRequest.get).toHaveBeenCalledWith(`${CORE_API_ENDPOINT}`);
    });

    test('fetches erroneously data from an API', async () => {
        const response = {
            success: false,
            data: null,
        };
        mockedRequest.get.mockResolvedValue(response);
        const result = await generateUniqueID();
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(result).toEqual({ success: false });
    });
});

describe('searchForms', () => {
    afterEach(jest.clearAllMocks);
    test('fetches successfully data from an API', async () => {
        mockedRequest.get.mockResolvedValue(response);
        const result = await searchForms('test');
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(mockedRequest.get).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}/search?idOrNameLike=test`);
        expect(result).toEqual(response);
    });

    test('fetches erroneously data from an API', async () => {
        mockedRequest.get.mockResolvedValue(falseResponse);
        const result = await searchForms('react');
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(mockedRequest.get).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}/search?idOrNameLike=react`);
        expect(result).toEqual({ success: false });
    });
});

describe('deleteForm', () => {
    afterEach(jest.clearAllMocks);
    test('fetches successfully data from an API', async () => {
        mockedRequest.delete.mockResolvedValue(response);
        const result = await deleteForm(123);
        expect(mockedRequest.delete).toHaveBeenCalledTimes(1);
        expect(mockedRequest.delete).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}/123`);
        expect(result).toEqual({ success: true, message: 'Hello World' });
    });

    test('fetches erroneously data from an API', async () => {
        mockedRequest.delete.mockResolvedValue(falseResponse);
        const result = await deleteForm(123);
        expect(mockedRequest.delete).toHaveBeenCalledTimes(1);
        expect(mockedRequest.delete).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}/123`);
        expect(result).toEqual({ success: false });
    });
});

describe('fetchFormDetails', () => {
    afterEach(jest.clearAllMocks);
    test('fetches successfully data from an API', async () => {
        mockedRequest.get.mockResolvedValue(response);
        const result = await fetchFormDetails(123);
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(mockedRequest.get).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}/123`);
        expect(result).toEqual(response);
    });

    test('fetches erroneously data from an API', async () => {
        mockedRequest.get.mockResolvedValue(falseResponse);
        const result = await fetchFormDetails(123);
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(mockedRequest.get).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}/123`);
        expect(result).toEqual({ success: false });
    });
});

describe('getAllForms', () => {
    afterEach(jest.clearAllMocks);
    test('fetches successfully data from an API', async () => {
        mockedRequest.get.mockResolvedValue(response);
        const result = await getAllForms();
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(mockedRequest.get).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}?include-form-content=false`);
        expect(result).toEqual({ success: true, data: ['mock'] });
    });

    test('fetches erroneously data from an API', async () => {
        mockedRequest.get.mockResolvedValue(falseResponse);
        const result = await getAllForms();
        expect(mockedRequest.get).toHaveBeenCalledTimes(1);
        expect(mockedRequest.get).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}?include-form-content=false`);
        expect(result).toEqual({ success: false });
    });
});

describe('deployForm', () => {
    afterEach(jest.clearAllMocks);

    const mockFormDetails = {
        name: 'Test',
        id: 123,
        components: {},
        version: 1,
    };
    const apiData = {
        formName: 'Test',
        formKey: 123,
        formContent: {},
        formVersion: 1,
        tenantId: 1,
    };
    test('fetches successfully data from an API', async () => {
        mockedRequest.post.mockResolvedValue(response);
        const result = await deployForm(mockFormDetails);
        expect(mockedRequest.post).toHaveBeenCalledTimes(1);
        expect(mockedRequest.post).toHaveBeenCalledWith(FORM_DEPLOY_API_ENDPOINT, apiData);
        expect(result).toEqual({ success: true, message: 'Hello World' });
    });

    test('fetches erroneously data from an API', async () => {
        mockedRequest.post.mockResolvedValue(falseResponse);
        const result = await deployForm(mockFormDetails);
        expect(mockedRequest.post).toHaveBeenCalledTimes(1);
        expect(result).toEqual({ success: false });
    });
});

describe('saveForm', () => {
    afterEach(jest.clearAllMocks);
    const mockFormDetails = {
        name: 'Test',
        id: 'test',
        version: 1,
        content: {},
    };
    test('fetches successfully data from an API', async () => {
        mockedRequest.post.mockResolvedValue(response);
        const result = await saveForm(mockFormDetails);
        expect(mockedRequest.post).toHaveBeenCalledTimes(1);
        expect(mockedRequest.post).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}`, mockFormDetails);
        expect(result).toEqual({ success: true, message: 'Hello World' });
    });

    test('fetches erroneously data from an API', async () => {
        mockedRequest.post.mockResolvedValue(falseResponse);
        const result = await saveForm(mockFormDetails);
        expect(mockedRequest.post).toHaveBeenCalledTimes(1);
        expect(mockedRequest.post).toHaveBeenCalledWith(`${FORM_API_ENDPOINT}`, mockFormDetails);
        expect(result).toEqual({ success: false });
    });
});
