/**
 * Enhanced Terminal Service
 * Integrates modular tool system with intent analysis for agentic chat
 *
 * This service provides:
 * - Modular tool system with registry
 * - Enhanced intent analysis
 * - Automatic error handling and output formatting
 * - Execution history and statistics
 * - Security checks and validation
 */

const { ToolRegistry } = require('./tool-base.cjs');
const { ShellTool, StreamingShellTool } = require('./shell-tool.cjs');
const { FileOperationTool } = require('./file-tool.cjs');
const { IntentAnalyzer } = require('./intent-analyzer.cjs');

class EnhancedTerminalService {
  constructor(config = {}) {
    this.config = {
      defaultTimeout: config.defaultTimeout || 30000,
      maxOutputSize: config.maxOutputSize || 100000,
      enableSecurity: config.enableSecurity !== false,
      enableHistory: config.enableHistory !== false,
      enableTelemetry: config.enableTelemetry !== false,
      ...config
    };

    // Initialize tool registry
    this.registry = new ToolRegistry();

    // Initialize intent analyzer
    this.analyzer = new IntentAnalyzer({
      tools: [],
      history: []
    });

    // Initialize stats
    this.stats = {
      totalCommands: 0,
      successfulCommands: 0,
      failedCommands: 0,
      commandByType: {},
      avgResponseTime: 0
    };

    // Setup default tools
    this.setupDefaultTools();

    // Setup middleware
    this.setupMiddleware();
  }

  /**
   * Register default tools
   */
  setupDefaultTools() {
    // Shell command tool
    this.registry.register(new ShellTool({
      defaultTimeout: this.config.defaultTimeout,
      maxOutputSize: this.config.maxOutputSize
    }));

    // Streaming shell for long commands
    this.registry.register(new StreamingShellTool({
      defaultTimeout: this.config.defaultTimeout
    }));

    // File operations tool
    this.registry.register(new FileOperationTool({
      maxFileSize: this.config.maxFileSize,
      allowedPaths: this.config.allowedPaths
    }));

    // Update analyzer with available tools
    this.analyzer.setTools(this.registry.list());
  }

  /**
   * Setup execution middleware
   */
  setupMiddleware() {
    // Logging middleware
    this.registry.use({
      before: async (toolName, params) => {
        console.log(`[EnhancedTerminal] Executing: ${toolName}`, {
          params: JSON.stringify(params).substring(0, 100)
        });
      },
      after: async (toolName, params, result) => {
        if (result.success) {
          console.log(`[EnhancedTerminal] Success: ${toolName}`);
        } else {
          console.error(`[EnhancedTerminal] Failed: ${toolName}`, result.error?.message);
        }
      }
    });

    // Telemetry middleware
    if (this.config.enableTelemetry) {
      this.registry.use({
        after: async (toolName, params, result) => {
          this.recordTelemetry(toolName, result);
        }
      });
    }
  }

  /**
   * Execute a command with automatic intent analysis
   *
   * @param {string} input - User input or command
   * @param {Object} options - Execution options
   * @returns {Promise<Object>} Execution result
   */
  async execute(input, options = {}) {
    const startTime = Date.now();

    try {
      // Analyze intent
      const intent = this.analyzer.analyze(input);

      // Check if intent is valid (has sufficient confidence and a tool)
      const isValid = intent.confidence > 0.3 && intent.tool;
      if (!isValid) {
        return {
          success: false,
          output: 'Could not determine command intent',
          intent: intent,
          error: 'Invalid intent'
        };
      }

      // Execute with detected tool
      const result = await this.registry.execute(intent.tool, intent.parameters);

      // Learn from execution
      this.analyzer.learn(input, result);

      // Update stats
      this.updateStats(intent.intent, result, Date.now() - startTime);

      // Format output
      return {
        success: result.success,
        output: result.output,
        data: result.data,
        intent: intent,
        duration: Date.now() - startTime,
        metadata: result.metadata
      };
    } catch (error) {
      return {
        success: false,
        output: error.message,
        error: error.message,
        duration: Date.now() - startTime
      };
    }
  }

  /**
   * Execute a specific tool directly
   *
   * @param {string} toolName - Name of tool to execute
   * @param {Object} parameters - Tool parameters
   * @returns {Promise<Object>} Execution result
   */
  async executeTool(toolName, parameters = {}) {
    const startTime = Date.now();

    try {
      const result = await this.registry.execute(toolName, parameters);

      return {
        success: result.success,
        output: result.output,
        data: result.data,
        duration: Date.now() - startTime,
        metadata: result.metadata
      };
    } catch (error) {
      return {
        success: false,
        output: error.message,
        error: error.message,
        duration: Date.now() - startTime
      };
    }
  }

  /**
   * Execute a shell command directly
   *
   * @param {string} command - Shell command to execute
   * @param {Object} options - Execution options
   * @returns {Promise<Object>} Execution result
   */
  async executeShell(command, options = {}) {
    return this.executeTool('shell', {
      command,
      cwd: options.cwd,
      timeout: options.timeout,
      env: options.env
    });
  }

  /**
   * Get command suggestions based on history
   *
   * @param {string} input - Partial input
   * @returns {Array<string>} Suggestions
   */
  getSuggestions(input = '') {
    return this.analyzer.getSuggestions(input);
  }

  /**
   * Get execution history
   *
   * @param {Object} options - Query options
   * @returns {Array} History records
   */
  getHistory(options = {}) {
    return this.registry.getHistory(options);
  }

  /**
   * Get service statistics
   *
   * @returns {Object} Statistics
   */
  getStats() {
    return {
      ...this.stats,
      registry: this.registry.getStats(),
      tools: this.registry.listMetadata()
    };
  }

  /**
   * Get available tools
   *
   * @returns {Array} Tool metadata
   */
  getAvailableTools() {
    return this.registry.listMetadata();
  }

  /**
   * Add a custom tool
   *
   * @param {BaseTool} tool - Tool to register
   */
  addTool(tool) {
    this.registry.register(tool);
    this.analyzer.setTools(this.registry.list());
    return this;
  }

  /**
   * Update service configuration
   *
   * @param {Object} updates - Configuration updates
   */
  updateConfig(updates) {
    Object.assign(this.config, updates);
    return this;
  }

  /**
   * Record telemetry data
   */
  recordTelemetry(toolName, result) {
    // Implementation depends on telemetry system
    // Could send to analytics service, log file, etc.
  }

  /**
   * Update statistics
   */
  updateStats(intent, result, duration) {
    this.stats.totalCommands++;

    if (result.success) {
      this.stats.successfulCommands++;
    } else {
      this.stats.failedCommands++;
    }

    this.stats.commandByType[intent] = (this.stats.commandByType[intent] || 0) + 1;

    // Update average response time
    const totalDuration = this.stats.avgResponseTime * (this.stats.totalCommands - 1) + duration;
    this.stats.avgResponseTime = totalDuration / this.stats.totalCommands;
  }

  /**
   * Reset statistics
   */
  resetStats() {
    this.stats = {
      totalCommands: 0,
      successfulCommands: 0,
      failedCommands: 0,
      commandByType: {},
      avgResponseTime: 0
    };
    this.registry.clearHistory();
  }

  /**
   * Health check
   *
   * @returns {Object} Health status
   */
  healthCheck() {
    return {
      status: 'healthy',
      tools: this.registry.list().length,
      uptime: process.uptime(),
      memory: process.memoryUsage(),
      stats: this.getStats()
    };
  }

  /**
   * Cleanup resources
   */
  async cleanup() {
    this.registry.clearHistory();
    this.resetStats();
  }
}

/**
 * Factory function to create a service instance
 */
function createEnhancedTerminalService(config = {}) {
  return new EnhancedTerminalService(config);
}

module.exports = {
  EnhancedTerminalService,
  createEnhancedTerminalService
};
