/**
 * Context Enricher - Injects relevant memory into agent prompts
 */

class ContextEnricher {
  constructor(memoryBridge) {
    this.memoryBridge = memoryBridge;
    this.cache = new Map();
    this.cacheTimeout = 300000; // 5 minutes
  }

  /**
   * Enrich agent prompt with relevant memory context
   */
  async enrichPrompt(prompt, context = {}) {
    const { project, phase, agent, type } = context;

    // Build memory sections
    const memorySections = [];

    // Add similar work if relevant
    if (context.includeSimilar !== false) {
      const similar = await this.findSimilarWork(context);
      if (similar.length > 0) {
        memorySections.push(this.formatSimilarWork(similar));
      }
    }

    // Add recent observations
    if (context.includeObservations !== false) {
      const observations = await this.getRecentObservations(context);
      if (observations.length > 0) {
        memorySections.push(this.formatObservations(observations));
      }
    }

    // Add project insights
    if (context.includeInsights !== false) {
      const insights = await this.getProjectInsights(project);
      if (insights) {
        memorySections.push(this.formatInsights(insights));
      }
    }

    // Add past decisions
    if (context.includeDecisions !== false) {
      const decisions = await this.getPastDecisions(context);
      if (decisions.length > 0) {
        memorySections.push(this.formatDecisions(decisions));
      }
    }

    // Inject memory context into prompt
    if (memorySections.length > 0) {
      const memoryContext = memorySections.join('\n\n');
      return this.injectContext(prompt, memoryContext);
    }

    return prompt;
  }

  /**
   * Find similar past work
   */
  async findSimilarWork(context) {
    const cacheKey = `similar-${context.project}-${context.phase}`;

    if (this.cache.has(cacheKey)) {
      const cached = this.cache.get(cacheKey);
      if (Date.now() - cached.timestamp < this.cacheTimeout) {
        return cached.data;
      }
    }

    const similar = await this.memoryBridge.findSimilar(
      `${context.project} ${context.phase}`,
      { limit: 5 }
    );

    this.cache.set(cacheKey, {
      data: similar.results || [],
      timestamp: Date.now()
    });

    return similar.results || [];
  }

  /**
   * Get recent observations
   */
  async getRecentObservations(context) {
    const results = await this.memoryBridge.search('', {
      project: context.project,
      type: 'observation',
      limit: context.maxObservations || 10
    });

    return results.results || [];
  }

  /**
   * Get project insights
   */
  async getProjectInsights(project) {
    if (!project) return null;

    const cacheKey = `insights-${project}`;

    if (this.cache.has(cacheKey)) {
      const cached = this.cache.get(cacheKey);
      if (Date.now() - cached.timestamp < this.cacheTimeout) {
        return cached.data;
      }
    }

    const insights = await this.memoryBridge.getProjectInsights(project);

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

    return insights;
  }

  /**
   * Get past decisions
   */
  async getPastDecisions(context) {
    const results = await this.memoryBridge.search('decision', {
      project: context.project,
      type: 'decision',
      limit: 5
    });

    return results.results || [];
  }

  /**
   * Format similar work for injection
   */
  formatSimilarWork(similar) {
    const lines = ['<memory_context type="similar_work">'];
    lines.push('## Similar Past Work\n');

    for (const item of similar) {
      lines.push(`### ${item.title || 'Previous work'}`);
      if (item.summary) {
        lines.push(item.summary);
      }
      if (item.outcome) {
        lines.push(`**Outcome:** ${item.outcome}`);
      }
      if (item.lessons) {
        lines.push(`**Lessons:** ${item.lessons}`);
      }
      lines.push('');
    }

    lines.push('</memory_context>');
    return lines.join('\n');
  }

  /**
   * Format observations for injection
   */
  formatObservations(observations) {
    const lines = ['<memory_context type="observations">'];
    lines.push('## Recent Observations\n');

    for (const obs of observations) {
      lines.push(`- **${obs.type}:** ${obs.title || obs.content?.substring(0, 100)}`);
      if (obs.facts && obs.facts.length > 0) {
        lines.push(`  Facts: ${obs.facts.slice(0, 3).join(', ')}`);
      }
    }

    lines.push('</memory_context>');
    return lines.join('\n');
  }

  /**
   * Format insights for injection
   */
  formatInsights(insights) {
    const lines = ['<memory_context type="insights">'];
    lines.push('## Project Insights\n');

    if (insights.patterns) {
      lines.push('**Common Patterns:**');
      for (const pattern of insights.patterns) {
        lines.push(`- ${pattern}`);
      }
      lines.push('');
    }

    if (insights.preferences) {
      lines.push('**User Preferences:**');
      for (const pref of insights.preferences) {
        lines.push(`- ${pref}`);
      }
      lines.push('');
    }

    if (insights.antipatterns) {
      lines.push('**Avoid:**');
      for (const anti of insights.antipatterns) {
        lines.push(`- ${anti}`);
      }
    }

    lines.push('</memory_context>');
    return lines.join('\n');
  }

  /**
   * Format decisions for injection
   */
  formatDecisions(decisions) {
    const lines = ['<memory_context type="decisions">'];
    lines.push('## Past Decisions\n');

    for (const decision of decisions) {
      lines.push(`**${decision.title || 'Decision'}**`);
      lines.push(`- Choice: ${decision.choice}`);
      lines.push(`- Rationale: ${decision.rationale}`);
      if (decision.outcome) {
        lines.push(`- Outcome: ${decision.outcome}`);
      }
      lines.push('');
    }

    lines.push('</memory_context>');
    return lines.join('\n');
  }

  /**
   * Inject context into prompt
   */
  injectContext(prompt, memoryContext) {
    // Look for injection point
    const injectionMarker = '<memory_injection_point/>';

    if (prompt.includes(injectionMarker)) {
      return prompt.replace(injectionMarker, memoryContext);
    }

    // If no marker, add after initial instructions
    const lines = prompt.split('\n');
    let injectionIndex = -1;

    // Find a good injection point
    for (let i = 0; i < Math.min(10, lines.length); i++) {
      if (lines[i].includes('</objective>') ||
          lines[i].includes('</context>') ||
          lines[i].includes('## Context')) {
        injectionIndex = i + 1;
        break;
      }
    }

    if (injectionIndex === -1) {
      // Default to adding after first paragraph
      injectionIndex = Math.min(3, lines.length);
    }

    lines.splice(injectionIndex, 0, '', memoryContext, '');
    return lines.join('\n');
  }

  /**
   * Clear context cache
   */
  clearCache() {
    this.cache.clear();
  }
}

module.exports = ContextEnricher;