/**
 * Python Service Client
 * Handles communication with the Python processing service
 */
// Use native fetch (Node.js 18+) or node-fetch for older versions
let fetch;
if (typeof globalThis.fetch !== 'undefined') {
  // Node.js 18+ has native fetch
  fetch = globalThis.fetch;
} else {
  // Fallback: dynamically import node-fetch
  try {
    const nodeFetch = require('node-fetch');
    fetch = nodeFetch.default || nodeFetch;
  } catch (e) {
    // If node-fetch is not available, we'll handle it in the functions
    fetch = null;
  }
}

const PYTHON_SERVICE_URL = process.env.PYTHON_SERVICE_URL || 'http://localhost:8010';

/**
 * Call Python service for options flow processing
 * @param {Object} params - Query parameters
 * @returns {Promise<Object>} Processed options flow data
 */
export async function getOptionsFlowFromPython(params = {}) {
  if (!fetch) {
    throw new Error('Fetch is not available. Please install node-fetch or use Node.js 18+');
  }

  const {
    startDate,
    endDate,
    minPremium = 80000,
    tolPct = 0.20
  } = params;

  const queryParams = new URLSearchParams();
  if (startDate) queryParams.append('start_date', startDate);
  if (endDate) queryParams.append('end_date', endDate);
  if (minPremium) queryParams.append('min_premium', minPremium);
  if (tolPct) queryParams.append('tol_pct', tolPct);

  const url = `${PYTHON_SERVICE_URL}/api/options-flow?${queryParams.toString()}`;

  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 30000);
    
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
      signal: controller.signal
    });
    
    clearTimeout(timeoutId);

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`Python service error: ${response.status} - ${errorText}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error calling Python service:', error);
    
    // Fallback to SQL if Python service is unavailable
    if (error.name === 'AbortError' || 
        error.code === 'ECONNREFUSED' || 
        error.code === 'ETIMEDOUT' ||
        error.message.includes('fetch')) {
      console.warn('Python service unavailable, falling back to SQL');
      throw new Error('PYTHON_SERVICE_UNAVAILABLE');
    }
    
    throw error;
  }
}

/**
 * Check if Python service is healthy
 * @returns {Promise<boolean>}
 */
export async function checkPythonServiceHealth() {
  if (!fetch) {
    return false;
  }
  
  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 5000);
    
    const response = await fetch(`${PYTHON_SERVICE_URL}/health`, {
      method: 'GET',
      signal: controller.signal,
      // Add connection timeout
      headers: {
        'Connection': 'close'
      }
    });
    
    clearTimeout(timeoutId);

    if (!response.ok) {
      return false;
    }

    const data = await response.json();
    return data.status === 'healthy';
  } catch (error) {
    // Don't log here - let the middleware handle logging to avoid duplicate messages
    // Only return false to indicate unhealthy state
    return false;
  }
}

/**
 * Calculate Phase 1 metrics for a specific signal on-demand
 * @param {Object} params - Signal data (symbol, flow_ts_utc, flow_date_cst, row_data)
 * @returns {Promise<Object>} Phase 1 calculation results
 */
export async function calculatePhase1ForSignal(params = {}, retries = 2) {
  if (!fetch) {
    throw new Error('Fetch is not available. Please install node-fetch or use Node.js 18+');
  }

  const { symbol, flow_ts_utc, flow_date_cst, row_data } = params;

  if (!symbol || !flow_ts_utc) {
    throw new Error('symbol and flow_ts_utc are required');
  }

  const url = `${PYTHON_SERVICE_URL}/api/phase1/calculate`;
  const TIMEOUT_MS = 120000; // 120 seconds (2 minutes) for Phase 1 calculations

  for (let attempt = 0; attempt <= retries; attempt++) {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
      
      console.log(`📊 Phase 1 calculation attempt ${attempt + 1}/${retries + 1} for ${symbol}...`);
      
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          symbol,
          flow_ts_utc,
          flow_date_cst,
          row_data: row_data || {}
        }),
        signal: controller.signal,
        // Add keep-alive and connection settings
        keepalive: true
      });
      
      clearTimeout(timeoutId);

      if (!response.ok) {
        const errorText = await response.text();
        // Don't retry on 4xx errors (client errors)
        if (response.status >= 400 && response.status < 500) {
          throw new Error(`Python service error: ${response.status} - ${errorText}`);
        }
        // Retry on 5xx errors (server errors)
        throw new Error(`Python service error: ${response.status} - ${errorText}`);
      }

      const data = await response.json();
      console.log(`✅ Phase 1 calculation completed for ${symbol}`);
      return data;
    } catch (error) {
      const isLastAttempt = attempt === retries;
      const isRetryable = error.name === 'AbortError' || 
                         error.code === 'ECONNREFUSED' || 
                         error.code === 'ETIMEDOUT' ||
                         error.code === 'ECONNRESET' ||
                         error.message.includes('fetch') ||
                         error.message.includes('timeout') ||
                         (error.message.includes('Python service error') && error.message.includes('50'));
      
      if (isLastAttempt || !isRetryable) {
        console.error(`❌ Phase 1 calculation failed for ${symbol} after ${attempt + 1} attempts:`, error.message);
        
        if (error.name === 'AbortError') {
          throw new Error('PYTHON_SERVICE_TIMEOUT');
        }
        
        if (isRetryable) {
          throw new Error('PYTHON_SERVICE_UNAVAILABLE');
        }
        
        throw error;
      }
      
      // Exponential backoff: wait 2^attempt seconds before retrying
      const backoffMs = Math.min(1000 * Math.pow(2, attempt), 10000); // Max 10 seconds
      console.log(`⏳ Retrying Phase 1 calculation for ${symbol} in ${backoffMs}ms...`);
      await new Promise(resolve => setTimeout(resolve, backoffMs));
    }
  }
}

/**
 * Get flow statistics from Python service
 * @param {string} symbol - Optional symbol filter
 * @returns {Promise<Object>}
 */
export async function getFlowStatsFromPython(symbol = null) {
  if (!fetch) {
    throw new Error('Fetch is not available');
  }
  
  const queryParams = new URLSearchParams();
  if (symbol) queryParams.append('symbol', symbol);

  const url = `${PYTHON_SERVICE_URL}/api/options-flow/stats?${queryParams.toString()}`;

  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 10000);
    
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
      signal: controller.signal
    });
    
    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`Python service error: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Error getting flow stats from Python service:', error);
    throw error;
  }
}

