
import { expectSaga } from 'redux-saga-test-plan';
import { takeLatest } from 'redux-saga/effects';
import * as matchers from 'redux-saga-test-plan/matchers';
import { throwError } from 'redux-saga-test-plan/providers';
import { fromJS } from 'immutable';
import * as types from '../constants';
import * as sagas from '../sagas';
import { v2EmailDuplicateTemplateSaga, v2EmailSagas } from '../sagas';
import {transformEmailTemplates} from '../../../utils/cdnTransformation';
import * as Api from '../../../services/api';


describe('transformEmailTemplate saga', () => {
  it('handle valid response from api', () => {
    const callback = () => {};
    const action = {
      type: types.TRANSFORM_EMAIL_TEMPLATE_REQUEST,
      callback,
      template: {},
    };
    expectSaga(sagas.transformEmailTemplate, action)
      .provide([
        [
          matchers.call.fn(transformEmailTemplates),
          {
            success: true,
            status: {
              isError: false,
              code: 200,
              message: "success",
            },
            message: "Meta data fecthed successfully",
            response: {
              "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/f98ce0c0-53f8-4fbd-b4e3-05953dda.jpg": 1400,
            },
          },
        ],
        [matchers.call.fn(callback)],
      ])
      .run();
  });

  it('handles error thrown from api', () => {
    const callback = () => {};
    const action = {
      type: types.TRANSFORM_EMAIL_TEMPLATE_REQUEST,
      callback,
      template: {},
    };
    expectSaga(sagas.transformEmailTemplate, action)
      .provide([
        [matchers.call.fn(transformEmailTemplates), throwError()],
      ])
      .run();
  });
});

describe('watchTransformEmailTemplate saga', () => {
  let generator = null;
  beforeEach(() => {
    generator = sagas.watchTransformEmailTemplate();
  });
  it('handle valid response from api', () => {
    const progress1 = generator.next();
    const mockTask = takeLatest(types.TRANSFORM_EMAIL_TEMPLATE_REQUEST, sagas.transformEmailTemplate);
    expect(progress1.value).toEqual(mockTask);
  });
});


describe('Email Templates Sagas', () => {
  describe('createTemplate saga', () => {
    it('should handle creating a template successfully', () => {
      const template = { id: 1, name: 'New Template' };
      const fakeResponse = {
        success: true,
        response: { id: 1, name: 'New Template', status: 'created' },
        status: { code: 200 },
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({
          type: types.CREATE_TEMPLATE_SUCCESS, data: fakeResponse.response, statusCode: 200, errorMsg: undefined,
        })
        .run();
    });

    it('should handle creating a template successfully with onCreateTemplateComplete callback', () => {
      const onCreateTemplateComplete = jest.fn();
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete };
      const fakeResponse = {
        success: true,
        response: { id: 1, name: 'New Template', status: 'created' },
        status: { code: 200 },
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({
          type: types.CREATE_TEMPLATE_SUCCESS,
          data: fakeResponse.response,
          statusCode: 200,
          errorMsg: undefined,
        })
        .run()
        .then(() => {
          expect(onCreateTemplateComplete).toHaveBeenCalledWith(fakeResponse.response);
        });
    });

    it('should handle creating a template successfully when result has no status (statusCode empty string)', () => {
      const onCreateTemplateComplete = jest.fn();
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete };
      const fakeResponse = {
        success: true,
        response: { id: 1, name: 'New Template' },
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({
          type: types.CREATE_TEMPLATE_SUCCESS,
          data: fakeResponse.response,
          statusCode: '',
          errorMsg: undefined,
        })
        .run()
        .then(() => {
          expect(onCreateTemplateComplete).toHaveBeenCalledWith(fakeResponse.response);
        });
    });

    it('should handle errors when creating a template fails', () => {
      const template = { id: 1, name: 'New Template' };
      const fakeError = new Error('Failed to create template');

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), throwError(fakeError)],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, error: fakeError, errorMsg: fakeError.message })
        .run();
    });
  });

  describe('getTemplateDetails saga', () => {
    const id = 1;

    it('should fetch template details successfully', () => {
      const detailsResponse = { id: 1, name: 'Sample Template' };

      return expectSaga(sagas.getTemplateDetails, id)
        .provide([
          [matchers.call.fn(Api.getTemplateDetails), { response: detailsResponse }],
        ])
        .put({ type: types.GET_TEMPLATE_DETAILS_SUCCESS, data: detailsResponse })
        .run();
    });

    it('should handle error when fetching template details fails', () => {
      const error = new Error('Error fetching details');

      return expectSaga(sagas.getTemplateDetails, id)
        .provide([
          [matchers.call.fn(Api.getTemplateDetails), throwError(error)],
        ])
        .put({ type: types.GET_TEMPLATE_DETAILS_FAILURE, error })
        .run();
    });
  });

  describe('uploadAsset saga', () => {
    const file = new Blob();
    const assetType = 'image';
    const fileParams = { param1: 'value1' };

    it('should handle successful asset upload', () => {
      const uploadResponse = {
        response: { asset: { id: 1, url: 'http://example.com/asset.jpg', metaInfo: { secure_file_path: 'path', file_size: 1024 } } },
        status: { code: '200' },
      };

      return expectSaga(sagas.uploadAsset, file, assetType, fileParams)
        .provide([
          [matchers.call.fn(Api.uploadFile), uploadResponse],
        ])
        .put({
          type: types.UPLOAD_ASSET_SUCCESS,
          data: uploadResponse.response.asset,
          statusCode: '200',
        })
        .run();
    });

    it('should handle successful asset upload with no status (empty statusCode)', () => {
      const uploadResponse = {
        response: {
          asset: {
            id: 1,
            url: 'http://example.com/asset.jpg',
            metaInfo: { secure_file_path: 'path', file_size: 1024 },
          },
        },
      };

      return expectSaga(sagas.uploadAsset, file, assetType, fileParams)
        .provide([
          [matchers.call.fn(Api.uploadFile), uploadResponse],
        ])
        .put({
          type: types.UPLOAD_ASSET_SUCCESS,
          data: uploadResponse.response.asset,
          statusCode: '',
        })
        .run();
    });

    it('should handle failure in asset upload', () => {
      const error = new Error('Failed to upload asset');

      return expectSaga(sagas.uploadAsset, file, assetType, fileParams)
        .provide([
          [matchers.call.fn(Api.uploadFile), throwError(error)],
        ])
        .put({ type: types.UPLOAD_ASSET_FAILURE, error })
        .run();
    });
  });
});


describe('Combined Sagas', () => {
  it('v2EmailSagas should run specified sagas', () => expectSaga(v2EmailSagas)
    .run());

  it('v2EmailDuplicateTemplateSaga should run the duplicate template sagas', () => expectSaga(v2EmailDuplicateTemplateSaga)
    .run());
});


describe('duplicateTemplate saga', () => {
  it('handles successful duplication with callback', () => {
    const fakeResponse = {
      status: { code: 200 },
      response: { id: 2, name: 'Duplicated Template' },
    };
    const callback = jest.fn();
    const payload = { id: 1, channel: 'email', callback };

    return expectSaga(sagas.duplicateTemplate, payload)
      .provide([
        [matchers.call.fn(Api.duplicateTemplate, { id: 1, channel: 'email' }), fakeResponse],
      ])
      .put({
        type: types.DUPLICATE_TEMPLATE_SUCCESS,
        data: fakeResponse.response,
        statusCode: fakeResponse.status.code,
        errorMsg: undefined,
      })
      .run()
      .then(() => {
        expect(callback).toHaveBeenCalledWith(fakeResponse.response);
      });
  });

  it('handles API error', () => {
    const payload = { id: 1, channel: 'email' };
    const error = new Error('API error');

    return expectSaga(sagas.duplicateTemplate, payload)
      .provide([
        [matchers.call.fn(Api.duplicateTemplate, { id: 1, channel: 'email' }), throwError(error)],
      ])
      .put({
        type: types.DUPLICATE_TEMPLATE_FAILURE,
        error,
        errorMsg: undefined,
      })
      .run();
  });

  it('handles server-side error status', () => {
    const fakeResponse = {
      status: { code: 500 },
      message: 'Internal server error',
    };
    const payload = { id: 1, channel: 'email' };

    return expectSaga(sagas.duplicateTemplate, payload)
      .provide([
        [matchers.call.fn(Api.duplicateTemplate, { id: 1, channel: 'email' }), fakeResponse],
      ])
      .put({
        type: types.DUPLICATE_TEMPLATE_SUCCESS,
        data: undefined,
        statusCode: fakeResponse.status.code,
        errorMsg: 'Internal server error',
      })
      .run();
  });
});

describe('getAllAssets saga', () => {
  it('handles successful duplication with callback', () => {
    const fakeResponse = {
      status: { code: 200 },
      response: { id: 2, name: 'Duplicated Template' },
    };
    const callback = jest.fn();
    const payload = {assetType: 'image', queryParams: { page: 1 }, callback };

    return expectSaga(sagas.getAllAssets, payload)
      .provide([
        [matchers.call.fn(Api.getAllAssets, { id: 1, channel: 'email' }), fakeResponse],
      ])
      .put({
        type: types.GET_ALL_ASSETS_SUCCESS,
        data: fakeResponse.response,
        isReset: true,
      })
      .run();
  });

  it('handles server-side error status', () => {
    const fakeResponse = {
      status: { code: 500 },
      message: 'Internal server error',
    };
    const payload = {assetType: 'image', queryParams: { page: 1 } };

    return expectSaga(sagas.getAllAssets, payload)
      .provide([
        [matchers.call.fn(Api.getAllAssets, { id: 1, channel: 'email' }), fakeResponse],
      ])
      .put({
        type: types.GET_ALL_ASSETS_SUCCESS,
        data: undefined,
        isReset: true,
      })
      .run();
  });

  it('should handle success when page > 1 (isReset false)', () => {
    const fakeResponse = {
      status: { code: 200 },
      response: [{ id: 3, name: 'Asset 3' }],
    };
    const payload = { assetType: 'image', queryParams: { page: 2 } };

    return expectSaga(sagas.getAllAssets, payload)
      .provide([
        [matchers.call.fn(Api.getAllAssets), fakeResponse],
      ])
      .put({
        type: types.GET_ALL_ASSETS_SUCCESS,
        data: fakeResponse.response,
        isReset: false,
      })
      .run();
  });

  it('should handle failure when fetching all assets throws an error', () => {
    const error = new Error('Network error');
    const payload = { assetType: 'image', queryParams: { page: 1 } };

    return expectSaga(sagas.getAllAssets, payload)
      .provide([
        [matchers.call.fn(Api.getAllAssets), throwError(error)],
      ])
      .put({ type: types.GET_ALL_ASSETS_FAILURE, error })
      .run();
  });

  describe('getCmsAccounts saga', () => {
    it('should handle successful CMS accounts fetch with matching type', () => {
      const cmsType = 'bee';
      const fakeResponse = {
        data: {
          response: {
            cmsAccounts: {
              type: 'bee',
            },
          },
        },
      };

      return expectSaga(sagas.getCmsAccounts, { cmsType })
        .provide([
          [matchers.call.fn(Api.getCmsAccounts), fakeResponse],
        ])
        .put({ type: types.GET_CMS_ACCOUNTS_SUCCESS, isBeeEnabled: true })
        .run();
    });

    it('should handle CMS accounts fetch when type does not match', () => {
      const cmsType = 'bee';
      const fakeResponse = {
        data: {
          response: {
            cmsAccounts: {
              type: 'other',
            },
          },
        },
      };

      return expectSaga(sagas.getCmsAccounts, { cmsType })
        .provide([
          [matchers.call.fn(Api.getCmsAccounts), fakeResponse],
        ])
        .put({ type: types.GET_CMS_ACCOUNTS_SUCCESS, isBeeEnabled: false })
        .run();
    });

    it('should handle CMS accounts fetch when response structure is different', () => {
      const cmsType = 'bee';
      const fakeResponse = {
        data: {
          response: {},
        },
      };

      return expectSaga(sagas.getCmsAccounts, { cmsType })
        .provide([
          [matchers.call.fn(Api.getCmsAccounts), fakeResponse],
        ])
        .put({ type: types.GET_CMS_ACCOUNTS_SUCCESS, isBeeEnabled: false })
        .run();
    });

    it('should handle error when fetching CMS accounts fails', () => {
      const cmsType = 'bee';
      const fakeError = new Error('Failed to fetch CMS accounts');

      return expectSaga(sagas.getCmsAccounts, { cmsType })
        .provide([
          [matchers.call.fn(Api.getCmsAccounts), throwError(fakeError)],
        ])
        .put({ type: types.GET_CMS_ACCOUNTS_FAILURE, error: fakeError })
        .run();
    });
  });

  describe('createTemplate saga error handling paths', () => {
    it('should handle API error with status code >= 400', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeResponse = {
        success: false,
        status: { code: 400 },
        message: 'Bad Request',
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'Bad Request' })
        .run()
        .then(() => {
          expect(template.onCreateTemplateComplete).toHaveBeenCalledWith({
            error: true,
            message: 'Bad Request',
            statusCode: 400,
          });
        });
    });

    it('should handle API error with errorMessage field', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeResponse = {
        success: false,
        status: { code: 500 },
        errorMessage: 'Server Error',
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'Server Error' })
        .run();
    });

    it('should handle API error with error.message field', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeResponse = {
        success: false,
        status: { code: 500 },
        error: { message: 'Error from error object' },
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'Error from error object' })
        .run();
    });

    it('should handle API error with response.message field', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeResponse = {
        success: false,
        status: { code: 500 },
        response: { message: 'Error from response' },
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'Error from response' })
        .run();
    });

    it('should handle API error with status.message field', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeResponse = {
        success: false,
        status: { code: 500, message: 'Error from status' },
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'Error from status' })
        .run();
    });

    it('should handle API error with data.message field', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeResponse = {
        success: false,
        status: { code: 500 },
        data: { message: 'Error from data' },
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'Error from data' })
        .run();
    });

    it('should handle API error with unknown status code', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeResponse = {
        success: false,
        status: 500,
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'API Error: 500' })
        .run();
    });

    it('should use "Unknown error" fallback when statusCode is also undefined', () => {
      const template = { id: 1, name: 'New Template' };
      const fakeResponse = {
        success: false,
      };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'API Error: Unknown error' })
        .run();
    });

    it('should handle callback error gracefully', () => {
      const template = {
        id: 1,
        name: 'New Template',
        onCreateTemplateComplete: jest.fn(() => {
          throw new Error('Callback error');
        }),
      };
      const fakeResponse = {
        success: false,
        status: { code: 400 },
        message: 'Bad Request',
      };

      const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), fakeResponse],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg: 'Bad Request' })
        .run()
        .then(() => {
          expect(consoleErrorSpy).toHaveBeenCalledWith(
            '[Email Saga] Error executing callback:',
            expect.any(Error)
          );
          consoleErrorSpy.mockRestore();
        });
    });

    it('should handle catch block with error message', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeError = { message: 'Error message' };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), throwError(fakeError)],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, error: fakeError, errorMsg: 'Error message' })
        .run()
        .then(() => {
          expect(template.onCreateTemplateComplete).toHaveBeenCalledWith({
            error: true,
            message: 'Error message',
          });
        });
    });

    it('should handle catch block with error toString', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeError = { toString: () => 'Error string' };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), throwError(fakeError)],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, error: fakeError, errorMsg: 'Error string' })
        .run()
        .then(() => {
          expect(template.onCreateTemplateComplete).toHaveBeenCalledWith({
            error: true,
            message: 'Error string',
          });
        });
    });

    it('should handle catch block with unknown error', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      // Create an error object without message
      // error.toString() on {} returns '[object Object]', which is truthy, so it will be used
      const fakeError = {};

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), throwError(fakeError)],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, error: fakeError, errorMsg: '[object Object]' })
        .run()
        .then(() => {
          expect(template.onCreateTemplateComplete).toHaveBeenCalledWith({
            error: true,
            message: '[object Object]',
          });
        });
    });

    it('should handle catch block when toString returns empty string', () => {
      const template = { id: 1, name: 'New Template', onCreateTemplateComplete: jest.fn() };
      const fakeError = { toString: () => '' };

      return expectSaga(sagas.createTemplate, template)
        .provide([
          [matchers.call.fn(Api.createEmailTemplate), throwError(fakeError)],
        ])
        .put({ type: types.CREATE_TEMPLATE_FAILURE, error: fakeError, errorMsg: 'An unexpected error occurred' })
        .run()
        .then(() => {
          expect(template.onCreateTemplateComplete).toHaveBeenCalledWith({
            error: true,
            message: 'An unexpected error occurred',
          });
        });
    });
  });
});


describe('getCmsSetting saga', () => {
  const basePayload = {
    cmsType: 'bee',
    projectId: 1,
    cmsMode: 'normal',
    langId: 1,
    isEdmSupport: false,
    isBEEAppEnable: true,
  };

  it('should handle successful settings fetch with matching type (isBeeEnabled true)', () => {
    const fakeResponse = {
      data: {
        response: {
          cmsDetails: { type: 'bee', settings: {} },
        },
      },
    };

    return expectSaga(sagas.getCmsSetting, basePayload)
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: true, isBeeEnabled: true });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: fakeResponse.data.response.cmsDetails, isBeeEnabled: true })
      .run();
  });

  it('should handle successful settings fetch with non-matching type (isBeeEnabled false)', () => {
    const fakeResponse = {
      data: {
        response: {
          cmsDetails: { type: 'ck', settings: {} },
        },
      },
    };

    return expectSaga(sagas.getCmsSetting, basePayload)
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: true, isBeeEnabled: false });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: fakeResponse.data.response.cmsDetails, isBeeEnabled: false })
      .run();
  });

  it('should handle successful settings fetch when cmsDetails is undefined (fallback to empty object)', () => {
    const fakeResponse = {
      data: {
        response: {},
      },
    };

    return expectSaga(sagas.getCmsSetting, basePayload)
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: true, isBeeEnabled: false });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: {}, isBeeEnabled: false })
      .run();
  });

  it('should handle error when fetching CMS settings fails', () => {
    const fakeError = new Error('Failed to fetch CMS settings');

    return expectSaga(sagas.getCmsSetting, basePayload)
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: true, isBeeEnabled: true });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), throwError(fakeError)],
      ])
      .put({ type: types.GET_CMS_EDITOR_DETAILS_FAILURE, error: fakeError })
      .run();
  });

  it('should wait for accounts when fetchingCmsAccounts is true and cmsAccountsLoaded is false (accounts succeed)', () => {
    const fakeResponse = {
      data: { response: { cmsDetails: { type: 'bee', settings: {} } } },
    };
    let selectCallCount = 0;

    return expectSaga(sagas.getCmsSetting, basePayload)
      .provide([
        {
          select(effect, next) {
            selectCallCount += 1;
            if (selectCallCount === 1) {
              return fromJS({ cmsAccountsLoaded: false, fetchingCmsAccounts: true, isBeeEnabled: null });
            }
            return fromJS({ cmsAccountsLoaded: true, fetchingCmsAccounts: false, isBeeEnabled: true });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .dispatch({ type: types.GET_CMS_ACCOUNTS_SUCCESS, isBeeEnabled: true })
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: { type: 'bee', settings: {} }, isBeeEnabled: true })
      .run();
  });

  it('should wait for accounts when fetchingCmsAccounts is true and cmsAccountsLoaded is false (accounts fail)', () => {
    const fakeResponse = {
      data: { response: { cmsDetails: { type: 'ck', settings: {} } } },
    };
    let selectCallCount = 0;

    return expectSaga(sagas.getCmsSetting, basePayload)
      .provide([
        {
          select(effect, next) {
            selectCallCount += 1;
            if (selectCallCount === 1) {
              return fromJS({ cmsAccountsLoaded: false, fetchingCmsAccounts: true, isBeeEnabled: null });
            }
            return fromJS({ cmsAccountsLoaded: true, fetchingCmsAccounts: false, isBeeEnabled: false });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .dispatch({ type: types.GET_CMS_ACCOUNTS_FAILURE })
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: { type: 'ck', settings: {} }, isBeeEnabled: false })
      .run();
  });

  it('should skip wait and use isBEEAppEnableFromAction as fallback when cmsAccountsLoaded is false but fetchingCmsAccounts is false', () => {
    const fakeResponse = {
      data: { response: { cmsDetails: { type: 'bee', settings: {} } } },
    };

    return expectSaga(sagas.getCmsSetting, { ...basePayload, isBEEAppEnable: true })
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: false, fetchingCmsAccounts: false, isBeeEnabled: null });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: { type: 'bee', settings: {} }, isBeeEnabled: true })
      .run();
  });

  it('should use state isBeeEnabled (null) and fall back to isBEEAppEnableFromAction via ?? operator', () => {
    const fakeResponse = {
      data: { response: { cmsDetails: { type: 'bee', settings: {} } } },
    };

    return expectSaga(sagas.getCmsSetting, { ...basePayload, isBEEAppEnable: true })
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: true, fetchingCmsAccounts: false, isBeeEnabled: null });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .call(Api.getCmsTemplateSettingsV2, basePayload.cmsType, basePayload.projectId, basePayload.cmsMode, basePayload.langId, basePayload.isEdmSupport, true)
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: { type: 'bee', settings: {} }, isBeeEnabled: true })
      .run();
  });

  it('should use state isBeeEnabled false over isBEEAppEnableFromAction true via ?? operator (false is not null/undefined)', () => {
    const fakeResponse = {
      data: { response: { cmsDetails: { type: 'bee', settings: {} } } },
    };

    return expectSaga(sagas.getCmsSetting, { ...basePayload, isBEEAppEnable: true })
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: true, fetchingCmsAccounts: false, isBeeEnabled: false });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .call(Api.getCmsTemplateSettingsV2, basePayload.cmsType, basePayload.projectId, basePayload.cmsMode, basePayload.langId, basePayload.isEdmSupport, false)
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: { type: 'bee', settings: {} }, isBeeEnabled: true })
      .run();
  });

  it('should derive isBeeEnabled false when cmsDetails type is undefined', () => {
    const fakeResponse = {
      data: { response: { cmsDetails: { settings: {} } } },
    };

    return expectSaga(sagas.getCmsSetting, basePayload)
      .provide([
        {
          select(effect, next) {
            return fromJS({ cmsAccountsLoaded: true, fetchingCmsAccounts: false, isBeeEnabled: true });
          },
        },
        [matchers.call.fn(Api.getCmsTemplateSettingsV2), fakeResponse],
      ])
      .put({ type: types.GET_CMS_EDITOR_DETAILS_SUCCESS, settings: { settings: {} }, isBeeEnabled: false })
      .run();
  });
});


describe('getCmsData saga', () => {
  const payload = { cmsType: 'bee', projectId: 1, langId: 1 };

  it('should handle successful CMS data fetch', () => {
    const fakeResponse = {
      data: {
        response: {
          data: { html: '<p>content</p>' },
          langId: 1,
        },
      },
    };

    return expectSaga(sagas.getCmsData, payload)
      .provide([
        [matchers.call.fn(Api.getCmsTemplateDataV2), fakeResponse],
      ])
      .put({
        type: types.GET_CMS_EDITOR_DATA_SUCCESS,
        data: fakeResponse.data.response.data,
        langId: fakeResponse.data.response.langId,
      })
      .run();
  });

  it('should handle error when fetching CMS data fails', () => {
    const fakeError = new Error('Failed to fetch CMS data');

    return expectSaga(sagas.getCmsData, payload)
      .provide([
        [matchers.call.fn(Api.getCmsTemplateDataV2), throwError(fakeError)],
      ])
      .put({ type: types.GET_CMS_EDITOR_DATA_FAILURE, error: fakeError })
      .run();
  });
});
