/**
 * Proxy Check Operations - Checking proxy functionality
 */
import type { OperationContext } from '@stock-bot/di';
import { getLogger } from '@stock-bot/logger';
import type { ProxyInfo } from '@stock-bot/proxy';
import { fetch } from '@stock-bot/utils';
import { PROXY_CONFIG } from '../shared/config';

/**
 * Check if a proxy is working
 */
export async function checkProxy(proxy: ProxyInfo): Promise<ProxyInfo> {
  const ctx = {
    logger: getLogger('proxy-check'),
    resolve: (_name: string) => {
      throw new Error(`Service container not available for proxy operations`);
    },
  } as any;

  let success = false;
  ctx.logger.debug(`Checking Proxy:`, {
    protocol: proxy.protocol,
    host: proxy.host,
    port: proxy.port,
  });

  try {
    // Test the proxy using fetch with proxy support
    const proxyUrl =
      proxy.username && proxy.password
        ? `${proxy.protocol}://${encodeURIComponent(proxy.username)}:${encodeURIComponent(proxy.password)}@${proxy.host}:${proxy.port}`
        : `${proxy.protocol}://${proxy.host}:${proxy.port}`;

    const response = await fetch(PROXY_CONFIG.CHECK_URL, {
      proxy: proxyUrl,
      signal: AbortSignal.timeout(PROXY_CONFIG.CHECK_TIMEOUT),
      logger: ctx.logger,
    } as any);

    const data = await response.text();

    const isWorking = response.ok;
    const result: ProxyInfo = {
      ...proxy,
      isWorking,
      lastChecked: new Date(),
    };

    if (isWorking && !data.includes(PROXY_CONFIG.CHECK_IP)) {
      success = true;
      await updateProxyInCache(result, true, ctx);
    } else {
      await updateProxyInCache(result, false, ctx);
    }

    if (proxy.source) {
      updateProxyStats(proxy.source, success, ctx);
    }

    ctx.logger.debug('Proxy check completed', {
      host: proxy.host,
      port: proxy.port,
      isWorking,
    });

    return result;
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error);
    const result: ProxyInfo = {
      ...proxy,
      isWorking: false,
      error: errorMessage,
      lastChecked: new Date(),
    };

    // Update cache for failed proxy (increment total, don't update TTL)
    await updateProxyInCache(result, false, ctx);

    if (proxy.source) {
      updateProxyStats(proxy.source, success, ctx);
    }

    ctx.logger.debug('Proxy check failed', {
      host: proxy.host,
      port: proxy.port,
      error: errorMessage,
    });

    return result;
  }
}

/**
 * Update proxy data in cache with working/total stats and average response time
 */
async function updateProxyInCache(
  proxy: ProxyInfo,
  isWorking: boolean,
  ctx: OperationContext
): Promise<void> {
  // const _cacheKey = `${PROXY_CONFIG.CACHE_KEY}:${proxy.protocol}://${proxy.host}:${proxy.port}`;

  try {
    // For now, skip cache operations without service container
    // TODO: Pass service container to operations
    const existing: ProxyInfo | null = null;

    // For failed proxies, only update if they already exist
    if (!isWorking && !existing) {
      ctx.logger.debug('Proxy not in cache, skipping failed update', {
        proxy: `${proxy.host}:${proxy.port}`,
      });
      return;
    }

    // Calculate new average response time if we have a response time
    let newAverageResponseTime = existing?.averageResponseTime;
    if (proxy.responseTime !== undefined) {
      const existingAvg = existing?.averageResponseTime || 0;
      const existingTotal = existing?.total || 0;

      // Calculate weighted average: (existing_avg * existing_count + new_response) / (existing_count + 1)
      newAverageResponseTime =
        existingTotal > 0
          ? (existingAvg * existingTotal + proxy.responseTime) / (existingTotal + 1)
          : proxy.responseTime;
    }

    // Build updated proxy data
    const updated = {
      ...existing,
      ...proxy, // Keep latest proxy info
      total: (existing?.total || 0) + 1,
      working: isWorking ? (existing?.working || 0) + 1 : existing?.working || 0,
      isWorking,
      lastChecked: new Date(),
      // Add firstSeen only for new entries
      ...(existing ? {} : { firstSeen: new Date() }),
      // Update average response time if we calculated a new one
      ...(newAverageResponseTime !== undefined
        ? { averageResponseTime: newAverageResponseTime }
        : {}),
    };

    // Calculate success rate
    updated.successRate = updated.total > 0 ? (updated.working / updated.total) * 100 : 0;

    // Save to cache: reset TTL for working proxies, keep existing TTL for failed ones
    // const _cacheOptions = isWorking ? { ttl: PROXY_CONFIG.CACHE_TTL } : undefined;
    // Skip cache operations without service container
    // TODO: Pass service container to operations

    ctx.logger.debug(`Updated ${isWorking ? 'working' : 'failed'} proxy in cache`, {
      proxy: `${proxy.host}:${proxy.port}`,
      working: updated.working,
      total: updated.total,
      successRate: updated.successRate.toFixed(1) + '%',
      avgResponseTime: updated.averageResponseTime
        ? `${updated.averageResponseTime.toFixed(0)}ms`
        : 'N/A',
    });
  } catch (error) {
    ctx.logger.error('Failed to update proxy in cache', {
      proxy: `${proxy.host}:${proxy.port}`,
      error: error instanceof Error ? error.message : String(error),
    });
  }
}

function updateProxyStats(sourceId: string, success: boolean, ctx: OperationContext) {
  // Stats are now handled by the global ProxyManager
  ctx.logger.debug('Proxy check result', { sourceId, success });

  // TODO: Integrate with global ProxyManager stats if needed
}
