/**
 * Generic Async Asset Upload Utilities
 * 
 * Provides reusable constants, reducer cases, and action creators for async asset uploads
 * across all channels (WhatsApp, MobilePush, Email, SMS, etc.)
 * 
 * Usage:
 *   import { createAsyncAssetUploadConstants, createAsyncAssetUploadReducerCases } from '../../utils/asyncAssetUpload';
 * 
 *   // In constants.js
 *   export const {
 *     UPLOAD_ASSET_PROCESSING,
 *     UPLOAD_ASSET_COMPLETED,
 *     UPLOAD_ASSET_FAILED,
 *     UPLOAD_ASSET_TIMEOUT,
 *   } = createAsyncAssetUploadConstants('WHATSAPP'); // or 'MOBILEPUSH', 'EMAIL', etc.
 * 
 *   // In reducer.js
 *   import { createAsyncAssetUploadReducerCases } from '../../utils/asyncAssetUpload';
 *   const asyncUploadCases = createAsyncAssetUploadReducerCases({
 *     PROCESSING: UPLOAD_ASSET_PROCESSING,
 *     COMPLETED: UPLOAD_ASSET_COMPLETED,
 *     FAILED: UPLOAD_ASSET_FAILED,
 *     TIMEOUT: UPLOAD_ASSET_TIMEOUT,
 *   });
 *   
 *   // In reducer switch statement
 *   case asyncUploadCases.PROCESSING:
 *     return asyncUploadCases.handleProcessing(state, action);
 *   case asyncUploadCases.COMPLETED:
 *     return asyncUploadCases.handleCompleted(state, action);
 *   // etc.
 */

import { fromJS } from 'immutable';
import { ASSET_STATUS } from './assetStatusConstants';

/**
 * Creates async asset upload constants for a given channel
 * @param {string} channelPrefix - Channel prefix (e.g., 'WHATSAPP', 'MOBILEPUSH', 'EMAIL')
 * @param {string} containerPath - Container path (e.g., 'app/v2Containers/Whatsapp')
 * @returns {Object} Object containing all async upload constants
 */
export function createAsyncAssetUploadConstants(channelPrefix, containerPath) {
  const prefix = containerPath || `app/v2Containers/${channelPrefix}`;
  const channelName = channelPrefix.toUpperCase();
  
  return {
    [`UPLOAD_${channelName}_ASSET_PROCESSING`]: `${prefix}/UPLOAD_${channelName}_ASSET_PROCESSING`,
    [`UPLOAD_${channelName}_ASSET_COMPLETED`]: `${prefix}/UPLOAD_${channelName}_ASSET_COMPLETED`,
    [`UPLOAD_${channelName}_ASSET_FAILED`]: `${prefix}/UPLOAD_${channelName}_ASSET_FAILED`,
    [`UPLOAD_${channelName}_ASSET_TIMEOUT`]: `${prefix}/UPLOAD_${channelName}_ASSET_TIMEOUT`,
  };
}

/**
 * Creates reducer case handlers for async asset uploads
 * @param {Object} actionTypes - Action type constants
 * @param {Object} options - Configuration options
 * @param {string} options.uploadedAssetDataKey - Key for uploaded asset data (default: 'uploadedAssetData')
 * @param {string} options.assetUploadingKey - Key for asset uploading flag (default: 'assetUploading')
 * @param {string} options.uploadAssetSuccessKey - Key for upload success flag (default: 'uploadAssetSuccess')
 * @param {string} options.assetProcessingKey - Key for asset processing state (default: 'assetProcessing')
 * @returns {Object} Object containing reducer case handlers
 */
export function createAsyncAssetUploadReducerCases(actionTypes, options = {}) {
  const {
    uploadedAssetDataKey = 'uploadedAssetData',
    assetUploadingKey = 'assetUploading',
    uploadAssetSuccessKey = 'uploadAssetSuccess',
    assetProcessingKey = 'assetProcessing',
  } = options;

  return {
    // Action type constants for use in switch statements
    PROCESSING: actionTypes.PROCESSING,
    COMPLETED: actionTypes.COMPLETED,
    FAILED: actionTypes.FAILED,
    TIMEOUT: actionTypes.TIMEOUT,

    // Reducer handlers
    handleProcessing: (state, action) => {
      const startTime = new Date().getTime();
      return state
        .set(uploadAssetSuccessKey, false)
        .set(assetUploadingKey, true)
        .setIn([assetProcessingKey, action.payload.assetId], fromJS({
          status: ASSET_STATUS.PROCESSING,
          startTime,
          asset: action.payload.asset,
          error: null
        }));
    },

    handleCompleted: (state, action) => {
      const templateType = action.templateType;
      const assetDataKey = templateType !== undefined
        ? `${uploadedAssetDataKey}${templateType}`
        : uploadedAssetDataKey;

      return state
        .set(uploadAssetSuccessKey, true)
        .set(assetUploadingKey, false)
        .setIn([assetProcessingKey, action.payload.assetId], fromJS({
          status: ASSET_STATUS.COMPLETED,
          asset: action.payload.asset,
          error: null
        }))
        .set(assetDataKey, fromJS(action.payload.asset));
    },

    handleFailed: (state, action) => {
      return state
        .set(uploadAssetSuccessKey, false)
        .set(assetUploadingKey, false)
        .setIn([assetProcessingKey, action.payload.assetId], fromJS({
          status: ASSET_STATUS.FAILED,
          error: action.payload.error
        }));
    },

    handleTimeout: (state, action) => {
      return state
        .set(uploadAssetSuccessKey, false)
        .set(assetUploadingKey, false)
        .setIn([assetProcessingKey, action.payload.assetId], fromJS({
          status: ASSET_STATUS.TIMEOUT,
          error: action.payload.message
        }));
    },
  };
}

/**
 * Creates polling configuration for use with centralized pollAssetStatus saga
 * @param {string} assetType - Asset type ('image', 'video', 'document', etc.)
 * @param {string} assetId - Asset ID
 * @param {Object} actionTypes - Action type constants
 * @returns {Object} Polling configuration object
 */
export function createPollingConfig(assetType, assetId, actionTypes, templateType) {
  return {
    type: assetType,
    assetId,
    onCompleted: (data) => ({
      type: actionTypes.COMPLETED,
      payload: data,
      templateType,
    }),
    onFailed: (data) => ({
      type: actionTypes.FAILED,
      payload: data,
      templateType,
    }),
    onTimeout: (data) => ({
      type: actionTypes.TIMEOUT,
      payload: data,
      templateType,
    }),
  };
}
