/**
 * Memory Bridge - Integration layer between Ignite and Claude-Mem
 * Provides unified interface for memory operations across Ignite workflows
 */

const fetch = require('node-fetch');
const fs = require('fs').promises;
const path = require('path');

class MemoryBridge {
  constructor(config = {}) {
    this.config = {
      workerHost: config.workerHost || 'localhost',
      workerPort: config.workerPort || 37777,
      dataDir: config.dataDir || path.join(process.env.HOME, '.ignite', 'memory'),
      model: config.model || 'claude-3-5-haiku-latest',
      ...config
    };

    this.baseUrl = `http://${this.config.workerHost}:${this.config.workerPort}`;
    this.sessionCache = new Map();
  }

  /**
   * Initialize memory system for Ignite
   */
  async initialize() {
    try {
      // Ensure data directory exists
      await fs.mkdir(this.config.dataDir, { recursive: true });

      // Check if worker is running
      const health = await this.checkHealth();
      if (!health.ok) {
        console.log('Starting memory worker service...');
        await this.startWorker();
      }

      return { success: true };
    } catch (error) {
      console.error('Failed to initialize memory system:', error);
      return { success: false, error: error.message };
    }
  }

  /**
   * Check worker health
   */
  async checkHealth() {
    try {
      const response = await fetch(`${this.baseUrl}/health`);
      return { ok: response.ok, status: response.status };
    } catch (error) {
      return { ok: false, error: error.message };
    }
  }

  /**
   * Start worker service
   */
  async startWorker() {
    const { spawn } = require('child_process');
    const workerPath = path.join(__dirname, '..', 'worker', 'service.js');

    const worker = spawn('node', [workerPath], {
      detached: true,
      stdio: 'ignore',
      env: {
        ...process.env,
        IGNITE_MEMORY_PORT: this.config.workerPort,
        IGNITE_MEMORY_DATA_DIR: this.config.dataDir
      }
    });

    worker.unref();

    // Wait for worker to be ready
    await this.waitForWorker();
  }

  /**
   * Wait for worker to be ready
   */
  async waitForWorker(maxAttempts = 30) {
    for (let i = 0; i < maxAttempts; i++) {
      const health = await this.checkHealth();
      if (health.ok) return true;
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
    throw new Error('Worker failed to start');
  }

  /**
   * Create or get session for current Ignite workflow
   */
  async getSession(context = {}) {
    const sessionKey = context.sessionId || `${context.project}-${context.phase}-${Date.now()}`;

    if (this.sessionCache.has(sessionKey)) {
      return this.sessionCache.get(sessionKey);
    }

    try {
      const response = await fetch(`${this.baseUrl}/api/session/init`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          session_id: sessionKey,
          project: context.project || 'default',
          phase: context.phase,
          agent: context.agent,
          command: context.command,
          user_prompt: context.userPrompt
        })
      });

      const session = await response.json();
      this.sessionCache.set(sessionKey, session);
      return session;
    } catch (error) {
      console.error('Failed to create session:', error);
      return null;
    }
  }

  /**
   * Search memory with query
   */
  async search(query, options = {}) {
    try {
      const params = new URLSearchParams({
        q: query,
        type: options.type || '',
        project: options.project || '',
        limit: options.limit || 20
      });

      const response = await fetch(`${this.baseUrl}/api/search?${params}`);
      return await response.json();
    } catch (error) {
      console.error('Memory search failed:', error);
      return { results: [], error: error.message };
    }
  }

  /**
   * Find similar phases/work
   */
  async findSimilar(reference, options = {}) {
    try {
      const response = await fetch(`${this.baseUrl}/api/similar`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          reference,
          project: options.project,
          limit: options.limit || 10
        })
      });

      return await response.json();
    } catch (error) {
      console.error('Similar search failed:', error);
      return { results: [], error: error.message };
    }
  }

  /**
   * Store observation from agent execution
   */
  async storeObservation(observation) {
    try {
      const response = await fetch(`${this.baseUrl}/api/observation`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          session_id: observation.sessionId,
          type: observation.type || 'discovery',
          title: observation.title,
          content: observation.content,
          metadata: {
            project: observation.project,
            phase: observation.phase,
            agent: observation.agent,
            files_read: observation.filesRead || [],
            files_modified: observation.filesModified || [],
            concepts: observation.concepts || [],
            facts: observation.facts || []
          }
        })
      });

      return await response.json();
    } catch (error) {
      console.error('Failed to store observation:', error);
      return { success: false, error: error.message };
    }
  }

  /**
   * Get context for current work
   */
  async getContext(options = {}) {
    try {
      const params = new URLSearchParams({
        project: options.project || '',
        phase: options.phase || '',
        max_summaries: options.maxSummaries || 3,
        max_observations: options.maxObservations || 20
      });

      const response = await fetch(`${this.baseUrl}/api/context/inject?${params}`);
      return await response.json();
    } catch (error) {
      console.error('Failed to get context:', error);
      return { context: '', error: error.message };
    }
  }

  /**
   * Generate summary for session/phase
   */
  async generateSummary(sessionId, content) {
    try {
      const response = await fetch(`${this.baseUrl}/api/summary`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          session_id: sessionId,
          content
        })
      });

      return await response.json();
    } catch (error) {
      console.error('Failed to generate summary:', error);
      return { success: false, error: error.message };
    }
  }

  /**
   * Get project insights and patterns
   */
  async getProjectInsights(project) {
    try {
      const response = await fetch(`${this.baseUrl}/api/projects/${project}/insights`);
      return await response.json();
    } catch (error) {
      console.error('Failed to get project insights:', error);
      return { insights: {}, error: error.message };
    }
  }

  /**
   * Close session
   */
  async closeSession(sessionId) {
    try {
      const response = await fetch(`${this.baseUrl}/api/session/${sessionId}/close`, {
        method: 'POST'
      });

      this.sessionCache.delete(sessionId);
      return await response.json();
    } catch (error) {
      console.error('Failed to close session:', error);
      return { success: false, error: error.message };
    }
  }
}

// Singleton instance
let memoryBridge = null;

/**
 * Get or create memory bridge instance
 */
function getMemoryBridge(config) {
  if (!memoryBridge) {
    memoryBridge = new MemoryBridge(config);
  }
  return memoryBridge;
}

module.exports = {
  MemoryBridge,
  getMemoryBridge
};