/**
 * BenchmarkService - Fetches model benchmark text for routing decisions
 *
 * Purpose:
 * - Fetch benchmark text from Azure backend
 * - Refresh benchmarks periodically
 * - Supply benchmark text to model router (as-is, no processing)
 */

import { MODEL_ROUTER_CONFIG } from '../utilities/constants.js';

class BenchmarkService {
  constructor(config, logger) {
    this.config = config;
    this.logger = logger;

    this.benchmarkText = null;
    this.lastUpdated = null;
    this.isLoading = false;
    this.endpointAvailable = true; // Set to false on 404 to stop retrying

    // Use config backend URL with default fallback
    this.azureBackendUrl = config.backend?.baseUrl || 'https://loxia-api-g7hrb8bxdae8a2h7.z02.azurefd.net';
    this.refreshInterval = MODEL_ROUTER_CONFIG.BENCHMARK_REFRESH_INTERVAL;
  }

  /**
   * Initialize benchmark service and load initial data
   */
  async initialize() {
    try {
      await this.loadBenchmarks();
      this._scheduleRefresh();
      this.logger.info('Benchmark service initialized');
    } catch (error) {
      this.logger.error('Failed to initialize benchmark service', { error: error.message });
      this.benchmarkText = null;
    }
  }

  /**
   * Get current benchmark text
   */
  getBenchmarks() {
    if (!this.benchmarkText) {
      this.logger.warn('No benchmark data available');
      return null;
    }
    return this.benchmarkText;
  }

  /**
   * Get benchmark text for router prompt (alias for consistency)
   */
  getBenchmarkTable() {
    return this.getBenchmarks();
  }

  /**
   * Load benchmarks from Azure backend
   */
  async loadBenchmarks() {
    if (this.isLoading) {
      this.logger.debug('Benchmark loading already in progress');
      return;
    }

    if (!this.endpointAvailable) {
      return;
    }

    this.isLoading = true;

    try {
      const text = await this._fetchFromAzureBackend();

      if (text) {
        this.benchmarkText = text;
        this.lastUpdated = new Date();
        this.logger.info('Benchmarks loaded from Azure backend');
      } else {
        throw new Error('No benchmark data received from backend');
      }

    } catch (error) {
      // If the endpoint doesn't exist (404), stop retrying — it won't appear later
      if (error.message.includes('404')) {
        this.endpointAvailable = false;
        this.logger.warn('Benchmark endpoint not available (404) — disabled until restart');
      } else {
        this.logger.error('Failed to fetch benchmarks from Azure backend', {
          error: error.message
        });
      }

      if (!this.benchmarkText) {
        this.benchmarkText = null;
      }

    } finally {
      this.isLoading = false;
    }
  }

  /**
   * Check if benchmarks need refresh
   */
  needsRefresh() {
    if (!this.lastUpdated) return true;

    const timeSinceUpdate = Date.now() - this.lastUpdated.getTime();
    return timeSinceUpdate > this.refreshInterval;
  }

  /**
   * Fetch benchmarks from Azure backend as plain text
   * @private
   */
  async _fetchFromAzureBackend() {
    const url = `${this.azureBackendUrl}/llm/model-benchmarks`;

    let apiKey = null;
    if (this.config.apiKey) {
      apiKey = this.config.apiKey;
    }

    // Use AbortController for timeout (Node.js fetch doesn't support timeout option)
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 10000);

    const fetchOptions = {
      method: 'GET',
      headers: {
        'Accept': 'text/plain',
        ...(apiKey && { 'Authorization': `Bearer ${apiKey}` })
      },
      signal: controller.signal
    };

    this.logger.debug('Fetching benchmarks from Azure backend', { url });

    try {
      const response = await fetch(url, fetchOptions);
      clearTimeout(timeoutId);

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const text = await response.text();
      return text;
    } catch (error) {
      clearTimeout(timeoutId);
      if (error.name === 'AbortError') {
        throw new Error('Request timeout after 10 seconds');
      }
      throw error;
    }
  }

  /**
   * Schedule periodic refresh
   * @private
   */
  _scheduleRefresh() {
    setInterval(async () => {
      if (this.needsRefresh()) {
        this.logger.debug('Refreshing benchmark data');
        await this.loadBenchmarks();
      }
    }, this.refreshInterval);
  }

  /**
   * Force refresh benchmarks
   */
  async forceRefresh() {
    this.logger.info('Force refreshing benchmark data');
    await this.loadBenchmarks();
  }

  /**
   * Get service status
   */
  getStatus() {
    return {
      initialized: !!this.benchmarkText,
      lastUpdated: this.lastUpdated?.toISOString() || null,
      isLoading: this.isLoading,
      needsRefresh: this.needsRefresh(),
      hasData: !!this.benchmarkText
    };
  }
}

export default BenchmarkService;
