/**
 * Customer Search Section Sagas
 */

import {
  call, put, takeLatest, all,
} from 'redux-saga/effects';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import * as Api from '../../services/api';
import {
  SEARCH_CUSTOMERS_REQUESTED,
  SEARCH_CUSTOMERS_SUCCESS,
  SEARCH_CUSTOMERS_FAILURE,
  EXTRACT_TAGS_REQUEST,
  EXTRACT_TAGS_SUCCESS,
  EXTRACT_TAGS_FAILURE,
  UPDATE_PREVIEW_REQUEST,
  UPDATE_PREVIEW_SUCCESS,
  UPDATE_PREVIEW_FAILURE,
  SEND_TEST_MESSAGE_REQUESTED,
  SEND_TEST_MESSAGE_SUCCESS,
  SEND_TEST_MESSAGE_FAILURE,
  FETCH_TEST_CUSTOMERS_REQUESTED,
  FETCH_TEST_GROUPS_REQUESTED,
  FETCH_TEST_CUSTOMERS_SUCCESS,
  FETCH_TEST_CUSTOMERS_FAILURE,
  FETCH_TEST_GROUPS_SUCCESS,
  FETCH_TEST_GROUPS_FAILURE,
  CREATE_MESSAGE_META_REQUESTED,
  CREATE_MESSAGE_META_SUCCESS,
  CREATE_MESSAGE_META_FAILURE,
  GET_PREFILLED_VALUES_REQUESTED,
  GET_PREFILLED_VALUES_SUCCESS,
  GET_PREFILLED_VALUES_FAILURE,
} from './constants';

// Search Customers Saga
export function* searchCustomersSaga(action) {
  try {
    const { query } = action.payload;
    const response = yield call(Api.searchCustomers, { query });

    if (response.isError) {
      yield put({ type: SEARCH_CUSTOMERS_FAILURE, payload: { error: response.message || 'Failed to search customers' } });
    } else {
      const customers = response?.result?.data || [];
      yield put({ type: SEARCH_CUSTOMERS_SUCCESS, payload: { customers } });
    }
  } catch (error) {
    yield put({ type: SEARCH_CUSTOMERS_FAILURE, payload: { error: error.message || 'Network error occurred' } });
  }
}

// Extract Tags Saga
export function* extractTagsSaga(action) {
  try {
    const { templateSubject, templateContent } = action.payload;

    const payload = {
      messageTitle: templateSubject || '',
      messageBody: templateContent || '',
    };

    const response = yield call(Api.extractTagsWithMetaData, payload);
    if (response?.data?.length > 0) {
      yield put({ type: EXTRACT_TAGS_SUCCESS, payload: { extractedtags: response.data } });
    } else {
      yield put({ type: EXTRACT_TAGS_FAILURE, payload: { error: response.error || 'Failed to extract tags' } });
    }
  } catch (error) {
    yield put({ type: EXTRACT_TAGS_FAILURE, payload: { error: error.message || 'Network error occurred' } });
  }
}

// Update Preview Saga
export function* updatePreviewSaga(action) {
  try {
    // Store custom values before making the API call
    const customValues = action.payload.resolvedTags;

    const response = yield call(Api.updateEmailPreview, action.payload);
    if (response?.data) {
      yield put({
        type: UPDATE_PREVIEW_SUCCESS,
        payload: {
          previewData: response.data,
          customValues, // Pass custom values to be preserved
        },
      });
    } else {
      yield put({
        type: UPDATE_PREVIEW_FAILURE,
        payload: {
          error: response.error || 'Failed to update preview',
          customValues, // Pass custom values even on failure
        },
      });
    }
  } catch (error) {
    yield put({
      type: UPDATE_PREVIEW_FAILURE,
      payload: {
        error: error.message || 'Network error occurred',
        customValues: action.payload.resolvedTags, // Pass custom values on error
      },
    });
  }
}

// Send Test Email Saga
export function* sendTestMessageSaga(action) {
  try {
    const { callback } = action;
    const response = yield call(Api.sendTestMessage, action.payload);

    if (!response.errors) {
      yield put({ type: SEND_TEST_MESSAGE_SUCCESS, payload: { response: true } });
      callback(true);
    } else {
      yield put({ type: SEND_TEST_MESSAGE_FAILURE, payload: { response: false, error: response.errors || 'Failed to send test email' } });
      callback(false);
    }
  } catch (error) {
    yield put({ type: SEND_TEST_MESSAGE_FAILURE, payload: { response: false, error: error.message || 'Network error occurred' } });
    action.callback(false);
  }
}

export function* getBulkCustomerDetails({fetchedUserIds}) {
  try {
    const bulkCustomerDetails = yield call(Api.getBulkCustomerDetails, {
      userIds: fetchedUserIds,
    });
    const transformedData = get(bulkCustomerDetails, 'result.data').map(
      (item) => {
        const profile = get(item, 'entity.profiles[0]', {});
        if (isEmpty(profile)) {
          throw item?.errors?.[0]?.message;
        }
        const mobileIdentifier = profile?.identifiers?.find(
          (identifier) => identifier.type === 'mobile',
        );
        const emailIdentifier = profile?.identifiers?.find(
          (identifier) => identifier.type === 'email',
        );
        return {
          userId: item?.entity?.id,
          name: `${profile?.firstName} ${profile?.lastName}`,
          mobile: mobileIdentifier?.value,
          email: emailIdentifier?.value,
        };
      },
    );
    yield put({
      type: FETCH_TEST_CUSTOMERS_SUCCESS,
      payload: { customers: transformedData },
    });
  } catch (error) {
    yield put({
      type: FETCH_TEST_CUSTOMERS_FAILURE,
      payload: { error },
    });
  }
}

export function* fetchTestCustomersSaga() {
  try {
    const response = yield call(Api.fetchTestCustomers);
    if (response.entity) {
      const fetchedUserIds = get(response, 'entity.userIds');
      if (Array.isArray(fetchedUserIds) && fetchedUserIds.length > 0) {
        yield call(getBulkCustomerDetails, { fetchedUserIds });
      } else {
        yield put({
          type: FETCH_TEST_CUSTOMERS_FAILURE,
          payload: { error: "No test customers found" },
        });
      }
    } else {
      yield put({ type: FETCH_TEST_CUSTOMERS_FAILURE, payload: { error: response.error || 'Failed to fetch test customers' } });
    }
  } catch (error) {
    yield put({ type: FETCH_TEST_CUSTOMERS_FAILURE, payload: { error: error.message } });
  }
}

export function* fetchTestGroupsSaga() {
  try {
    const response = yield call(Api.fetchTestGroups);
    if (response?.entity) {
      yield put({ type: FETCH_TEST_GROUPS_SUCCESS, payload: { groups: response?.entity?.userGroups } });
    } else {
      yield put({ type: FETCH_TEST_GROUPS_FAILURE, payload: { error: response.error || 'Failed to fetch test groups' } });
    }
  } catch (error) {
    yield put({ type: FETCH_TEST_GROUPS_FAILURE, payload: { error: error.message } });
  }
}

export function* createMessageMetaSaga(action) {
  try {
    const { payload, messageMetaConfigId, callback } = action;
    let response;
    if (messageMetaConfigId) {
      response = yield call(Api.updateTestMessageMeta, { data: payload, messageMetaConfigId });
    } else {
      response = yield call(Api.createTestMessageMeta, payload);
    }
    if (!response.errors) {
      yield put({ type: CREATE_MESSAGE_META_SUCCESS, payload: { response } });
      callback(response);
    } else {
      yield put({ type: CREATE_MESSAGE_META_FAILURE, payload: { error: response.errors || 'Failed to create message meta' } });
    }
  } catch (error) {
    yield put({ type: CREATE_MESSAGE_META_FAILURE, payload: { error } });
  }
}

export function* getPrefilledValuesSaga(action) {
  try {
    const response = yield call(Api.updateEmailPreview, action.payload);
    if (response?.data) {
      yield put({ type: GET_PREFILLED_VALUES_SUCCESS, payload: { values: response?.data?.resolvedTagValues } });
    } else {
      yield put({ type: GET_PREFILLED_VALUES_FAILURE, payload: { error: response.error || 'Failed to fetch prefilled values' } });
    }
  } catch (error) {
    yield put({ type: GET_PREFILLED_VALUES_FAILURE, payload: { error } });
  }
}

// Watcher Sagas
export function* watchSearchCustomers() {
  yield takeLatest(SEARCH_CUSTOMERS_REQUESTED, searchCustomersSaga);
}

export function* watchExtractTags() {
  yield takeLatest(EXTRACT_TAGS_REQUEST, extractTagsSaga);
}

export function* watchUpdatePreview() {
  yield takeLatest(UPDATE_PREVIEW_REQUEST, updatePreviewSaga);
}

export function* watchSendTestMessage() {
  yield takeLatest(SEND_TEST_MESSAGE_REQUESTED, sendTestMessageSaga);
}

export function* watchFetchTestCustomers() {
  yield takeLatest(FETCH_TEST_CUSTOMERS_REQUESTED, fetchTestCustomersSaga);
}

export function* watchFetchTestGroups() {
  yield takeLatest(FETCH_TEST_GROUPS_REQUESTED, fetchTestGroupsSaga);
}

export function* watchCreateMessageMeta() {
  yield takeLatest(CREATE_MESSAGE_META_REQUESTED, createMessageMetaSaga);
}

export function* watchGetPrefilledValues() {
  yield takeLatest(GET_PREFILLED_VALUES_REQUESTED, getPrefilledValuesSaga);
}

// Root saga
export function* previewAndTestSaga() {
  yield all([
    watchSearchCustomers(),
    watchExtractTags(),
    watchUpdatePreview(),
    watchSendTestMessage(),
    watchFetchTestCustomers(),
    watchFetchTestGroups(),
    watchCreateMessageMeta(),
    watchGetPrefilledValues(),
  ]);
}
