#!/usr/bin/env node
/**
 * Memory Service - NocoDB Integration
 * 
 * Uses ai_data_Memory table (mx149yctebfwvys) in Agent base (pedwxnsn51vxdq2)
 * Single table with 'type' field to distinguish record types
 */

const axios = require('axios');

class MemoryService {
  constructor(config = {}) {
    this.nocodbUrl = config.nocodbUrl || 'http://192.168.25.5:8080';
    this.nocodbToken = config.nocodbToken || process.env.NOCODB_TOKEN;
    this.baseId = config.baseId || 'pedwxnsn51vxdq2';
    this.tableId = config.tableId || 'mx149yctebfwvys'; // ai_data_Memory
  }

  /**
   * Get HTTP client with auth
   */
  getClient() {
    return axios.create({
      baseURL: `${this.nocodbUrl}/api/v2/tables/${this.tableId}`,
      headers: {
        'xc-token': this.nocodbToken,
        'Content-Type': 'application/json'
      }
    });
  }

  // ============================================
  // CORRECTIONS API
  // ============================================

  /**
   * Load all active corrections
   */
  async loadCorrections() {
    const client = this.getClient();
    const response = await client.get('/records', {
      params: {
        where: `(type,eq,correction)~and(blocking,eq,true)`,
        limit: 1000
      }
    });
    return response.data.list.map(this.parseCorrectionRecord);
  }

  /**
   * Store new correction
   */
  async storeCorrection(correction) {
    const client = this.getClient();
    
    const payload = {
      type: 'correction',
      pattern: correction.pattern,
      exclude_pattern: correction.excludePattern || null,
      severity: correction.severity,
      message: correction.message,
      suggestion: correction.suggestion,
      blocking: correction.blocking !== false,
      auto_detected: correction.autoDetected || true,
      manual_entry: correction.manualEntry || false,
      hit_count: 0,
      context: correction.context || 'unknown'
    };
    
    const response = await client.post('/records', payload);
    return this.parseCorrectionRecord(response.data);
  }

  /**
   * Increment hit count for correction
   */
  async incrementCorrectionHit(correctionId) {
    const client = this.getClient();
    
    // Get current record
    const current = await client.get(`/records/${correctionId}`);
    const newCount = (current.data.hit_count || 0) + 1;
    
    await client.patch(`/records/${correctionId}`, {
      hit_count: newCount,
      last_triggered: new Date().toISOString(),
      updated_at: new Date().toISOString()
    });
    
    return newCount;
  }

  parseCorrectionRecord(record) {
    return {
      id: record.id,
      pattern: record.pattern,
      excludePattern: record.exclude_pattern,
      severity: record.severity,
      message: record.message,
      suggestion: record.suggestion,
      blocking: record.blocking,
      autoDetected: record.auto_detected,
      manualEntry: record.manual_entry,
      hitCount: record.hit_count,
      lastTriggered: record.last_triggered,
      context: record.context,
      createdAt: record.created_at
    };
  }

  // ============================================
  // PREFERENCES API
  // ============================================

  /**
   * Get preferences by category
   */
  async getPreferences(category, minImportance = 5) {
    const client = this.getClient();
    
    const response = await client.get('/records', {
      params: {
        where: `(type,eq,preference)~and(category,eq,${category})~and(importance,gte,${minImportance})`,
        sort: '-importance,-access_count'
      }
    });
    
    return response.data.list.map(this.parsePreferenceRecord);
  }

  /**
   * Store preference
   */
  async storePreference(pref) {
    const client = this.getClient();
    
    const payload = {
      type: 'preference',
      category: pref.category,
      key: pref.key,
      value: pref.value,
      importance: pref.importance || 5,
      confidence: pref.confidence || 1.0,
      tags: JSON.stringify(pref.tags || []),
      confirmed_count: pref.confirmedCount || 0
    };
    
    const response = await client.post('/records', payload);
    return this.parsePreferenceRecord(response.data);
  }

  parsePreferenceRecord(record) {
    return {
      id: record.id,
      category: record.category,
      key: record.key,
      value: record.value,
      importance: record.importance,
      confidence: record.confidence,
      tags: JSON.parse(record.tags || '[]'),
      accessCount: record.access_count,
      lastAccessed: record.last_accessed,
      confirmedCount: record.confirmed_count,
      createdAt: record.created_at
    };
  }

  // ============================================
  // EPISODES API
  // ============================================

  /**
   * Store episodic memory
   */
  async storeEpisode(episode) {
    const client = this.getClient();
    
    const payload = {
      type: 'episode',
      date: episode.date || new Date().toISOString().split('T')[0],
      summary: episode.summary,
      details: episode.details,
      project: episode.project,
      outcomes: JSON.stringify(episode.outcomes || []),
      corrections_triggered: JSON.stringify(episode.correctionsTriggered || [])
    };
    
    const response = await client.post('/records', payload);
    return response.data;
  }

  /**
   * Get recent episodes
   */
  async getEpisodes(limit = 10) {
    const client = this.getClient();
    
    const response = await client.get('/records', {
      params: {
        where: `(type,eq,episode)`,
        sort: '-date',
        limit
      }
    });
    
    return response.data.list;
  }

  // ============================================
  // DECISIONS API
  // ============================================

  /**
   * Store decision
   */
  async storeDecision(decision) {
    const client = this.getClient();
    
    const payload = {
      type: 'decision',
      date: decision.date || new Date().toISOString().split('T')[0],
      project: decision.project,
      decision: decision.decision,
      alternatives: JSON.stringify(decision.alternatives || []),
      rationale: decision.rationale,
      status: decision.status || 'active'
    };
    
    const response = await client.post('/records', payload);
    return response.data;
  }

  /**
   * Get active decisions
   */
  async getActiveDecisions(project) {
    const client = this.getClient();
    
    const params = {
      where: `(type,eq,decision)~and(status,eq,active)`,
      sort: '-date'
    };
    
    if (project) {
      params.where += `~and(project,eq,${project})`;
    }
    
    const response = await client.get('/records', { params });
    return response.data.list;
  }

  // ============================================
  // VALIDATION LOGGING
  // ============================================

  /**
   * Log validation run
   */
  async logValidation(run) {
    const client = this.getClient();
    
    const payload = {
      type: 'validation',
      session_id: run.sessionId,
      input_length: run.inputLength,
      output_length: run.outputLength,
      violations_found: run.violationsFound || 0,
      new_patterns_detected: run.newPatternsDetected || 0,
      corrections_auto_stored: run.correctionsAutoStored || 0,
      processing_time_ms: run.processingTimeMs,
      blocked: run.blocked || false,
      workflow: run.workflow
    };
    
    const response = await client.post('/records', payload);
    return response.data;
  }

  /**
   * Get validation statistics
   */
  async getValidationStats(days = 7) {
    const client = this.getClient();
    
    const cutoff = new Date();
    cutoff.setDate(cutoff.getDate() - days);
    const cutoffStr = cutoff.toISOString();
    
    const response = await client.get('/records', {
      params: {
        where: `(type,eq,validation)~and(timestamp,gte,${cutoffStr})`,
        fields: 'blocked,violations_found,corrections_auto_stored'
      }
    });
    
    const runs = response.data.list;
    
    return {
      totalRuns: runs.length,
      blockedCount: runs.filter(r => r.blocked).length,
      totalViolations: runs.reduce((sum, r) => sum + (r.violations_found || 0), 0),
      totalAutoCorrections: runs.reduce((sum, r) => sum + (r.corrections_auto_stored || 0), 0),
      blockRate: runs.length > 0 ? (runs.filter(r => r.blocked).length / runs.length * 100).toFixed(1) : 0
    };
  }

  // ============================================
  // UTILITY
  // ============================================

  /**
   * Test connection
   */
  async testConnection() {
    const client = this.getClient();
    
    try {
      const response = await client.get('/records', {
        params: { limit: 1 }
      });
      
      return {
        success: true,
        message: 'Connected to ai_data_Memory table',
        recordCount: response.data.pageInfo?.totalRows || 0
      };
    } catch (err) {
      return {
        success: false,
        message: err.response?.data?.error || err.message
      };
    }
  }
}

// Export
module.exports = MemoryService;
