import { expectSaga } from 'redux-saga-test-plan';

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

describe('Facebook Ad Management Sagas', () => {
  describe('fetchMarketingObjectives Saga', () => {
    it.concurrent('handles successful fetching of marketing objectives', () => {
      const fakeResponse = {
        data: [{ id: 1, name: 'Increase Reach' }],
        errors: []
      };

      return expectSaga(sagas.fetchMarketingObjectives)
        .provide([
          [matchers.call.fn(Api.getMarketingObjectives, 'FACEBOOK'), fakeResponse]
        ])
        .put({
          type: types.SET_MARKETING_OBJECTIVES_SUCCESS,
          payload: fakeResponse.data,
        })
        .run();
    });

    it.concurrent('handles errors in fetching marketing objectives', () => {
      const fakeResponse = {
        errors: ['Error fetching data'],
        data: null
      };

      return expectSaga(sagas.fetchMarketingObjectives)
        .provide([
          [matchers.call.fn(Api.getMarketingObjectives, 'FACEBOOK'), throwError(new Error('Error'))]
        ])
        .put({
          type: types.SET_MARKETING_OBJECTIVES_FAILURE,
          payload: new Error('Error'),
        })
        .run();
    });
  });

  describe('getOrgOUs Saga', () => {
    const orgID = '123';

    it.concurrent('handles successful fetching of org OUs', () => {
      const fakeResponse = {
        status: 200,
        result: [{ id: 1, name: 'Org Unit One' }],
      };

      return expectSaga(sagas.getOrgOUs, { orgID })
        .provide([
          [matchers.call.fn(Api.getOrgOUs, { orgID }), fakeResponse]
        ])
        .put({
          type: types.GET_ORG_OU_LIST_SUCCESS,
          payload: fakeResponse.result,
        })
        .run();
    });

    it.concurrent('handles failure in fetching org OUs', () => {
      const error = new Error('Fetch failed');

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

  describe('uploadFbAdAsset Saga', () => {
    const file = { name: 'ad.mp4', assetType: 'video', videoData: { accessToken: 'abc123' } };
    const assetType = 'video';
    const fileParams = {};

    it.concurrent('handles successful asset upload', () => {
      const uploadResponse = {
        status: { code: 200 },
        response: { asset: { id: 1, metaInfo: { secure_file_path: 'http://example.com/ad.mp4' } } }
      };
      const videoIdResponse = {
        response: { id: 'video123' },
        status: { isError: false }
      };

      return expectSaga(sagas.uploadFbAdAsset, file, assetType, fileParams)
        .provide([
          [matchers.call.fn(Api.uploadFile, file, assetType, fileParams), uploadResponse],
          [matchers.call.fn(Api.getFacebookVideoId, {
            videoUrl: uploadResponse.response.asset.metaInfo.secure_file_path,
            accessToken: file.videoData.accessToken,
            actId: file.videoData.actId,
            pageAccessToken: file.videoData.pageAccessToken,
            pageId: file.videoData.pageId
          }), videoIdResponse]
        ])
        .put({
          type: types.UPLOAD_FB_AD_ASSET_SUCCESS,
          data: {...uploadResponse.response.asset, videoIdResponse: videoIdResponse.response},
          statusCode: 200,
          templateType: file.templateType,
        })
        .run();
    });

    it.concurrent('handles failure in asset upload', () => {
      const error = new Error('Upload failed');

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


  // Test combined saga
  describe('Combined v2FacebookSagas', () => {
    it.concurrent('should initialize all Facebook-related watcher sagas without error', () => {
      return expectSaga(v2FacebookSagas)
        .run();
    });
  });
});



describe('editTemplate Saga', () => {
  const template = { id: 1, content: 'Updated Ad Content' };
  const callback = jest.fn(); // Mock callback function

  it('handles successful editing of a Facebook Ad template', () => {
    const fakeResponse = {
      response: { id: 1, name: 'Updated Ad' },
      status: { code: 200 }
    };

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


});