/**
 * Centralized Asset Status Polling Saga
 * Reusable across all channels (WhatsApp, MobilePush, Email, SMS, etc.)
 * 
 * Usage:
 * import { pollAssetStatus } from '../../sagas/assetPolling';
 * 
 * yield call(pollAssetStatus, {
 *   type: 'video',
 *   assetId: 'asset-123',
 *   onProcessing: (data) => ({ type: 'ASSET_PROCESSING', payload: data }),
 *   onCompleted: (asset) => ({ type: 'ASSET_COMPLETED', payload: asset }),
 *   onFailed: (error) => ({ type: 'ASSET_FAILED', payload: error }),
 *   onTimeout: () => ({ type: 'ASSET_TIMEOUT' })
 * });
 */

import { call, put } from 'redux-saga/effects';
import { getAssetStatus } from '../services/api';
import { ASSET_STATUS } from '../utils/assetStatusConstants';
import { VIDEO } from '../constants/unified';

/**
 * Delay utility function compatible with redux-saga 0.16.2
 * Returns a promise that resolves after the specified milliseconds
 * @param {number} ms - Milliseconds to delay
 * @returns {Promise} Promise that resolves after delay
 */
export function delay(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

/**
 * Generic asset status polling saga
 * @param {Object} config - Polling configuration
 * @param {string} config.type - Asset type (image, video, document, gif)
 * @param {string} config.assetId - Asset ID to poll
 * @param {Function} config.onCompleted - Action creator for completed state
 * @param {Function} config.onFailed - Action creator for failed state
 * @param {Function} config.onTimeout - Action creator for timeout state
 * @param {number} config.maxDuration - Max polling duration in ms (default: 90000)
 * @param {number} config.initialDelay - Initial delay before first poll in ms (default: 1000)
 * @param {number} config.pollInterval - Interval between polls in ms (default: 2000)
 */
export function* pollAssetStatus(config) {
  const {
    type,
    assetId,
    onCompleted,
    onFailed,
    onTimeout,
    maxDuration = 90000, // 90 seconds default
    initialDelay: configInitialDelay = 1000, // 1 second default
    pollInterval = 2000, // 2 seconds default
  } = config;

  const startTime = Date.now();
  let isFirstPoll = true;

  try {
    while (true) {
      // Initial delay, then regular interval
      // Using call() for compatibility with redux-saga 0.16.2
      yield call(delay, isFirstPoll ? configInitialDelay : pollInterval);
      isFirstPoll = false;

      // Check timeout
      if (Date.now() - startTime > maxDuration) {
        if (onTimeout) {
          const timeoutAction = onTimeout({
            assetId,
            message: 'Asset processing is taking longer than expected. Please check back later.',
            duration: Date.now() - startTime,
          });
          yield put(timeoutAction);
        }
        break;
      }

      // Poll status endpoint
      const statusResponse = yield call(getAssetStatus, type, assetId);
      
      // Validate API response structure
      // Check for error indicators: success: false, error property, or missing response
      if (!statusResponse || statusResponse.success === false || statusResponse.error) {
        const errorMessage = statusResponse?.error || 
                            statusResponse?.message || 
                            'Failed to fetch asset status: Invalid API response';
        
        if (onFailed) {
          const failedAction = onFailed({
            assetId,
            error: errorMessage,
            duration: Date.now() - startTime,
          });
          yield put(failedAction);
        }
        break;
      }
      
      // Extract status data from response
      const statusData = statusResponse?.response || {};
      
      // Validate that statusData has a meaningful status property
      if (!statusData || typeof statusData.status !== 'string') {
        const errorMessage = 'Invalid asset status response: Missing or invalid status field';
        
        if (onFailed) {
          const failedAction = onFailed({
            assetId,
            error: errorMessage,
            duration: Date.now() - startTime,
          });
          yield put(failedAction);
        }
        break;
      }

      if (statusData.status === ASSET_STATUS.COMPLETED) {
        // For video assets, continue polling until video_file_path_preview is available
        // Even though status is COMPLETED, video preview generation may still be in progress
        if (statusData?.asset?.type === VIDEO.toUpperCase() && 
            !statusData?.asset?.metaInfo?.video_file_path_preview) {
          continue;
        }

        if (onCompleted) {
          const completedAction = onCompleted({
            assetId,
            asset: statusData.asset,
            duration: Date.now() - startTime,
          });
          yield put(completedAction);
        }
        break;
      } else if (statusData.status === ASSET_STATUS.FAILED) {
        // Asset processing failed
        if (onFailed) {
          const failedAction = onFailed({
            assetId,
            error: statusData.error || 'Processing failed',
            duration: Date.now() - startTime,
          });
          yield put(failedAction);
        }
        break;
      }

      // Continue polling if still processing
    }
  } catch (error) {
    // Handle polling errors (network issues, etc.)
    if (onFailed) {
      const errorAction = onFailed({
        assetId,
        error: `Failed to check asset status: ${error.message}`,
      });
      yield put(errorAction);
    }
  }
}
