/**
 * @package
 * Test visualization manager for state debugging.
 * 
 * This module provides a simplified interface for test state visualization,
 * with support for different verbosity levels based on test configuration.
 */

import type { IStateVisualizationService, VisualizationConfig, ContextVisualizationConfig } from './IStateVisualizationService';
import type { IStateHistoryService } from '../StateHistoryService/IStateHistoryService';
import type { IStateTrackingService } from '../StateTrackingService/IStateTrackingService';
import { StateVisualizationFileOutput, FileOutputConfig } from './FileOutputService';
import { CompactStateVisualization } from './CompactStateVisualization';
import { serviceLogger } from '@core/utils/logger';

/**
 * Verbosity levels for test output
 */
export enum TestOutputVerbosity {
  /**
   * Minimal output - only error information
   */
  Minimal = 'minimal',
  
  /**
   * Standard output - errors plus basic test state info
   */
  Standard = 'standard',
  
  /**
   * Verbose output - detailed state information 
   */
  Verbose = 'verbose',
  
  /**
   * Debug output - maximum detail for troubleshooting
   */
  Debug = 'debug'
}

/**
 * Configuration for test visualization manager
 */
export interface TestVisualizationConfig {
  /**
   * Verbosity level for console output
   */
  verbosity?: TestOutputVerbosity;
  
  /**
   * If true, visualizations will be written to files instead of console
   */
  outputToFiles?: boolean;
  
  /**
   * Base directory for file outputs
   */
  outputDir?: string;
  
  /**
   * Default visualization format
   */
  defaultFormat?: 'mermaid' | 'dot' | 'json';
  
  /**
   * If true, system state metrics will be included
   */
  includeMetrics?: boolean;
}

/**
 * Manages state visualizations for test environments
 */
export class TestVisualizationManager {
  private fileOutput: StateVisualizationFileOutput;
  private compactVis: CompactStateVisualization;
  private verbosity: TestOutputVerbosity;
  private outputToFiles: boolean;
  private defaultFormat: 'mermaid' | 'dot' | 'json';
  private includeMetrics: boolean;
  
  /**
   * Create a new test visualization manager
   */
  constructor(
    private visualizationService: IStateVisualizationService,
    private historyService: IStateHistoryService,
    private trackingService: IStateTrackingService,
    config: TestVisualizationConfig = {}
  ) {
    this.verbosity = this.resolveVerbosity(config.verbosity);
    this.outputToFiles = config.outputToFiles ?? false;
    this.defaultFormat = config.defaultFormat || 'mermaid';
    this.includeMetrics = config.includeMetrics ?? true;
    
    // Initialize file output service if needed
    const fileConfig: FileOutputConfig = {
      outputDir: config.outputDir || './logs/state-visualization'
    };
    this.fileOutput = new StateVisualizationFileOutput(fileConfig);
    
    // Initialize compact visualization service
    this.compactVis = new CompactStateVisualization(
      this.historyService,
      this.trackingService,
      this.visualizationService
    );
    
    serviceLogger.debug('Test visualization manager initialized', { 
      verbosity: this.verbosity,
      outputToFiles: this.outputToFiles,
      defaultFormat: this.defaultFormat
    });
  }
  
  /**
   * Visualize a state with appropriate verbosity
   * @param stateId - The state ID to visualize
   * @param label - Optional label for the visualization
   * @returns The visualization result as string or file path
   */
  public visualizeState(stateId: string, label?: string): string | null {
    try {
      // Early return for minimal verbosity
      if (this.verbosity === TestOutputVerbosity.Minimal) {
        return null;
      }
      
      // Handle different verbosity levels
      if (this.verbosity === TestOutputVerbosity.Standard) {
        return this.handleStandardVerbosity(stateId, label);
      } else if (this.verbosity === TestOutputVerbosity.Verbose) {
        return this.handleVerboseVerbosity(stateId, label);
      } else if (this.verbosity === TestOutputVerbosity.Debug) {
        return this.handleDebugVerbosity(stateId, label);
      }
      
      return null;
    } catch (error) {
      serviceLogger.error('Failed to visualize state', { stateId, error });
      return `Error visualizing state ${stateId}: ${error instanceof Error ? error.message : 'Unknown error'}`;
    }
  }
  
  /**
   * Visualize multiple states with appropriate verbosity
   * @param stateIds - The state IDs to visualize
   * @param label - Optional label for the visualization
   * @returns The visualization result as string or file path
   */
  public visualizeStates(stateIds: string[], label?: string): string | null {
    try {
      // Early return for minimal verbosity
      if (this.verbosity === TestOutputVerbosity.Minimal || stateIds.length === 0) {
        return null;
      }
      
      if (stateIds.length === 1) {
        return this.visualizeState(stateIds[0], label);
      }
      
      // For relationship visualizations
      const fileName = `state_relationship_${label || 'graph'}`;
      
      if (this.verbosity === TestOutputVerbosity.Standard) {
        // Compact summary of states
        const summary = stateIds.map(id => this.compactVis.generateCompactStateSummary(id)).join('\n\n');
        
        if (this.outputToFiles) {
          return this.fileOutput.writeToFile(summary, fileName, 'text');
        }
        
        return summary;
      } else {
        // Generate relationship graph with appropriate detail level
        const config: VisualizationConfig = {
          format: this.defaultFormat,
          includeMetadata: this.verbosity === TestOutputVerbosity.Debug,
          includeTimestamps: this.verbosity === TestOutputVerbosity.Debug,
        };
        
        const visualization = this.visualizationService.generateRelationshipGraph(stateIds, config);
        
        if (this.outputToFiles) {
          if (this.defaultFormat === 'mermaid') {
            return this.fileOutput.writeMermaidHtml(visualization, fileName, label);
          } else {
            return this.fileOutput.writeToFile(visualization, fileName, this.defaultFormat);
          }
        }
        
        return visualization;
      }
    } catch (error) {
      serviceLogger.error('Failed to visualize states', { stateIds, error });
      return `Error visualizing states: ${error instanceof Error ? error.message : 'Unknown error'}`;
    }
  }
  
  /**
   * Visualize variable resolution across states
   * @param variableName - The variable name to trace
   * @param rootStateId - Optional root state to limit scope
   * @param label - Optional label for the visualization
   * @returns The visualization result as string or file path
   */
  public visualizeVariableResolution(variableName: string, rootStateId?: string, label?: string): string | null {
    try {
      // Early return for minimal verbosity
      if (this.verbosity === TestOutputVerbosity.Minimal) {
        return null;
      }
      
      const fileName = `variable_resolution_${variableName}_${label || 'trace'}`;
      
      // Different detail levels based on verbosity
      const config: ContextVisualizationConfig = {
        format: this.defaultFormat,
        includeVars: true,
        includeFilePaths: this.verbosity !== TestOutputVerbosity.Standard,
        includeTimestamps: this.verbosity === TestOutputVerbosity.Debug,
        filterToRelevantVars: this.verbosity !== TestOutputVerbosity.Debug,
      };
      
      const visualization = this.visualizationService.visualizeVariablePropagation(
        variableName,
        rootStateId,
        config
      );
      
      if (this.outputToFiles) {
        if (this.defaultFormat === 'mermaid') {
          return this.fileOutput.writeMermaidHtml(visualization, fileName, `Variable: ${variableName}`);
        } else {
          return this.fileOutput.writeToFile(visualization, fileName, this.defaultFormat);
        }
      }
      
      return visualization;
    } catch (error) {
      serviceLogger.error('Failed to visualize variable resolution', { variableName, rootStateId, error });
      return `Error visualizing variable resolution: ${error instanceof Error ? error.message : 'Unknown error'}`;
    }
  }
  
  /**
   * Generate state metrics appropriate for the configured verbosity
   * @returns The metrics result as string or file path
   */
  public generateMetrics(): string | null {
    try {
      // Skip metrics if not enabled or minimal verbosity
      if (!this.includeMetrics || this.verbosity === TestOutputVerbosity.Minimal) {
        return null;
      }
      
      const fileName = 'state_metrics';
      
      if (this.verbosity === TestOutputVerbosity.Standard) {
        // Generate compact metrics summary
        const summary = this.compactVis.generateCompactMetricsSummary();
        
        if (this.outputToFiles) {
          return this.fileOutput.writeToFile(summary, fileName, 'text');
        }
        
        return summary;
      } else {
        // Generate detailed metrics
        const metrics = this.visualizationService.getMetrics();
        const detailedMetrics = JSON.stringify(metrics, null, 2);
        
        if (this.outputToFiles) {
          return this.fileOutput.writeToFile(detailedMetrics, fileName, 'json');
        }
        
        return detailedMetrics;
      }
    } catch (error) {
      serviceLogger.error('Failed to generate metrics', { error });
      return `Error generating metrics: ${error instanceof Error ? error.message : 'Unknown error'}`;
    }
  }
  
  /**
   * Set the verbosity level
   * @param verbosity - The new verbosity level
   */
  public setVerbosity(verbosity: TestOutputVerbosity | string): void {
    this.verbosity = this.resolveVerbosity(verbosity);
    serviceLogger.debug('Test visualization verbosity updated', { verbosity: this.verbosity });
  }
  
  /**
   * Set output mode (console vs files)
   * @param outputToFiles - Whether to output to files
   */
  public setOutputMode(outputToFiles: boolean): void {
    this.outputToFiles = outputToFiles;
    serviceLogger.debug('Test visualization output mode updated', { outputToFiles });
  }
  
  /**
   * Clear all visualization files from the output directory
   * @returns Success indicator
   */
  public clearOutputFiles(): boolean {
    return this.fileOutput.clearOutputDirectory();
  }
  
  /**
   * Handle standard verbosity visualization
   * @private
   */
  private handleStandardVerbosity(stateId: string, label?: string): string | null {
    // Generate compact summary
    const summary = this.compactVis.generateCompactStateSummary(stateId);
    
    if (this.outputToFiles) {
      const fileName = `state_${stateId}_${label || 'summary'}`;
      return this.fileOutput.writeToFile(summary, fileName, 'text');
    }
    
    return summary;
  }
  
  /**
   * Handle verbose verbosity visualization
   * @private
   */
  private handleVerboseVerbosity(stateId: string, label?: string): string | null {
    // Generate both state summary and transformation details
    const stateSummary = this.compactVis.generateCompactStateSummary(stateId);
    const transformSummary = this.compactVis.generateCompactTransformSummary(stateId);
    
    if (this.outputToFiles) {
      const fileName = `state_${stateId}_${label || 'verbose'}`;
      const content = `${stateSummary}\n\n${transformSummary}`;
      return this.fileOutput.writeToFile(content, fileName, 'text');
    }
    
    return `${stateSummary}\n\n${transformSummary}`;
  }
  
  /**
   * Handle debug verbosity visualization
   * @private
   */
  private handleDebugVerbosity(stateId: string, label?: string): string | null {
    // Generate full hierarchy visualization
    const config: VisualizationConfig = {
      format: this.defaultFormat,
      includeMetadata: true,
      includeTimestamps: true,
    };
    
    const visualization = this.visualizationService.generateHierarchyView(stateId, config);
    
    // Add transformation diagram if available
    const transformations = this.historyService.getTransformationChain(stateId);
    let transitionDiagram = '';
    
    if (transformations.length > 0) {
      transitionDiagram = this.visualizationService.generateTransitionDiagram(stateId, config);
    }
    
    if (this.outputToFiles) {
      const fileName = `state_${stateId}_${label || 'debug'}`;
      
      if (this.defaultFormat === 'mermaid') {
        // Create combined HTML with both visualizations
        const combinedMermaid = `${visualization}\n\n${transitionDiagram}`;
        return this.fileOutput.writeMermaidHtml(combinedMermaid, fileName, `State ${stateId} Debug View`);
      } else {
        // Write separate files
        const hierarchyFile = this.fileOutput.writeToFile(
          visualization, 
          `${fileName}_hierarchy`, 
          this.defaultFormat
        );
        
        if (transformations.length > 0) {
          this.fileOutput.writeToFile(
            transitionDiagram,
            `${fileName}_transitions`,
            this.defaultFormat
          );
        }
        
        return hierarchyFile;
      }
    }
    
    // Return combined visualization for console output
    return transformations.length > 0
      ? `${visualization}\n\n${transitionDiagram}`
      : visualization;
  }
  
  /**
   * Resolve verbosity from string or enum value
   * @private
   */
  private resolveVerbosity(verbosity?: TestOutputVerbosity | string): TestOutputVerbosity {
    if (!verbosity) {
      // Check for environment variable
      const envVerbosity = process.env.TEST_LOG_LEVEL || process.env.TEST_VISUALIZATION_LEVEL;
      
      if (envVerbosity) {
        return this.resolveVerbosityFromString(envVerbosity);
      }
      
      // Default to standard
      return TestOutputVerbosity.Standard;
    }
    
    if (typeof verbosity === 'string') {
      return this.resolveVerbosityFromString(verbosity);
    }
    
    return verbosity;
  }
  
  /**
   * Resolve verbosity from string value
   * @private
   */
  private resolveVerbosityFromString(verbosity: string): TestOutputVerbosity {
    switch (verbosity.toLowerCase()) {
      case 'minimal':
      case 'min':
      case 'none':
        return TestOutputVerbosity.Minimal;
        
      case 'standard':
      case 'normal':
      case 'default':
        return TestOutputVerbosity.Standard;
        
      case 'verbose':
      case 'detailed':
        return TestOutputVerbosity.Verbose;
        
      case 'debug':
      case 'full':
      case 'max':
        return TestOutputVerbosity.Debug;
        
      default:
        serviceLogger.warn('Unknown verbosity level, defaulting to standard', { requestedVerbosity: verbosity });
        return TestOutputVerbosity.Standard;
    }
  }
}