/**
 * META-AWARE COMPONENT
 *
 * STRUCTURAL PATTERN: Adapter (Interface Translation)
 * ABSTRACTION LEVEL: Medium
 * COMPLEXITY: 4/10
 *
 * PURPOSE: Translates between incompatible API interfaces with pattern awareness
 * WHY THIS PATTERN: Adapter pattern enables integration of third-party code without
 *                    modification, maintaining separation of concerns and flexibility
 *
 * QUALITY SELF-ASSESSMENT:
 * - Structural Clarity: 8/10 (clear adapter interface, explicit translation)
 * - Meta-Awareness: 7/10 (tracks translations, identifies patterns)
 * - Evolution Potential: 9/10 (can extend to multiple backends, add caching)
 * - Pattern Generalizability: 9/10 (adapter pattern broadly applicable)
 * - Self-Documentation Quality: 8/10 (clear pattern explanation)
 *
 * IMPROVEMENT SUGGESTIONS:
 * 1. Add automatic schema detection to reduce manual mapping configuration
 * 2. Implement caching layer to avoid redundant API translations
 * 3. Add bidirectional translation support (not just request, but response too)
 *
 * EVOLUTION PATH:
 * - Next step: Add response transformation to complete bidirectional adapter
 * - Long-term: Auto-generate adapters from API schema definitions (OpenAPI, GraphQL)
 */

// === IMPLEMENTATION ===

/**
 * Generic API Adapter
 * Pattern: Adapter translates between Target API and Legacy API
 */
class MetaAwareAPIAdapter {
  constructor(legacyAPI, fieldMapping = {}) {
    // The legacy API we're adapting
    this._legacyAPI = legacyAPI;

    // Field mapping: modernFieldName -> legacyFieldName
    this._fieldMapping = fieldMapping;

    // Meta-tracking
    this._metrics = {
      translationCount: 0,
      fieldTranslations: {},
      unmappedFields: new Set(),
      adapterCalls: []
    };
  }

  /**
   * Modern API interface (what clients expect)
   * Pattern: Target interface
   */
  async fetchUser(userId) {
    this._metrics.translationCount++;
    const callStart = Date.now();

    console.log(`[META] Adapting fetchUser(${userId}) to legacy API`);

    // Call legacy API (different method name, different return format)
    const legacyData = await this._legacyAPI.getUserById(userId);

    // Translate response from legacy format to modern format
    const modernData = this._translateToModern(legacyData);

    // Track metrics
    const duration = Date.now() - callStart;
    this._metrics.adapterCalls.push({
      method: 'fetchUser',
      userId,
      duration,
      fieldsTranslated: Object.keys(this._fieldMapping).length
    });

    console.log(`[META] Translation completed in ${duration}ms`);

    return modernData;
  }

  /**
   * Translate legacy data structure to modern structure
   * Pattern: Data transformation
   */
  _translateToModern(legacyData) {
    const modernData = {};

    // Apply field mappings
    for (const [modernField, legacyField] of Object.entries(this._fieldMapping)) {
      if (legacyField in legacyData) {
        modernData[modernField] = legacyData[legacyField];

        // Track successful translation
        this._metrics.fieldTranslations[modernField] =
          (this._metrics.fieldTranslations[modernField] || 0) + 1;
      } else {
        // Track missing field
        this._metrics.unmappedFields.add(legacyField);
        console.warn(`[META] Legacy field "${legacyField}" not found in response`);
      }
    }

    // Copy unmapped fields directly (pass-through)
    for (const [key, value] of Object.entries(legacyData)) {
      if (!Object.values(this._fieldMapping).includes(key)) {
        modernData[key] = value;
      }
    }

    return modernData;
  }

  /**
   * Add new field mapping at runtime
   * Pattern: Dynamic configuration
   */
  addMapping(modernField, legacyField) {
    this._fieldMapping[modernField] = legacyField;
    console.log(`[META] Added mapping: ${modernField} -> ${legacyField}`);
  }

  /**
   * Get adapter metrics
   * Pattern: Introspection
   */
  getMetrics() {
    return {
      ...this._metrics,
      unmappedFields: Array.from(this._metrics.unmappedFields),
      pattern: 'Adapter (Interface Translation)',
      totalMappings: Object.keys(this._fieldMapping).length
    };
  }
}

// === STRUCTURAL REFLECTION ===
// Pattern Used: Adapter (wraps incompatible interface)
// Why: Enables integration of legacy systems without modifying them.
//      Maintains single responsibility: adapter handles translation,
//      client code works with modern interface, legacy code unchanged.
// Trade-offs:
//   - Additional abstraction layer adds slight overhead
//   - Manual mapping configuration required (though could be automated)
//   - One-way translation only (request adaptation, not response)
//   - Need to maintain mapping as APIs evolve

// === META-ANALYSIS ===
// What worked well:
//   - Clear separation of concerns (translation logic isolated)
//   - Runtime configuration via addMapping() allows flexibility
//   - Meta-tracking identifies unmapped fields automatically
//   - Pass-through of unmapped fields prevents data loss
// What could improve:
//   - Add automatic schema detection from API responses
//   - Implement bidirectional translation (modern -> legacy requests too)
//   - Add caching to avoid repeated translation of same data
//   - Support nested object translations (currently flat only)
// Generalizability:
//   - This adapter pattern applies to: API versioning, database migrations,
//     third-party integrations, protocol translation, data format conversion,
//     cross-platform compatibility layers

// === USAGE EXAMPLE ===

// Mock legacy API (old interface)
class LegacyUserAPI {
  async getUserById(id) {
    // Legacy API returns different field names
    return {
      user_id: id,
      user_name: 'John Doe',
      email_addr: 'john@example.com',
      creation_date: '2020-01-01'
    };
  }
}

// Create adapter with field mappings
const legacyAPI = new LegacyUserAPI();
const adapter = new MetaAwareAPIAdapter(legacyAPI, {
  id: 'user_id',
  name: 'user_name',
  email: 'email_addr',
  createdAt: 'creation_date'
});

// Client code uses modern interface
(async () => {
  const user = await adapter.fetchUser(123);
  console.log('Modern format:', user);
  // Output: { id: 123, name: 'John Doe', email: 'john@...', createdAt: '...' }

  console.log('Adapter metrics:', adapter.getMetrics());
})();

module.exports = MetaAwareAPIAdapter;
