const cron = require('node-cron');
const axios = require('axios');
const { db } = require('../database/db');
const logger = require('../utils/logger');

const CHECK_TIMEOUT = 10000; // 10 seconds timeout
const BATCH_SIZE = 10; // Check 10 channels at a time

/**
 * Check if a channel URL is accessible
 */
async function checkChannelHealth(channelId, url) {
  try {
    const response = await axios.get(url, {
      timeout: CHECK_TIMEOUT,
      maxRedirects: 5,
      responseType: 'stream',
      headers: {
        'User-Agent': 'StreamFlow/1.0'
      }
    });

    // Close the stream immediately
    if (response.data && typeof response.data.destroy === 'function') {
      response.data.destroy();
    }

    // Consider 2xx and 3xx as healthy
    const isHealthy = response.status >= 200 && response.status < 400;
    const status = isHealthy ? 'healthy' : 'degraded';

    // Update channel health status
    db.run(
      'UPDATE channels SET health_status = ?, last_checked = CURRENT_TIMESTAMP WHERE id = ?',
      [status, channelId],
      (err) => {
        if (err) {
          logger.error(`Failed to update health status for channel ${channelId}:`, err);
        }
      }
    );

    return { channelId, status, healthy: isHealthy };
  } catch (error) {
    // Mark as dead if request fails
    const status = 'dead';
    
    db.run(
      'UPDATE channels SET health_status = ?, last_checked = CURRENT_TIMESTAMP WHERE id = ?',
      [status, channelId],
      (err) => {
        if (err) {
          logger.error(`Failed to update health status for channel ${channelId}:`, err);
        }
      }
    );

    logger.debug(`Channel ${channelId} health check failed: ${error.message}`);
    return { channelId, status, healthy: false, error: error.message };
  }
}

/**
 * Check all channels in batches
 */
async function checkAllChannels() {
  return new Promise((resolve, reject) => {
    db.all(
      'SELECT id, url FROM channels WHERE is_active = 1',
      [],
      async (err, channels) => {
        if (err) {
          logger.error('Failed to fetch channels for health check:', err);
          reject(err);
          return;
        }

        logger.info(`Starting health check for ${channels.length} channels`);
        const results = {
          total: channels.length,
          healthy: 0,
          degraded: 0,
          dead: 0
        };

        // Process channels in batches
        for (let i = 0; i < channels.length; i += BATCH_SIZE) {
          const batch = channels.slice(i, i + BATCH_SIZE);
          const promises = batch.map(channel => checkChannelHealth(channel.id, channel.url));
          
          try {
            const batchResults = await Promise.all(promises);
            batchResults.forEach(result => {
              if (result.status === 'healthy') results.healthy++;
              else if (result.status === 'degraded') results.degraded++;
              else if (result.status === 'dead') results.dead++;
            });

            // Small delay between batches to avoid overwhelming the server
            await new Promise(resolve => setTimeout(resolve, 1000));
          } catch (error) {
            logger.error('Error in batch health check:', error);
          }
        }

        logger.info('Health check completed:', results);
        resolve(results);
      }
    );
  });
}

// Check channel health every 6 hours
cron.schedule('0 */6 * * *', async () => {
  logger.info('Running scheduled channel health check');
  try {
    await checkAllChannels();
  } catch (error) {
    logger.error('Channel health check failed:', error);
  }
});

// Export for manual triggering
module.exports = {
  checkAllChannels,
  checkChannelHealth
};

