sagas/bonus.js

/* eslint-disable sonarjs/cognitive-complexity */
/* eslint-disable sonarjs/no-duplicate-string */
import { takeLatest, put, call, select } from 'redux-saga/effects';
import { requestGet, requestPost } from '../utils/request';
import { API_URLS, MODALS, SUCCESS_MODALS } from '../constants';
import { parsePointsSettings, parseBonusSettings, revertBonusSettings } from '../utils/common';
import { getFilterData } from '../selectors/common';
import {
  getFreeBets,
  getClientBonuses,
  getClientRanks,
  getLastId,
  getLastDate,
  getFreeBetsCampaigns,
} from '../selectors/bonus';
import {
  aGetBonusSettings,
  aGetBonusSettingsSuccess,
  aGetClientBonusesSuccess,
  aGetClientRanksSuccess,
  aGetFreeBetsCampaignsSuccess,
  aGetFreeBetsSuccess,
  aGetPointSettings,
  aGetPointSettingsSuccess,
  aGetRankSettingsSuccess,
  aRequestCampaignDetailsSuccess,
  aRequestCampaignReportSuccess,
  aSavePointSettings,
  aUpdateCampaignListSuccess,
} from '../reducers/bonus';
import {
  aModalErrorMessageFromApi,
  aSetHasRecord,
  aSetIsFetched,
  aSetLastRecord,
  aSetOpenModal,
} from '../reducers/common';
import {
  aAddFreeBets,
  aCreateFreeBetsCampaign,
  aDeleteFreeBets,
  aGetClientBonuses,
  aGetClientRanks,
  aGetFreeBets,
  aGetFreeBetsCampaigns,
  aGetRankSettings,
  aSaveBonusSettings,
  aSaveRankSettings,
  aShopFBCampaignDetails,
  aShopFBCampaignReport,
  aShopFBDeleteCampaign,
  aShopFBEditCampaign,
  aShopFBEditUserList,
  aShopFBToggleAssignation,
  aShopFBToggleUsage,
  aShopFBUpdateEndTime,
} from '../reducers/actions';

/**
 * @namespace sagas/bonus
 */
/**
 * @memberof sagas/bonus
 * @typedef ClientBonus
 * @type {object}
 * @property {number} amount
 * @property {number} bonusId
 * @property {number} clientId
 * @property {string} completionDate
 * @property {string} expirationDate
 * @property {number} id
 * @property {string} lastUpdateDate
 * @property {number} paid
 * @property {string} paidDate
 * @property {number} points
 * @property {string} startDate
 * @property {number} status
 * @property {number} targetPoints
 */
/**
 * @memberof sagas/bonus
 * @typedef "getClientBonuses/response.data"
 * @type {object}
 * @property {Array<ClientBonus>} clientBonuses
 * @property {number} totalPage
 */
/**
 * Get client bonuses list
 *
 * @memberof sagas/bonus
 * @async
 * @param {object} action Filtering data
 */
function* getClientBonusesSaga(action) {
  let response;
  try {
    if (action.payload) {
      const lastUserBonusId = yield select(getLastId);
      const lastStartDate = yield select(getLastDate);
      const filters = {
        ...action.payload,
        lastUserBonusId,
        lastStartDate,
      };
      const params = `?${new URLSearchParams(filters).toString()}`;
      yield put(aSetIsFetched({ isFetched: false }));
      response = yield call(requestGet, API_URLS.CLIENT_BONUS + params, true);
      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        const clientBonuses = yield select(getClientBonuses);
        yield put(
          aGetClientBonusesSuccess({
            clientBonuses: [...clientBonuses, ...response.data.clientBonuses],
            lastUserBonusId: response.data.lastUserBonusId,
            lastStartDate: response.data.lastStartDate,
          })
        );
        if (!response.data.lastUserBonusId) {
          yield put(aSetLastRecord(true));
        }
        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data.clientBonuses.length > 0,
          },
        });
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * @memberof sagas/bonus
 * @typedef ClientRank
 * @type {object}
 * @property {number} clientId
 * @property {string} lastUpdateDate
 * @property {number} rankId
 * @property {number} turnover
 */
/**
 * @memberof sagas/bonus
 * @typedef "getClientRanks/response.data"
 * @type {object}
 * @property {Array<ClientRank>} clientRanks
 * @property {number} totalPage
 */
/**
 * Get client ranks list
 *
 * @memberof sagas/bonus
 * @async
 * @param {object} action Filtering data
 */
function* getClientRanksSaga(action) {
  let response;
  try {
    if (action.payload) {
      const lastUserId = yield select(getLastId);
      const lastUpdateDate = yield select(getLastDate);
      const filters = {
        ...action.payload,
        lastUserId,
        lastUpdateDate,
      };
      const params = `?${new URLSearchParams(filters).toString()}`;

      yield put(aSetIsFetched({ isFetched: false }));
      response = yield call(requestGet, API_URLS.CLIENT_RANKS + params, true);
      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        const clientRanks = yield select(getClientRanks);
        yield put(
          aGetClientRanksSuccess({
            clientRanks: [...clientRanks, ...response.data.clientRanks],
            lastUserId: response.data.lastUserId,
            lastUpdateDate: response.data.lastUpdateDate,
          })
        );
        if (!response.data.lastUserId) {
          yield put(aSetLastRecord(true));
        }
        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data.clientRanks.length > 0,
          },
        });
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * @memberof sagas/bonus
 * @typedef BonusSettings
 * @type {object}
 * @property {number} amount
 * @property {number} id
 * @property {string} name
 * @property {number} targetPoints
 * @property {string} timeAlowed
 */
/**
 * @memberof sagas/bonus
 * @typedef "getBonusSettings/response.data"
 * @type {object}
 * @property {Array<BonusSettings>} settings
 */
/**
 * Get bonus settings list
 *
 * @memberof sagas/bonus
 * @async
 */
function* getBonusSettings() {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestGet, API_URLS.BONUS_SETTINGS, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      yield put(
        aGetBonusSettingsSuccess({
          bonusSettings: parseBonusSettings(response.data.settings),
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * @memberof sagas/bonus
 * @typedef RankSettings
 * @type {object}
 * @property {number} id
 * @property {string} name
 * @property {number} turnover
 */
/**
 * @memberof sagas/bonus
 * @typedef "getRankSettings/response.data"
 * @type {object}
 * @property {Array<RankSettings>} rankSettings
 */
/**
 * Get rank settings list
 *
 * @memberof sagas/bonus
 * @async
 */
function* getRankSettings() {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestGet, API_URLS.RANK_SETTINGS, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      yield put(
        aGetRankSettingsSuccess({
          rankSettings: response.data.rankSettings,
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * @memberof sagas/bonus
 * @typedef Rank
 * @type {object}
 * @property {number} rankID
 * @property {string} rankLabel
 */
/**
 * @memberof sagas/bonus
 * @typedef "getPointSettings/response.data"
 * @type {object}
 * @property {object} pointsCombination Keys are rows and value is data for one row per column
 * @property {Array<Rank>} ranks
 */
/**
 * Get point settings list
 *
 * @memberof sagas/bonus
 * @async
 */
function* getPointSettings() {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestGet, API_URLS.POINT_SETTINGS, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      yield put(
        aGetPointSettingsSuccess({
          pointSettings: parsePointsSettings(response.data.pointsCombination),
          ranks: response.data.ranks,
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Edit bonus settings
 *
 * @memberof sagas/bonus
 * @async
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {Array<BonusSettings>} action.payload.bonusSettings
 */
function* saveBonusSettings(action) {
  let response;
  try {
    const body = {
      bonusSettings: revertBonusSettings(action.payload.bonusSettings),
    };
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestPost, API_URLS.BONUS_SETTINGS, body, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      yield put(
        aGetBonusSettingsSuccess({
          bonusSettings: action.payload.bonusSettings,
        })
      );
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.SAVE_BONUS_SETTTINGS,
            additionalMessage: 'successfully',
            modal: SUCCESS_MODALS.SAVE_BONUS_SETTTINGS,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Edit rank settings
 *
 * @memberof sagas/bonus
 * @async
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {Array<RankSettings>} action.payload.rankSettings
 */
function* saveRankSettings(action) {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestPost, API_URLS.SAVE_RANK_SETTINGS, action.payload, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      yield put(
        aGetRankSettingsSuccess({
          rankSettings: action.payload.rankSettings,
        })
      );
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.SAVE_RANK_SETTTINGS,
            additionalMessage: 'successfully',
            modal: SUCCESS_MODALS.SAVE_RANK_SETTTINGS,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Edit Point settings
 *
 * @memberof sagas/bonus
 * @async
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {Array} action.payload.pointSettings
 */
function* savePointSettings(action) {
  let response;
  const body = {
    pointsCombination: action.payload.pointSettings,
  };
  try {
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestPost, API_URLS.SAVE_POINT_SETTINGS, body, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const newPointSettings = [];
      const keys = Object.keys(action.payload.pointSettings);
      keys.forEach((key, i) => {
        const tempObj = action.payload.pointSettings[key];
        Object.keys(tempObj).map((objectKey) => {
          tempObj[objectKey] *= 100;
        });
        // eslint-disable-next-line no-param-reassign
        tempObj.selectionIndex = i + 1;
        newPointSettings.push(tempObj);
      });
      yield put(
        aGetPointSettingsSuccess({
          pointSettings: newPointSettings,
        })
      );
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.SAVE_POINT_SETTTINGS,
            additionalMessage: 'successfully',
            modal: SUCCESS_MODALS.SAVE_POINT_SETTTINGS,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * @memberof sagas/bonus
 * @typedef FreeBets
 * @type {object}
 * @property {number} id
 * @property {number} clientId
 * @property {number} stake
 * @property {string} assignmentDate
 * @property {string} expirationDate
 * @property {string} status
 * @property {string} usedDate
 * @property {string} assignedUser
 * @property {number} couponId
 */
/**
 * @memberof sagas/bonus
 * @typedef "getFreeBets/response.data"
 * @type {object}
 * @property {Array<FreeBets>} freeBets
 * @property {number} totalPage
 */
/**
 * @memberof sagas/bonus
 * @async
 * @param {object} action Filtering data
 */
function* getFreeBetsSaga(action) {
  let response;
  try {
    if (action.payload) {
      const lastFreeBetId = yield select(getLastId);
      const lastAssignmentDate = yield select(getLastDate);
      const filters = {
        ...action.payload,
        lastFreeBetId,
        lastAssignmentDate,
      };

      const params = `?${new URLSearchParams(filters).toString()}`;

      yield put(aSetIsFetched({ isFetched: false }));
      response = yield call(requestGet, API_URLS.FREE_BETS + params, true);
      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        const freeBets = yield select(getFreeBets);
        yield put(
          aGetFreeBetsSuccess({
            freeBets: [...freeBets, ...response.data.freeBets],
            lastFreeBetId: response.data.lastFreeBetId,
            lastAssignmentDate: response.data.lastAssignmentDate,
          })
        );
        if (!response.data.lastFreeBetId) {
          yield put(aSetLastRecord(true));
        }
        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data.freeBets.length > 0,
          },
        });
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Add Free Bets
 *
 * @memberof sagas/bonus
 * @async
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {Array<FreeBets>} action.payload.freeBets
 */
function* addFreeBet(action) {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestPost, API_URLS.ADD_FREE_BETS, action.payload, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const filters = yield select(getFilterData);
      yield put(
        aGetFreeBetsSuccess({
          freeBets: null,
          lastFreeBetId: null,
          startAssignmentDate: null,
        })
      );
      yield put(aGetFreeBets(filters));
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.ADD_FREE_BET,
            additionalMessage: 'successfully',
            modal: SUCCESS_MODALS.ADD_FREE_BET,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Delete Free Bet
 *
 * @memberof sagas/bonus
 * @async
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {Array<FreeBets>} action.payload.freeBets
 */
function* deleteFreeBets(action) {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));
    response = yield call(requestPost, `${API_URLS.DELETE_FREE_BETS}/${action.payload.userId}/cancel`, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const filters = yield select(getFilterData);
      yield put(
        aGetFreeBetsSuccess({
          freeBets: null,
          lastFreeBetId: null,
          startAssignmentDate: null,
        })
      );
      yield put(aGetFreeBets(filters));
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.CANCEL_FREE_BET,
            additionalMessage: 'successfully',
            modal: SUCCESS_MODALS.CANCEL_FREE_BET,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Get freeBets campaigns list
 *
 * @param {object} action
 */
function* getFreeBetsCampaignsSaga(action) {
  let response;
  try {
    if (action.payload) {
      const filters = {};
      if (action.payload?.['filter.startStartDate']) filters.startStartDate = action.payload?.['filter.startStartDate'];
      if (action.payload?.['filter.endStartDate']) filters.endStartDate = action.payload?.['filter.endStartDate'];
      if (action.payload?.['filter.startEndDate']) filters.startEndDate = action.payload?.['filter.startEndDate'];
      if (action.payload?.['filter.endEndDate']) filters.endEndDate = action.payload?.['filter.endEndDate'];
      if (action.payload?.['filter.campaignId']) filters.id = action.payload?.['filter.campaignId'];
      if (action.payload?.['filter.campaignName']) filters.name = action.payload?.['filter.campaignName'];
      if (action.payload?.['filter.status']) filters.status = action.payload?.['filter.status'];

      const params = `?${new URLSearchParams(filters).toString()}`;

      yield put(aSetIsFetched({ isFetched: false }));
      response = yield call(requestGet, API_URLS.GET_FREE_BETS_CAMPAIGNS + params, true);

      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data?.campaigns?.length > 0,
          },
        });

        yield put(
          aGetFreeBetsCampaignsSuccess({
            freeBetsCampaigns: [...response.data.campaigns],
          })
        );
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Create freeBets campaign
 *
 * @async
 * @param {object} action
 */
function* createFreeBetsCampaignSaga(action) {
  let response;
  try {
    const body = {
      ...action.payload,
    };
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(requestPost, API_URLS.CREATE_FREEBET_CAMPAIGN, body, true);

    if (response.status === -1) {
      throw new Error(response.error.message);
    } else {
      const filters = yield select(getFilterData);
      yield put(aGetFreeBetsCampaigns(filters));
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.CREATE_FREEBET_CAMPAIGN_SUCCESS,
            modal: SUCCESS_MODALS.CREATE_FREEBET_CAMPAIGN_SUCCESS,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aModalErrorMessageFromApi({
        message: error.message,
      })
    );
  }
}

/**
 * Toggle Assignation for freebets campaign
 *
 * @async
 * @param {object} action
 */
function* toggleAssinationSaga(action) {
  let response;
  try {
    const body = {
      state: !action.payload?.state,
    };
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(
      requestPost,
      `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_ASSIGNATION_TOGGLE}/${action.payload?.id}`,
      body,
      true
    );

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const campaignList = [...(yield select(getFreeBetsCampaigns))];
      const index = campaignList.findIndex((campaign) => campaign?.id === action.payload?.id);
      const updatedCampaign = { ...campaignList[index] };
      updatedCampaign.assignationSuspended = !updatedCampaign.assignationSuspended;
      campaignList[index] = updatedCampaign;

      yield put(aUpdateCampaignListSuccess(campaignList));

      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.ASSIGNATION_TOGGLE_SUCCESS,
            additionalMessage: `${updatedCampaign?.name} has been ${
              updatedCampaign?.assignationSuspended ? 'suspended' : 're-enabled'
            }`,
            modal: SUCCESS_MODALS.ASSIGNATION_TOGGLE_SUCCESS,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Toggle Usage for freebets campaign
 *
 * @async
 * @param {object} action
 */
function* toggleUsageSaga(action) {
  let response;
  try {
    const body = {
      state: !action.payload?.state,
    };
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(
      requestPost,
      `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_USAGE_TOGGLE}/${action.payload?.id}`,
      body,
      true
    );

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const campaignList = [...(yield select(getFreeBetsCampaigns))];
      const index = campaignList.findIndex((campaign) => campaign?.id === action.payload?.id);
      const updatedCampaign = { ...campaignList[index] };
      updatedCampaign.usageSuspended = !updatedCampaign.usageSuspended;
      campaignList[index] = updatedCampaign;

      yield put(aUpdateCampaignListSuccess(campaignList));

      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.USAGE_TOGGLE_SUCCESS,
            additionalMessage: `${updatedCampaign?.name} has been ${
              updatedCampaign?.usageSuspended ? 'suspended' : 're-enabled'
            }`,
            modal: SUCCESS_MODALS.USAGE_TOGGLE_SUCCESS,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Shop freebets delete specific campaign
 *
 * @async
 * @param {object} action
 */
function* deleteCampaignSaga(action) {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(
      requestPost,
      `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_UPCOMING_DELETE}/${action.payload?.id}`,
      {},
      true
    );

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      let campaignList = yield select(getFreeBetsCampaigns);
      const deletedCampaign = campaignList.find((campaign) => campaign?.id === action.payload?.id);
      campaignList = campaignList.filter((campaign) => campaign?.id !== action.payload?.id);

      yield put(aUpdateCampaignListSuccess(campaignList));

      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: '',
            additionalMessage: `The campaign ${deletedCampaign?.name} has been deleted`,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Request campaign details
 *
 * @async
 * @param {object} action
 */
function* campaignDetailsRequestSaga(action) {
  let response;
  try {
    const body = {
      id: action.payload?.id,
    };

    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(requestPost, `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_RETRIEVE_DETAILS}`, body, true);

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      yield put(
        aRequestCampaignDetailsSuccess({
          campaignDetails: response.data,
        })
      );

      if (action.payload?.showDetailsModal) {
        yield put(
          aSetOpenModal({
            modal: MODALS.SHOP_FB_CAMPAIGN_DETAILS,
          })
        );
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Request campaign report
 *
 * @async
 * @param {object} action
 */
function* campaignReportRequestSaga(action) {
  let response;
  try {
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(requestGet, `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_REPORTS}/${action.payload}/reports`, true);

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      yield put(
        aRequestCampaignReportSuccess({
          campaignReport: response.data,
        })
      );

      yield put(
        aSetOpenModal({
          modal: MODALS.SHOP_FB_CAMPAIGN_REPORT,
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Update endTime for campaign
 *
 * @async
 * @param {object} action
 */
function* updateEndTimeSaga(action) {
  let response;
  try {
    const body = {
      ...action.payload,
    };
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(requestPost, `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_ACTIVE_EDIT_END_DATE}`, body, true);

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const campaignList = [...(yield select(getFreeBetsCampaigns))];
      const index = campaignList.findIndex((campaign) => campaign?.id === action.payload?.id);
      const updatedCampaign = { ...campaignList[index] };
      updatedCampaign.endDate = action.payload.endDate;
      campaignList[index] = updatedCampaign;

      yield put(aUpdateCampaignListSuccess(campaignList));

      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: '',
            additionalMessage: `The End Date for campaign ${updatedCampaign?.name} has been updated successfully`,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Update userList for shop freebets campaign
 *
 * @async
 * @param {object} action
 */
function* editUserListSaga(action) {
  let response;
  try {
    const body = {
      ...action.payload,
    };
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(requestPost, `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_ACTIVE_EDIT_USERS}`, body, true);

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const campaignList = yield select(getFreeBetsCampaigns);
      const campaign = campaignList?.find((camp) => camp?.id === action.payload?.id);

      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: '',
            additionalMessage: `The Userlist for campaign ${campaign?.name} has been updated successfully`,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Edit freeBets campaign
 *
 * @async
 * @param {object} action
 */
function* editCampaignSaga(action) {
  let response;
  try {
    const body = {
      ...action.payload?.data,
    };
    yield put(aSetIsFetched({ isFetched: false }));

    response = yield call(
      requestPost,
      `${API_URLS.SHOP_FREE_BET_CAMPAIGNS_UPCOMING_EDIT}/${action.payload.id}`,
      body,
      true
    );

    if (response.status === -1) {
      throw new Error(response.error.message);
    } else {
      const campaignList = [...(yield select(getFreeBetsCampaigns))];
      const index = campaignList.findIndex((campaign) => campaign?.id === action.payload?.id);
      const updatedCampaign = { ...campaignList[index] };
      updatedCampaign.endDate = action.payload?.data?.endDate;
      updatedCampaign.startDate = action.payload?.data?.startDate;
      updatedCampaign.enabledUsers = action.payload?.data?.rules?.enabledUsers;
      updatedCampaign.name = action.payload?.data?.name;
      campaignList[index] = updatedCampaign;

      yield put(aUpdateCampaignListSuccess(campaignList));

      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.EDIT_FREEBET_CAMPAIGN_SUCCESS,
            modal: SUCCESS_MODALS.EDIT_FREEBET_CAMPAIGN_SUCCESS,
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aModalErrorMessageFromApi({
        message: error.message,
      })
    );
  }
}

/**
 * @memberof sagas/bonus
 * @async
 */
export default function* bonusSaga() {
  yield takeLatest(aGetClientBonuses, getClientBonusesSaga);
  yield takeLatest(aGetClientRanks, getClientRanksSaga);
  yield takeLatest(aGetBonusSettings, getBonusSettings);
  yield takeLatest(aGetRankSettings, getRankSettings);
  yield takeLatest(aGetPointSettings, getPointSettings);
  yield takeLatest(aSaveBonusSettings, saveBonusSettings);
  yield takeLatest(aSaveRankSettings, saveRankSettings);
  yield takeLatest(aSavePointSettings, savePointSettings);
  yield takeLatest(aGetFreeBets, getFreeBetsSaga);
  yield takeLatest(aAddFreeBets, addFreeBet);
  yield takeLatest(aDeleteFreeBets, deleteFreeBets);

  yield takeLatest(aCreateFreeBetsCampaign, createFreeBetsCampaignSaga);
  yield takeLatest(aGetFreeBetsCampaigns, getFreeBetsCampaignsSaga);
  yield takeLatest(aShopFBToggleAssignation, toggleAssinationSaga);
  yield takeLatest(aShopFBToggleUsage, toggleUsageSaga);
  yield takeLatest(aShopFBDeleteCampaign, deleteCampaignSaga);
  yield takeLatest(aShopFBCampaignDetails, campaignDetailsRequestSaga);
  yield takeLatest(aShopFBCampaignReport, campaignReportRequestSaga);
  yield takeLatest(aShopFBUpdateEndTime, updateEndTimeSaga);
  yield takeLatest(aShopFBEditUserList, editUserListSaga);
  yield takeLatest(aShopFBEditCampaign, editCampaignSaga);
}