import {
  call, put, takeLatest, all,
} from 'redux-saga/effects';
import get from 'lodash/get';
import { CapNotification } from '@capillarytech/cap-ui-library';
// import { schema, normalize } from 'normalizr';
import * as Api from '../../services/api';
import * as types from './constants';
import { saveCdnConfigs, removeAllCdnLocalStorageItems, initCdnConfigFromEnv } from '../../utils/cdnTransformation';
import { COPY_OF } from '../../constants/unified';
import { ZALO_TEMPLATE_INFO_REQUEST } from '../Zalo/constants';
import { getTemplateInfoById } from '../Zalo/saga';

// Individual exports for testing
export function* getAllTemplates(channel, queryParams) {
  try {
    const result = yield call(Api.getAllTemplates, channel, queryParams);
    const channelTemplates = (channel.channel === 'wechat') ? { templates: [...result.response.mapped, ...result.response.richmedia] } : result.response;
    // const sidebar = result.response.sidebar;
    if (channel.channel === 'wechat' && channel.queryParams && channel.queryParams.sortBy && channel.queryParams.sortBy.toLocaleLowerCase() === ("Most Recent").toLocaleLowerCase()) {
      channelTemplates.templates.sort((a, b) => {
        const dateA = new Date(a.updatedAt);
        const dateB = new Date(b.updatedAt);
        return dateB - dateA;
      });
    } else if (channel.channel === 'wechat' && channel.queryParams && channel.queryParams.sortBy && channel.queryParams.sortBy.toLocaleLowerCase() === ("Alphabetically").toLocaleLowerCase()) {
      channelTemplates.templates.sort((a, b) => b.name - a.name);
    }
    // Update the "name" property in each template
    if (channel.intlCopyOf && channelTemplates?.templates) {
      channelTemplates.templates = channelTemplates.templates.map((template) => ({
        ...template,
        name: template.name.replace(new RegExp(COPY_OF, 'g'), channel.intlCopyOf),
      }));
    }
    yield put({ type: types.GET_ALL_TEMPLATES_SUCCESS, data: channelTemplates, weCRMTemplate: result.response.unMapped, isReset: channel.queryParams.page === 1 });
  } catch (error) {
    yield put({ type: types.GET_ALL_TEMPLATES_FAILURE, error });
  }
}

export function* deleteTemplate(channel, id) {
  try {
    const result = yield call(Api.deleteTemplate, channel, id);
    // const sidebar = result.response.sidebar;
    yield put({ type: types.DELETE_TEMPLATE_SUCCESS, data: result.response });
  } catch (error) {
    yield put({ type: types.DELETE_TEMPLATE_FAILURE, error });
  }
}

export function* deleteRcsTemplate({templateName}) {
  try {
    const result = yield call(Api.deleteRcsTemplate, {templateName});
    
    if (result && result.success === false) {
      yield put({ type: types.DELETE_RCS_TEMPLATE_FAILURE, error: result.message || result });
      return;
    }
    yield put({ type: types.DELETE_RCS_TEMPLATE_SUCCESS, data: result?.response });
  } catch (error) {
    yield put({ type: types.DELETE_RCS_TEMPLATE_FAILURE, error: error?.message || error });
  }
}

export function* fetchUserList() {
  try {
    const result = yield call(Api.getUserList);
    yield put({
      type: types.GET_USER_LIST_SUCCESS,
      data: result.data.result,
    });
  } catch (error) {
    yield put({
      type: types.GET_USER_LIST_FAILURE,
      data: error,
    });
  }
}

export function* fetchWeCrmAccounts(action) {
  try {
    const result = yield call(Api.fetchWeCrmAccounts, action.source);
    yield put({
      type: types.GET_WECRM_ACCOUNTS_SUCCESS,
      data: result.response,
    });
  } catch (error) {
    yield put({
      type: types.GET_WECRM_ACCOUNTS_FAILURE,
      data: error,
    });
  }
}

export function* getOrgLevelCampaignSettings() {
  try {
    const result = yield call(Api.getOrgLevelCampaignSettings);
    yield put({
      type: types.GET_ORG_LEVEL_CAMPAIGN_SETTINGS_SUCCESS,
      result,
    });
  } catch (error) {
    yield put({ type: types.GET_ORG_LEVEL_CAMPAIGN_SETTINGS_FAILURE, error });
  }
}

export function* getCdnTransformationConfig() {
  try {
    // VAPT CAP-183204: prefer env vars injected via window.APP_ENV — avoids the
    // API response that leaked CDN/S3 infrastructure details. Fallback to API
    // keeps clusters that haven't received the env vars yet working during rollout.
    if (initCdnConfigFromEnv()) return;

    const res = yield call(Api.getCdnTransformationConfig);
    if (res?.success && res?.status?.code === 200) {
      const cdnConfigs = res?.response;
      saveCdnConfigs(cdnConfigs);
    } else {
      removeAllCdnLocalStorageItems();
    }
  } catch (error) {

    removeAllCdnLocalStorageItems();
  }
}

export function* watchGetOrgLevelCampaignSettings() {
  yield takeLatest(
    types.GET_ORG_LEVEL_CAMPAIGN_SETTINGS_REQUEST,
    getOrgLevelCampaignSettings,
  );
}

export function* sendZippedFile({ selectedFile, errorHandler, successHandler }) {
  let errorMessage = "";
  try {
    const result = yield call(Api.sendZippedFile, selectedFile);
    if (result.status.isError) {
      errorMessage = result.message;
      yield errorHandler(errorMessage);
      return;
    }

    const htmlContent = decodeURIComponent(result.response.metaEntity.htmlContent);
    
    yield put({
      type: types.SEND_ZIPPED_FILE_SUCCESS,
      selectedTemplate: htmlContent,
    });
    yield successHandler();
  } catch (error) {
    yield errorHandler();
    yield put({
      type: types.SEND_ZIPPED_FILE_FAILURE,
      data: errorMessage,
    });
  }
}

export function* getDefaultBeeTemplates() {
  try {
    const result = yield call(Api.getDefaultBeeTemplates);
    const edmTemplates = result.response;
    yield put({ type: types.GET_DEAFULT_BEE_TEMPLATES_SUCCESS, data: edmTemplates });
  } catch (error) {
    yield put({ type: types.GET_DEAFULT_BEE_TEMPLATES_FAILURE, error });
  }
}

export function* getTemplateDetails(id, channel) {
  try {
    const result = yield call(Api.getTemplateDetails, id, channel);
    // const sidebar = result.response.sidebar;
    yield put({ type: types.GET_TEMPLATE_DETAILS_SUCCESS, data: result.response });
  } catch (error) {
    yield put({ type: types.GET_TEMPLATE_DETAILS_FAILURE, error });
  }
}

export function* getSenderDetails({
  channel,
  orgUnitId,
} = {}) {
  try {
    const apiResponse = yield call(Api.getSenderDetails, channel, orgUnitId);
    if (!apiResponse?.errors?.length) {
      yield put({
        type: types.GET_SENDER_DETAILS_SUCCESS,
        payload: ['WHATSAPP', 'ZALO', 'RCS'].includes(channel) ?
        { channel,
          domainProperties: get(apiResponse, `entity.${channel}`, '')
        } :
        get(apiResponse, `entity.${channel}[0].domainProperties.hostName`, ''),
      });
      
    } else {
      yield put({
        type: types.GET_SENDER_DETAILS_FAILURE,
        payload: apiResponse.errors,
      });
    }
  } catch (error) {
    yield put({
      type: types.GET_SENDER_DETAILS_FAILURE,
      payload: [],
    });
  }
}

export function* archiveTemplateSaga({ channel, id, successMessage, description }) {
  try {
    yield call(Api.archiveTemplate, { channel, id });
    yield put({ type: types.ARCHIVE_TEMPLATE_SUCCESS, id, successMessage, description });
  } catch (error) {
    yield put({ type: types.ARCHIVE_TEMPLATE_FAILURE, error });
    CapNotification.error({ message: error.message || 'Failed to archive template' });
  }
}

export function* unarchiveTemplateSaga({ channel, id, successMessage, description }) {
  try {
    yield call(Api.unarchiveTemplate, { channel, id });
    yield put({ type: types.UNARCHIVE_TEMPLATE_SUCCESS, id, successMessage, description });
  } catch (error) {
    yield put({ type: types.UNARCHIVE_TEMPLATE_FAILURE, error });
    CapNotification.error({ message: error.message || 'Failed to unarchive template' });
  }
}

export function* bulkArchiveTemplatesSaga({ channel, ids, successMessage }) {
  try {
    const result = yield call(Api.bulkArchiveTemplates, { channel, ids });
    const count = get(result, 'response.modifiedCount', ids.length);
    yield put({ type: types.BULK_ARCHIVE_SUCCESS, successMessage, count });
  } catch (error) {
    yield put({ type: types.BULK_ARCHIVE_FAILURE, error });
    CapNotification.error({ message: error.message || 'Failed to archive templates' });
  }
}

export function* bulkUnarchiveTemplatesSaga({ channel, ids, successMessage }) {
  try {
    const result = yield call(Api.bulkUnarchiveTemplates, { channel, ids });
    const count = get(result, 'response.modifiedCount', ids.length);
    yield put({ type: types.BULK_UNARCHIVE_SUCCESS, successMessage, count });
  } catch (error) {
    yield put({ type: types.BULK_UNARCHIVE_FAILURE, error });
    CapNotification.error({ message: error.message || 'Failed to unarchive templates' });
  }
}

export function* watchArchiveTemplate() {
  yield takeLatest(types.ARCHIVE_TEMPLATE_REQUEST, archiveTemplateSaga);
}

export function* watchUnarchiveTemplate() {
  yield takeLatest(types.UNARCHIVE_TEMPLATE_REQUEST, unarchiveTemplateSaga);
}

export function* watchBulkArchive() {
  yield takeLatest(types.BULK_ARCHIVE_REQUEST, bulkArchiveTemplatesSaga);
}

export function* watchBulkUnarchive() {
  yield takeLatest(types.BULK_UNARCHIVE_REQUEST, bulkUnarchiveTemplatesSaga);
}

export function* watchGetAllTemplates() {
  yield takeLatest(types.GET_ALL_TEMPLATES_REQUEST, getAllTemplates);
}

export function* watchDeleteTemplate() {
  yield takeLatest(types.DELETE_TEMPLATE_REQUEST, deleteTemplate);
}

export function* watchDeleteRcsTemplate() {
  yield takeLatest(types.DELETE_RCS_TEMPLATE_REQUEST, deleteRcsTemplate);
}

export function* watchGetUserList() {
  yield takeLatest(types.GET_USER_LIST_REQUEST, fetchUserList);
}

export function* watchFetchWeCrmAccounts() {
  yield takeLatest(types.GET_WECRM_ACCOUNTS_REQUEST, fetchWeCrmAccounts);
}

export function* watchSendingFile() {
  yield takeLatest(types.SEND_ZIPPED_FILE_REQUEST, sendZippedFile);
}

export function* watchGetDefaultBeeTemplates() {
  yield takeLatest(types.GET_DEAFULT_BEE_TEMPLATES_REQUEST, getDefaultBeeTemplates);
}

export function* watchGetTemplateDetails() {
  yield takeLatest(types.GET_TEMPLATE_DETAILS_REQUEST, getTemplateDetails);
}

export function* watchGetSenderDetails() {
  yield takeLatest(types.GET_SENDER_DETAILS_REQUEST, getSenderDetails);
}

export function* watchGetCdnTransformationConfig() {
  yield takeLatest(
    types.GET_CDN_TRANSFORMATION_CONFIG_REQUEST,
    getCdnTransformationConfig
  );
}

// Zalo template info watcher - only for preview if previewUrl is empty from Templates component
export function* watchForGetTemplateInfoById() {
  yield takeLatest(ZALO_TEMPLATE_INFO_REQUEST, function* handleZaloTemplateInfoRequest(action) {
    // Honour only preview requests (Other functionality already handled by Zalo component saga)
    if (action?.payload?.preview) {
      yield call(getTemplateInfoById, action);
    }
  });
}


// All sagas to be loaded
export default [
  watchGetAllTemplates,
  watchDeleteTemplate,
  watchDeleteRcsTemplate,
  watchGetUserList,
  watchFetchWeCrmAccounts,
  watchSendingFile,
  watchGetDefaultBeeTemplates,
  watchGetTemplateDetails,
  watchGetOrgLevelCampaignSettings,
  watchGetSenderDetails,
  watchGetCdnTransformationConfig,
  watchForGetTemplateInfoById, // Zalo preview functionality from Templates component
];

export function* v2TemplateSaga() {
  yield all([
    watchGetAllTemplates(),
    watchDeleteTemplate(),
    watchDeleteRcsTemplate(),
    watchGetUserList(),
    watchGetTemplateDetails(),
    watchGetOrgLevelCampaignSettings(),
    watchGetCdnTransformationConfig(),
    watchFetchWeCrmAccounts(),
    watchGetSenderDetails(),
    watchForGetTemplateInfoById(), // Zalo preview functionality from Templates component
    watchArchiveTemplate(),
    watchUnarchiveTemplate(),
    watchBulkArchive(),
    watchBulkUnarchive(),
  ]);
}

export function* v2TemplateSagaWatchGetDefaultBeeTemplates() {
  yield all([
    watchSendingFile(),
    watchGetDefaultBeeTemplates(),
  ]);
}
