import { expectSaga } from 'redux-saga-test-plan';
import * as matchers from 'redux-saga-test-plan/matchers';
import { call, takeLatest } from 'redux-saga/effects';
import { throwError } from 'redux-saga-test-plan/providers';
import * as Api from '../../../services/api';
import * as sagas from '../sagas';
import * as types from '../constants';

describe('TestAndPreviewSlidebox Sagas', () => {
  describe('searchCustomersSaga', () => {
    it('should handle successful customer search', () => {
      const mockResponse = {
        result: {
          data: { 1: { id: 1, name: 'Customer 1' } },
        },
      };

      return expectSaga(sagas.searchCustomersSaga, {
        payload: {
          query: '432456',
        },
      })
        .provide([
          [call(Api.searchCustomers, { query: '432456' }), mockResponse],
        ])
        .put({
          type: types.SEARCH_CUSTOMERS_SUCCESS,
          payload: {
            customers: mockResponse.result.data,
          },
        })
        .run();
    });
    it('should handle error in searchCustomersSaga', () => {
      const error = 'Search failed';
      return expectSaga(sagas.searchCustomersSaga, {
        payload: {
          query: '432456',
        },
      })
        .provide([
          [call(Api.searchCustomers, { query: '432456' }), throwError(error)],
        ])
        .put({
          type: types.SEARCH_CUSTOMERS_FAILURE,
          payload: {
            error: 'Network error occurred',
          },
        })
        .run();
    });
    it('should handle error in searchCustomersSaga', () => {
      const error = new Error('Search failed');
      return expectSaga(sagas.searchCustomersSaga, {
        payload: {
          query: '432456',
        },
      })
        .provide([
          [call(Api.searchCustomers, { query: '432456' }), { isError: true, message: error.message }],
        ])
        .put({
          type: types.SEARCH_CUSTOMERS_FAILURE,
          payload: {
            error: error.message,
          },
        })
        .run();
    });
  });
  describe('extractTagsSaga', () => {
    it('should handle successful tag extraction', () => {
      const mockResponse = {
        data: [{
          tags: { 1: { id: 1, name: 'Tag 1' } },
        }],
      };
      return expectSaga(sagas.extractTagsSaga, {
        payload: {
          templateSubject: 'Test Subject',
          templateContent: 'Test Content',
        },
      })
        .provide([
          [call(Api.extractTagsWithMetaData, { messageTitle: 'Test Subject', messageBody: 'Test Content' }), mockResponse],
        ])
        .put({
          type: types.EXTRACT_TAGS_SUCCESS,
          payload: {
            extractedtags: mockResponse.data,
          },
        })
        .run();
    });
    it('should handle successful tag extraction', () => {
      const mockResponse = {
        data: [],
      };
      return expectSaga(sagas.extractTagsSaga, {
        payload: {
          templateSubject: 'Test Subject',
          templateContent: 'Test Content',
        },
      })
        .provide([
          [call(Api.extractTagsWithMetaData, { messageTitle: 'Test Subject', messageBody: 'Test Content' }), mockResponse],
        ])
        .put({
          type: types.EXTRACT_TAGS_FAILURE,
          payload: {
            error: 'Failed to extract tags',
          },
        })
        .run();
    });
    it('should handle error in extractTagsSaga', () => {
      const error = new Error('Tag extraction failed');
      return expectSaga(sagas.extractTagsSaga, {
        payload: {
          templateSubject: 'Test Subject',
          templateContent: 'Test Content',
        },
      })
        .provide([
          [call(Api.extractTagsWithMetaData, { messageTitle: 'Test Subject', messageBody: 'Test Content' }), throwError(error)],
        ])
        .put({
          type: types.EXTRACT_TAGS_FAILURE,
          payload: {
            error: error.message,
          },
        })
        .run();
    });
  });
  describe('updatePreviewSaga', () => {
    it('should handle successful preview update', () => {
      const mockResponse = {
        data: 'Test Preview Data',
      };
      const customValues = { test: 'value' };
      return expectSaga(sagas.updatePreviewSaga, {
        payload: {
          previewData: 'Test Preview Data',
          resolvedTags: customValues,
        },
      })
        .provide([
          [call(Api.updateEmailPreview, { previewData: 'Test Preview Data', resolvedTags: customValues }), mockResponse],
        ])
        .put({
          type: types.UPDATE_PREVIEW_SUCCESS,
          payload: {
            previewData: mockResponse.data,
            customValues,
          },
        })
        .run();
    });
    it('should throw error in updatePreviewSaga', () => {
      const mockResponse = {
        previewData: 'Test Preview Data',
        error: 'Failed to load preview',
      };
      const customValues = { test: 'value' };
      return expectSaga(sagas.updatePreviewSaga, {
        payload: {
          previewData: 'Test Preview Data',
          resolvedTags: customValues,
        },
      })
        .provide([
          [call(Api.updateEmailPreview, { previewData: 'Test Preview Data', resolvedTags: customValues }), mockResponse],
        ])
        .put({
          type: types.UPDATE_PREVIEW_FAILURE,
          payload: {
            error: 'Failed to load preview',
            customValues,
          },
        })
        .run();
    });
    it('should throw error in updatePreviewSaga', () => {
      const mockResponse = {
        previewData: 'Test Preview Data',
      };
      const customValues = { test: 'value' };
      return expectSaga(sagas.updatePreviewSaga, {
        payload: {
          previewData: 'Test Preview Data',
          resolvedTags: customValues,
        },
      })
        .provide([
          [call(Api.updateEmailPreview, { previewData: 'Test Preview Data', resolvedTags: customValues }), mockResponse],
        ])
        .put({
          type: types.UPDATE_PREVIEW_FAILURE,
          payload: {
            error: 'Failed to update preview',
            customValues,
          },
        })
        .run();
    });
    it('should handle error in updatePreviewSaga', () => {
      const error = new Error('Preview update failed');
      const customValues = { test: 'value' };
      return expectSaga(sagas.updatePreviewSaga, {
        payload: {
          previewData: 'Test Preview Data',
          resolvedTags: customValues,
        },
      })
        .provide([
          [call(Api.updateEmailPreview, { previewData: 'Test Preview Data', resolvedTags: customValues }), throwError(error)],
        ])
        .put({
          type: types.UPDATE_PREVIEW_FAILURE,
          payload: {
            error: error.message,
            customValues,
          },
        })
        .run();
    });
    it('should handle error in updatePreviewSaga', () => {
      const error = 'Preview update failed';
      const customValues = { test: 'value' };
      return expectSaga(sagas.updatePreviewSaga, {
        payload: {
          previewData: 'Test Preview Data',
          resolvedTags: customValues,
        },
      })
        .provide([
          [call(Api.updateEmailPreview, { previewData: 'Test Preview Data', resolvedTags: customValues }), throwError(error)],
        ])
        .put({
          type: types.UPDATE_PREVIEW_FAILURE,
          payload: {
            error: 'Network error occurred',
            customValues,
          },
        })
        .run();
    });
  });
  describe('sendTestMessageSaga', () => {
    it('should handle successful test message send', () => {
      const mockResponse = {
        data: {
          testMessage: 'Test Message',
        },
      };
      return expectSaga(sagas.sendTestMessageSaga, {
        payload: {
          testMessage: 'Test Message',
        },
        callback: jest.fn(),
      })
        .provide([
          [call(Api.sendTestMessage, { testMessage: 'Test Message' }), mockResponse],
        ])
        .put({
          type: types.SEND_TEST_MESSAGE_SUCCESS,
          payload: {
            response: true,
          },
        })
        .run();
    });
    it('should handle successful test message send', () => {
      const mockResponse = {
        errors: 'true',
      };
      return expectSaga(sagas.sendTestMessageSaga, {
        payload: {
          testMessage: 'Test Message',
        },
        callback: jest.fn(),
      })
        .provide([
          [call(Api.sendTestMessage, { testMessage: 'Test Message' }), mockResponse],
        ])
        .put({
          type: types.SEND_TEST_MESSAGE_FAILURE,
          payload: {
            response: false,
            error: 'true',
          },
        })
        .run();
    });
    it('should handle error in sendTestMessageSaga', () => {
      const error = new Error('Test message send failed');
      return expectSaga(sagas.sendTestMessageSaga, {
        payload: {
          testMessage: 'Test Message',
        },
        callback: jest.fn(),
      })
        .provide([
          [call(Api.sendTestMessage, { testMessage: 'Test Message' }), throwError(error)],
        ])
        .put({
          type: types.SEND_TEST_MESSAGE_FAILURE,
          payload: {
            response: false,
            error: error.message,
          },
        })
        .run();
    });
  });
  describe('fetchTestCustomersSaga', () => {
    it('should handle successful test customers fetch', () => {
      const mockResponse = {
        entity: {
          userIds: [1, 2, 3],
        },
      };
      return expectSaga(sagas.fetchTestCustomersSaga)
        .provide([
          [matchers.call.fn(Api.fetchTestCustomers), mockResponse],
          [matchers.call.fn(Api.getBulkCustomerDetails, { fetchedUserIds: [1, 2, 3] }), {
            result: {
              data: [
                {
                  entity: {
                    id: 1,
                    profiles: [{
                      firstName: 'John',
                      lastName: 'Doe',
                      identifiers: [{
                        type: 'mobile',
                        value: '1234567890',
                      }, {
                        type: 'email',
                        value: 'john@example.com',
                      }],
                    }],
                  },
                },
              ],
            },
          }],

        ])
        .put({
          type: types.FETCH_TEST_CUSTOMERS_SUCCESS,
          payload: {
            customers: [
              {
                userId: 1,
                name: 'John Doe',
                mobile: '1234567890',
                email: 'john@example.com',
              },
            ],
          },
        })
        .run();
    });
    it('should throw error in fetchTestCustomersSaga', () => {
      const mockResponse = {
        ent: {
          userIds: [1, 2, 3],
        },
      };
      return expectSaga(sagas.fetchTestCustomersSaga)
        .provide([
          [matchers.call.fn(Api.fetchTestCustomers), mockResponse],
          [matchers.call.fn(Api.getBulkCustomerDetails, { fetchedUserIds: [1, 2, 3] }), {
            result: {
              data: [
                {
                  entity: {
                    id: 1,
                    profiles: [{
                      firstName: 'John',
                      lastName: 'Doe',
                      identifiers: [{
                        type: 'mobile',
                        value: '1234567890',
                      }, {
                        type: 'email',
                        value: 'john@example.com',
                      }],
                    }],
                  },
                },
              ],
            },
          }],

        ])
        .put({
          type: types.FETCH_TEST_CUSTOMERS_FAILURE,
          payload: {
            error: 'Failed to fetch test customers',
          },
        })
        .run();
    });
    it('should throw error in fetchTestCustomersSaga', () => {
      const mockResponse = {
        entity: {
          userIds: 'not array',
        },
      };
      return expectSaga(sagas.fetchTestCustomersSaga)
        .provide([
          [matchers.call.fn(Api.fetchTestCustomers), mockResponse],
          [matchers.call.fn(Api.getBulkCustomerDetails, { fetchedUserIds: [1, 2, 3] }), {
            result: {
              data: [
                {
                  entity: {
                    id: 1,
                    profiles: [{
                      firstName: 'John',
                      lastName: 'Doe',
                      identifiers: [{
                        type: 'mobile',
                        value: '1234567890',
                      }, {
                        type: 'email',
                        value: 'john@example.com',
                      }],
                    }],
                  },
                },
              ],
            },
          }],

        ])
        .put({
          type: types.FETCH_TEST_CUSTOMERS_FAILURE,
          payload: {
            error: 'No test customers found',
          },
        })
        .run();
    });
    it('should handle error in fetchTestCustomersSaga', () => {
      const error = new Error('Test customers fetch failed');
      return expectSaga(sagas.fetchTestCustomersSaga)
        .provide([
          [call(Api.fetchTestCustomers), throwError(error)],
        ])
        .put({
          type: types.FETCH_TEST_CUSTOMERS_FAILURE,
          payload: {
            error: error.message,
          },
        })
        .run();
    });
  });
  describe('fetchTestGroupsSaga', () => {
    it('should handle successful test groups fetch', () => {
      const mockResponse = {
        entity: {
          userGroups: [
            {
              id: 1,
              name: 'Test Group',
              userIds: [1, 2, 3],
            },
          ],
        },
      };
      return expectSaga(sagas.fetchTestGroupsSaga)
        .provide([
          [call(Api.fetchTestGroups), mockResponse],
        ])
        .put({
          type: types.FETCH_TEST_GROUPS_SUCCESS,
          payload: {
            groups: mockResponse.entity.userGroups,
          },
        })
        .run();
    });
    it('should throw error in fetchTestGroupsSaga', () => {
      const mockResponse = {
        ent: {
          userGroups: [
            {
              id: 1,
              name: 'Test Group',
              userIds: [1, 2, 3],
            },
          ],
        },
      };
      return expectSaga(sagas.fetchTestGroupsSaga)
        .provide([
          [call(Api.fetchTestGroups), mockResponse],
        ])
        .put({
          type: types.FETCH_TEST_GROUPS_FAILURE,
          payload: {
            error: 'Failed to fetch test groups',
          },
        })
        .run();
    });
    it('should handle error in fetchTestGroupsSaga', () => {
      const error = new Error('Test groups fetch failed');
      return expectSaga(sagas.fetchTestGroupsSaga)
        .provide([
          [call(Api.fetchTestGroups), throwError(error)],
        ])
        .put({
          type: types.FETCH_TEST_GROUPS_FAILURE,
          payload: {
            error: error.message,
          },
        })
        .run();
    });
  });
  describe('createMessageMetaSaga', () => {
    it('should handle successful message meta creation', () => {
      const mockResponse = {
        data: {
          messageMeta: 'Test Message Meta',
        },
      };
      return expectSaga(sagas.createMessageMetaSaga, {
        payload: {
          messageMeta: 'Test Message Meta',
        },
        messageMetaConfigId: undefined,
        callback: jest.fn(),
      })
        .provide([
          [call(Api.createTestMessageMeta, { messageMeta: 'Test Message Meta' }), mockResponse],
        ])
        .put({
          type: types.CREATE_MESSAGE_META_SUCCESS,
          payload: {
            response: mockResponse,
          },
        })
        .run();
    });
    it('should handle error in createMessageMetaSaga', () => {
      const mockResponse = {
        errors: true,
      };
      return expectSaga(sagas.createMessageMetaSaga, {
        payload: {
          messageMeta: 'Test Message Meta',
        },
        messageMetaConfigId: '123',
        callback: jest.fn(),
      })
        .provide([
          [call(Api.updateTestMessageMeta, { data: { messageMeta: 'Test Message Meta' }, messageMetaConfigId: '123' }), mockResponse],
        ])
        .put({
          type: types.CREATE_MESSAGE_META_FAILURE,
          payload: {
            error: mockResponse.errors,
          },
        })
        .run();
    });
  });
  describe('getPrefilledValuesSaga', () => {
    it('should handle successful prefilled values fetch', () => {
      const mockResponse = {
        data: {
          resolvedTagValues: 'Test Prefilled Values',
        },
      };
      return expectSaga(sagas.getPrefilledValuesSaga, {
        payload: {
          previewData: 'test',
        },
      })
        .provide([
          [call(Api.updateEmailPreview, { previewData: 'test' }), mockResponse],
        ])
        .put({
          type: types.GET_PREFILLED_VALUES_SUCCESS,
          payload: {
            values: mockResponse.data.resolvedTagValues,
          },
        })
        .run();
    });
    it('should handle error in getPrefilledValuesSaga', () => {
      const error = new Error('Failed to fetch prefilled values');
      return expectSaga(sagas.getPrefilledValuesSaga, {
        payload: {
          previewData: 'test',
        },
      })
        .provide([
          [call(Api.updateEmailPreview, { previewData: 'test' }), error],
        ])
        .put({
          type: types.GET_PREFILLED_VALUES_FAILURE,
          payload: {
            error: error.message,
          },
        })
        .run();
    });
  });
});
describe('Saga watchers', () => {
  describe('watchSearchCustomersSaga', () => {
    const generator = sagas.watchSearchCustomers();
    it('should take the latest SEARCH_CUSTOMERS_REQUESTED actions and call searchCustomersSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.SEARCH_CUSTOMERS_REQUESTED, sagas.searchCustomersSaga));
    });
  });
  describe('watchExtractTagsSaga', () => {
    const generator = sagas.watchExtractTags();
    it('should take the latest EXTRACT_TAGS_REQUESTED actions and call extractTagsSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.EXTRACT_TAGS_REQUEST, sagas.extractTagsSaga));
    });
  });
  describe('watchUpdatePreviewSaga', () => {
    const generator = sagas.watchUpdatePreview();
    it('should take the latest UPDATE_PREVIEW_REQUESTED actions and call updatePreviewSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.UPDATE_PREVIEW_REQUEST, sagas.updatePreviewSaga));
    });
  });
  describe('watchSendTestMessageSaga', () => {
    const generator = sagas.watchSendTestMessage();
    it('should take the latest SEND_TEST_MESSAGE_REQUESTED actions and call sendTestMessageSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.SEND_TEST_MESSAGE_REQUESTED, sagas.sendTestMessageSaga));
    });
  });
  describe('watchFetchTestCustomersSaga', () => {
    const generator = sagas.watchFetchTestCustomers();
    it('should take the latest FETCH_TEST_CUSTOMERS_REQUESTED actions and call fetchTestCustomersSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.FETCH_TEST_CUSTOMERS_REQUESTED, sagas.fetchTestCustomersSaga));
    });
  });
  describe('watchFetchTestGroupsSaga', () => {
    const generator = sagas.watchFetchTestGroups();
    it('should take the latest FETCH_TEST_GROUPS_REQUESTED actions and call fetchTestGroupsSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.FETCH_TEST_GROUPS_REQUESTED, sagas.fetchTestGroupsSaga));
    });
  });
  describe('watchCreateMessageMetaSaga', () => {
    const generator = sagas.watchCreateMessageMeta();
    it('should take the latest CREATE_MESSAGE_META_REQUESTED actions and call createMessageMetaSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.CREATE_MESSAGE_META_REQUESTED, sagas.createMessageMetaSaga));
    });
  });
  describe('watchGetPrefilledValuesSaga', () => {
    const generator = sagas.watchGetPrefilledValues();
    it('should take the latest GET_PREFILLED_VALUES_REQUESTED actions and call getPrefilledValuesSaga', () => {
      expect(generator.next().value).toEqual(takeLatest(types.GET_PREFILLED_VALUES_REQUESTED, sagas.getPrefilledValuesSaga));
    });
  });
});
