import ConfigService from '../services/ConfigService.js';

/**
 * Fetches component definitions from Figma API.
 * Handles rate limiting, caching, and token decryption.
 */
export class FigmaScanner {
  constructor() {
    this.cache = new Map(); // Simple in-memory cache
    this.CACHE_TTL = 5 * 60 * 1000; // 5 minutes
    this.lastRequestTime = 0;
    this.MIN_REQUEST_INTERVAL = 500; // 2 requests per second = 500ms gap
  }

  /**
   * Scans a Figma file for components.
   * @param {Object} config - Project configuration containing figma details
   * @returns {Promise<Array<{name: string, figmaId: string, description: string}>>}
   */
  async scan(config) {
    const fileUrl = config['figma.file_url'];

    // Encrypted token retrieval
    let apiToken;
    try {
      const encryptedToken = config['figma.api_token'];
      apiToken = encryptedToken ? ConfigService._decrypt(encryptedToken) : null;
    } catch (e) {
      console.error('[FigmaScanner] Failed to decrypt token:', e.message);
      return [];
    }

    if (!fileUrl || !apiToken) {
      console.log('[FigmaScanner] Figma not configured, skipping scan');
      return []; // Skip if not configured
    }

    const fileKey = this._extractFileKey(fileUrl);
    if (!fileKey) {
      console.error('[FigmaScanner] Invalid Figma URL format');
      return [];
    }

    // Check cache
    const cacheKey = `figma_${fileKey}`;
    const cached = this.cache.get(cacheKey);
    if (cached && (Date.now() - cached.timestamp < this.CACHE_TTL)) {
      console.log('[FigmaScanner] Using cached Figma data');
      return cached.data;
    }

    try {
      const components = await this._fetchWithBackoff(fileKey, apiToken);

      const results = components.map(c => ({
        name: c.name,
        figmaId: c.key, // Figma API uses 'key' as the stable ID across versions
        description: c.description || ''
      }));

      // Update cache
      this.cache.set(cacheKey, { timestamp: Date.now(), data: results });

      return results;
    } catch (error) {
      console.error('[FigmaScanner] API Error:', error.message);
      return [];
    }
  }

  _extractFileKey(url) {
    const match = url.match(/figma\.com\/file\/([a-zA-Z0-9]+)/);
    return match ? match[1] : null;
  }

  async _fetchWithBackoff(fileKey, token, retries = 3) {
    const url = `https://api.figma.com/v1/files/${fileKey}/components`;

    for (let i = 0; i <= retries; i++) {
      try {
        await this._enforceRateLimit();

        const response = await fetch(url, {
          headers: { 'X-Figma-Token': token }
        });

        if (response.status === 429) {
          const waitTime = Math.pow(2, i) * 1000;
          console.warn(`[FigmaScanner] Rate limited. Waiting ${waitTime}ms`);
          await new Promise(resolve => setTimeout(resolve, waitTime));
          continue;
        }

        if (!response.ok) {
          throw new Error(`Figma API Error ${response.status}`);
        }

        const data = await response.json();
        return data.meta?.components || [];

      } catch (e) {
        if (i === retries) throw e;
      }
    }

    return [];
  }

  async _enforceRateLimit() {
    const now = Date.now();
    const timeSinceLast = now - this.lastRequestTime;

    if (timeSinceLast < this.MIN_REQUEST_INTERVAL) {
      await new Promise(resolve => setTimeout(resolve, this.MIN_REQUEST_INTERVAL - timeSinceLast));
    }
    this.lastRequestTime = Date.now();
  }
}
