/**
 * SONA Manager - Self-Optimizing Neural Architecture
 *
 * Manages learning modes and provides adaptive optimization for agent tasks.
 *
 * Performance Targets:
 * - Adaptation: <0.05ms
 * - Pattern retrieval: <1ms
 * - Learning step: <10ms
 *
 * Supported Modes:
 * - real-time: Sub-millisecond adaptation (2200 ops/sec)
 * - balanced: General purpose (+25% quality)
 * - research: Deep exploration (+55% quality)
 * - edge: Resource-constrained (<5MB)
 * - batch: High-throughput processing
 */

import type {
  SONAMode,
  SONAModeConfig,
  ModeOptimizations,
  Trajectory,
  TrajectoryStep,
  Pattern,
  PatternMatch,
  NeuralStats,
  NeuralEvent,
  NeuralEventListener,
  LoRAConfig,
  LoRAWeights,
  EWCConfig,
  EWCState,
  RLAlgorithm,
} from './types.js';

import { RealTimeMode } from './modes/real-time.js';
import { BalancedMode } from './modes/balanced.js';
import { ResearchMode } from './modes/research.js';
import { EdgeMode } from './modes/edge.js';
import { BatchMode } from './modes/batch.js';
import type { ModeImplementation } from './modes/index.js';
import { deepEncode, deepDecode } from './utils/serialize.js';

/**
 * Default mode configurations
 */
const MODE_CONFIGS: Record<SONAMode, SONAModeConfig> = {
  'real-time': {
    mode: 'real-time',
    loraRank: 2,
    learningRate: 0.001,
    batchSize: 32,
    trajectoryCapacity: 1000,
    patternClusters: 25,
    qualityThreshold: 0.7,
    maxLatencyMs: 0.5,
    memoryBudgetMb: 25,
    ewcLambda: 2000,
  },
  'balanced': {
    mode: 'balanced',
    loraRank: 4,
    learningRate: 0.002,
    batchSize: 32,
    trajectoryCapacity: 3000,
    patternClusters: 50,
    qualityThreshold: 0.5,
    maxLatencyMs: 18,
    memoryBudgetMb: 50,
    ewcLambda: 2000,
  },
  'research': {
    mode: 'research',
    loraRank: 16,
    learningRate: 0.002,
    batchSize: 64,
    trajectoryCapacity: 10000,
    patternClusters: 100,
    qualityThreshold: 0.2,
    maxLatencyMs: 100,
    memoryBudgetMb: 100,
    ewcLambda: 2500,
  },
  'edge': {
    mode: 'edge',
    loraRank: 1,
    learningRate: 0.001,
    batchSize: 16,
    trajectoryCapacity: 200,
    patternClusters: 15,
    qualityThreshold: 0.8,
    maxLatencyMs: 1,
    memoryBudgetMb: 5,
    ewcLambda: 1500,
  },
  'batch': {
    mode: 'batch',
    loraRank: 8,
    learningRate: 0.002,
    batchSize: 128,
    trajectoryCapacity: 5000,
    patternClusters: 75,
    qualityThreshold: 0.4,
    maxLatencyMs: 50,
    memoryBudgetMb: 75,
    ewcLambda: 2000,
  },
};

/**
 * Mode-specific optimizations
 */
const MODE_OPTIMIZATIONS: Record<SONAMode, ModeOptimizations> = {
  'real-time': {
    enableSIMD: true,
    useMicroLoRA: true,
    gradientCheckpointing: false,
    useHalfPrecision: true,
    patternCaching: true,
    asyncUpdates: true,
  },
  'balanced': {
    enableSIMD: true,
    useMicroLoRA: false,
    gradientCheckpointing: false,
    useHalfPrecision: false,
    patternCaching: true,
    asyncUpdates: false,
  },
  'research': {
    enableSIMD: true,
    useMicroLoRA: false,
    gradientCheckpointing: true,
    useHalfPrecision: false,
    patternCaching: true,
    asyncUpdates: false,
  },
  'edge': {
    enableSIMD: false,
    useMicroLoRA: true,
    gradientCheckpointing: false,
    useHalfPrecision: true,
    patternCaching: false,
    asyncUpdates: true,
  },
  'batch': {
    enableSIMD: true,
    useMicroLoRA: false,
    gradientCheckpointing: true,
    useHalfPrecision: true,
    patternCaching: true,
    asyncUpdates: true,
  },
};

/**
 * SONA Manager - Main orchestrator for neural learning
 */
export class SONAManager {
  private currentMode: SONAMode;
  private config: SONAModeConfig;
  private optimizations: ModeOptimizations;
  private modeImpl: ModeImplementation;

  private trajectories: Map<string, Trajectory> = new Map();
  private patterns: Map<string, Pattern> = new Map();
  private loraWeights: Map<string, LoRAWeights> = new Map();
  private ewcState: EWCState | null = null;

  private eventListeners: Set<NeuralEventListener> = new Set();
  private stats: NeuralStats;
  private isInitialized = false;

  // Performance tracking
  private operationCount = 0;
  private totalLatencyMs = 0;
  private learningCycles = 0;
  private lastStatsUpdate = Date.now();

  constructor(mode: SONAMode = 'balanced') {
    this.currentMode = mode;
    this.config = { ...MODE_CONFIGS[mode] };
    this.optimizations = { ...MODE_OPTIMIZATIONS[mode] };
    this.modeImpl = this.createModeImplementation(mode);
    this.stats = this.createInitialStats();
  }

  /**
   * Initialize the SONA manager
   */
  async initialize(): Promise<void> {
    if (this.isInitialized) return;

    // Initialize mode implementation
    await this.modeImpl.initialize();

    // Initialize EWC state for continual learning
    this.ewcState = {
      means: new Map(),
      fisher: new Map(),
      taskCount: 0,
      lastConsolidation: Date.now(),
    };

    this.isInitialized = true;
  }

  /**
   * Change the current learning mode
   */
  async setMode(mode: SONAMode): Promise<void> {
    if (mode === this.currentMode) return;

    const previousMode = this.currentMode;

    // Cleanup current mode
    await this.modeImpl.cleanup();

    // Update configuration
    this.currentMode = mode;
    this.config = { ...MODE_CONFIGS[mode] };
    this.optimizations = { ...MODE_OPTIMIZATIONS[mode] };

    // Create new mode implementation
    this.modeImpl = this.createModeImplementation(mode);
    await this.modeImpl.initialize();

    // Emit mode change event
    this.emitEvent({
      type: 'mode_changed',
      fromMode: previousMode,
      toMode: mode,
    });
  }

  /**
   * Get current mode and configuration
   */
  getConfig(): { mode: SONAMode; config: SONAModeConfig; optimizations: ModeOptimizations } {
    return {
      mode: this.currentMode,
      config: { ...this.config },
      optimizations: { ...this.optimizations },
    };
  }

  // ==========================================================================
  // Trajectory Management
  // ==========================================================================

  /**
   * Begin a new trajectory for a task
   */
  beginTrajectory(context: string, domain: Trajectory['domain'] = 'general'): string {
    const startTime = performance.now();

    const trajectoryId = `traj_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;

    const trajectory: Trajectory = {
      trajectoryId,
      context,
      domain,
      steps: [],
      qualityScore: 0,
      isComplete: false,
      startTime: Date.now(),
    };

    this.trajectories.set(trajectoryId, trajectory);

    this.emitEvent({
      type: 'trajectory_started',
      trajectoryId,
      context,
    });

    this.trackLatency(performance.now() - startTime);
    return trajectoryId;
  }

  /**
   * Record a step in a trajectory
   */
  recordStep(
    trajectoryId: string,
    action: string,
    reward: number,
    stateEmbedding: Float32Array,
    metadata?: Record<string, unknown>
  ): void {
    const startTime = performance.now();

    const trajectory = this.trajectories.get(trajectoryId);
    if (!trajectory || trajectory.isComplete) return;

    const step: TrajectoryStep = {
      stepId: `step_${trajectory.steps.length}`,
      timestamp: Date.now(),
      action,
      stateBefore: trajectory.steps.length > 0
        ? trajectory.steps[trajectory.steps.length - 1].stateAfter
        : stateEmbedding,
      stateAfter: stateEmbedding,
      reward,
      metadata,
    };

    trajectory.steps.push(step);

    // Update running quality score
    trajectory.qualityScore = this.calculateQualityScore(trajectory);

    this.trackLatency(performance.now() - startTime);
  }

  /**
   * Complete a trajectory
   */
  completeTrajectory(trajectoryId: string, finalQuality?: number): Trajectory | null {
    const startTime = performance.now();

    const trajectory = this.trajectories.get(trajectoryId);
    if (!trajectory || trajectory.isComplete) return null;

    trajectory.isComplete = true;
    trajectory.endTime = Date.now();

    if (finalQuality !== undefined) {
      trajectory.qualityScore = finalQuality;
    } else {
      trajectory.qualityScore = this.calculateQualityScore(trajectory);
    }

    this.emitEvent({
      type: 'trajectory_completed',
      trajectoryId,
      qualityScore: trajectory.qualityScore,
    });

    // Check if we should trigger learning
    this.checkLearningTrigger();

    this.trackLatency(performance.now() - startTime);
    return trajectory;
  }

  /**
   * Get a trajectory by ID
   */
  getTrajectory(trajectoryId: string): Trajectory | undefined {
    return this.trajectories.get(trajectoryId);
  }

  // ==========================================================================
  // Pattern Matching
  // ==========================================================================

  /**
   * Find similar patterns for a given context (k=3 optimal)
   */
  async findSimilarPatterns(
    embedding: Float32Array,
    k: number = 3
  ): Promise<PatternMatch[]> {
    const startTime = performance.now();

    const matches = await this.modeImpl.findPatterns(embedding, k, Array.from(this.patterns.values()));

    // Track pattern match events
    for (const match of matches) {
      this.emitEvent({
        type: 'pattern_matched',
        patternId: match.pattern.patternId,
        similarity: match.similarity,
      });
    }

    const latency = performance.now() - startTime;

    // Add latency to matches
    return matches.map(m => ({ ...m, latencyMs: latency }));
  }

  /**
   * Store a new pattern
   */
  storePattern(pattern: Omit<Pattern, 'patternId' | 'createdAt' | 'updatedAt'>): Pattern {
    const startTime = performance.now();

    const fullPattern: Pattern = {
      ...pattern,
      patternId: `pat_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
      createdAt: Date.now(),
      updatedAt: Date.now(),
    };

    this.patterns.set(fullPattern.patternId, fullPattern);

    this.trackLatency(performance.now() - startTime);
    return fullPattern;
  }

  /**
   * Update pattern based on usage
   */
  updatePatternUsage(patternId: string, quality: number): void {
    const pattern = this.patterns.get(patternId);
    if (!pattern) return;

    pattern.usageCount++;
    pattern.qualityHistory.push(quality);

    // Keep only last 100 quality scores
    if (pattern.qualityHistory.length > 100) {
      pattern.qualityHistory = pattern.qualityHistory.slice(-100);
    }

    // Update success rate
    pattern.successRate = pattern.qualityHistory.reduce((a, b) => a + b, 0) / pattern.qualityHistory.length;
    pattern.updatedAt = Date.now();
  }

  // ==========================================================================
  // Learning
  // ==========================================================================

  /**
   * Trigger a learning cycle
   */
  async triggerLearning(reason: string = 'manual'): Promise<void> {
    const startTime = performance.now();

    const completedTrajectories = Array.from(this.trajectories.values())
      .filter(t => t.isComplete && t.qualityScore >= this.config.qualityThreshold);

    if (completedTrajectories.length === 0) return;

    this.emitEvent({
      type: 'learning_triggered',
      reason,
      trajectoryCount: completedTrajectories.length,
    });

    // Perform learning via mode implementation
    const improvementDelta = await this.modeImpl.learn(
      completedTrajectories,
      this.config,
      this.ewcState!
    );

    this.learningCycles++;

    this.emitEvent({
      type: 'learning_completed',
      improvementDelta,
    });

    // Prune old trajectories if over capacity
    this.pruneTrajectories();

    this.trackLatency(performance.now() - startTime);
  }

  /**
   * Apply learned adaptations to processing
   */
  async applyAdaptations(
    input: Float32Array,
    domain?: string
  ): Promise<Float32Array> {
    const startTime = performance.now();

    // Get relevant LoRA weights
    const weights = domain
      ? this.loraWeights.get(domain)
      : this.loraWeights.get('default');

    // Apply adaptations via mode implementation
    const output = await this.modeImpl.applyLoRA(input, weights);

    const latency = performance.now() - startTime;

    // Verify performance target
    if (latency > 0.05 && this.currentMode !== 'research' && this.currentMode !== 'batch') {
      console.warn(`SONA adaptation exceeded target: ${latency.toFixed(3)}ms > 0.05ms`);
    }

    return output;
  }

  // ==========================================================================
  // LoRA Management
  // ==========================================================================

  /**
   * Get LoRA configuration for current mode
   */
  getLoRAConfig(): LoRAConfig {
    return {
      rank: this.config.loraRank,
      alpha: this.config.loraRank * 2,
      dropout: 0.05,
      targetModules: ['q_proj', 'v_proj', 'k_proj', 'o_proj'],
      microLoRA: this.optimizations.useMicroLoRA,
    };
  }

  /**
   * Initialize LoRA weights for a domain
   */
  initializeLoRAWeights(domain: string = 'default'): LoRAWeights {
    const config = this.getLoRAConfig();

    const weights: LoRAWeights = {
      adapterId: `lora_${domain}_${Date.now()}`,
      A: new Map(),
      B: new Map(),
      createdAt: Date.now(),
      updatedAt: Date.now(),
      iterations: 0,
      domain,
    };

    // Initialize A and B matrices for each target module
    for (const module of config.targetModules) {
      // A: (hidden_dim, rank) initialized with small random values
      // B: (rank, hidden_dim) initialized to zero
      const hiddenDim = 768; // Typical transformer hidden dim
      const A = new Float32Array(hiddenDim * config.rank);
      const B = new Float32Array(config.rank * hiddenDim);

      // Initialize A with small random values
      for (let i = 0; i < A.length; i++) {
        A[i] = (Math.random() - 0.5) * 0.02;
      }

      weights.A.set(module, A);
      weights.B.set(module, B);
    }

    this.loraWeights.set(domain, weights);
    return weights;
  }

  // ==========================================================================
  // EWC (Elastic Weight Consolidation)
  // ==========================================================================

  /**
   * Get EWC configuration
   */
  getEWCConfig(): EWCConfig {
    return {
      lambda: this.config.ewcLambda,
      decay: 0.9,
      fisherSamples: 100,
      minFisher: 1e-8,
      online: true,
    };
  }

  /**
   * Consolidate EWC after learning a new task
   */
  consolidateEWC(): void {
    if (!this.ewcState) return;

    const config = this.getEWCConfig();

    // Update Fisher information with decay
    for (const [key, fisher] of this.ewcState.fisher) {
      for (let i = 0; i < fisher.length; i++) {
        fisher[i] *= config.decay;
      }
    }

    this.ewcState.taskCount++;
    this.ewcState.lastConsolidation = Date.now();
  }

  // ==========================================================================
  // Statistics
  // ==========================================================================

  /**
   * Get current neural system statistics
   */
  getStats(): NeuralStats {
    this.updateStats();
    return { ...this.stats };
  }

  // ==========================================================================
  // Persistence (#1773 Phase 1.6)
  // ==========================================================================

  /**
   * Serialize manager state to a JSON-safe object. Includes mode, config,
   * trajectories, patterns, LoRA weights, EWC state, and stats. Excludes
   * the active mode implementation (rebuilt on deserialize) and event
   * listeners (callers re-register on restore).
   */
  serialize(): unknown {
    return deepEncode({
      schemaVersion: 1,
      currentMode: this.currentMode,
      config: this.config,
      optimizations: this.optimizations,
      trajectories: this.trajectories,
      patterns: this.patterns,
      loraWeights: this.loraWeights,
      ewcState: this.ewcState,
      stats: this.stats,
      isInitialized: this.isInitialized,
      operationCount: this.operationCount,
      totalLatencyMs: this.totalLatencyMs,
      learningCycles: this.learningCycles,
      lastStatsUpdate: this.lastStatsUpdate,
    });
  }

  /**
   * Restore manager state from a previously-serialized snapshot. Mode
   * implementation is rebuilt for the saved mode. Event listeners are NOT
   * restored — re-register manually after deserialize() returns.
   */
  deserialize(state: unknown): void {
    const decoded = deepDecode(state) as {
      schemaVersion: number;
      currentMode: SONAMode;
      config: SONAModeConfig;
      optimizations: ModeOptimizations;
      trajectories: Map<string, Trajectory>;
      patterns: Map<string, Pattern>;
      loraWeights: Map<string, LoRAWeights>;
      ewcState: EWCState | null;
      stats: NeuralStats;
      isInitialized: boolean;
      operationCount: number;
      totalLatencyMs: number;
      learningCycles: number;
      lastStatsUpdate: number;
    };
    if (decoded.schemaVersion !== 1) {
      throw new Error(`SONAManager: unsupported schemaVersion ${decoded.schemaVersion} (expected 1)`);
    }
    this.currentMode = decoded.currentMode;
    this.config = decoded.config;
    this.optimizations = decoded.optimizations;
    this.modeImpl = this.createModeImplementation(this.currentMode);
    this.trajectories = decoded.trajectories;
    this.patterns = decoded.patterns;
    this.loraWeights = decoded.loraWeights;
    this.ewcState = decoded.ewcState;
    this.stats = decoded.stats;
    this.isInitialized = decoded.isInitialized;
    this.operationCount = decoded.operationCount;
    this.totalLatencyMs = decoded.totalLatencyMs;
    this.learningCycles = decoded.learningCycles;
    this.lastStatsUpdate = decoded.lastStatsUpdate;
  }

  // ==========================================================================
  // Event System
  // ==========================================================================

  /**
   * Add an event listener
   */
  addEventListener(listener: NeuralEventListener): void {
    this.eventListeners.add(listener);
  }

  /**
   * Remove an event listener
   */
  removeEventListener(listener: NeuralEventListener): void {
    this.eventListeners.delete(listener);
  }

  // ==========================================================================
  // Cleanup
  // ==========================================================================

  /**
   * Cleanup resources
   */
  async cleanup(): Promise<void> {
    await this.modeImpl.cleanup();
    this.trajectories.clear();
    this.patterns.clear();
    this.loraWeights.clear();
    this.eventListeners.clear();
    this.isInitialized = false;
  }

  // ==========================================================================
  // Private Methods
  // ==========================================================================

  private createModeImplementation(mode: SONAMode): ModeImplementation {
    switch (mode) {
      case 'real-time':
        return new RealTimeMode(MODE_CONFIGS[mode], MODE_OPTIMIZATIONS[mode]);
      case 'balanced':
        return new BalancedMode(MODE_CONFIGS[mode], MODE_OPTIMIZATIONS[mode]);
      case 'research':
        return new ResearchMode(MODE_CONFIGS[mode], MODE_OPTIMIZATIONS[mode]);
      case 'edge':
        return new EdgeMode(MODE_CONFIGS[mode], MODE_OPTIMIZATIONS[mode]);
      case 'batch':
        return new BatchMode(MODE_CONFIGS[mode], MODE_OPTIMIZATIONS[mode]);
      default:
        return new BalancedMode(MODE_CONFIGS['balanced'], MODE_OPTIMIZATIONS['balanced']);
    }
  }

  private calculateQualityScore(trajectory: Trajectory): number {
    if (trajectory.steps.length === 0) return 0;

    // Average reward across steps
    const avgReward = trajectory.steps.reduce((sum, step) => sum + step.reward, 0) / trajectory.steps.length;

    // Discount factor for trajectory length (longer trajectories may accumulate errors)
    const lengthFactor = Math.min(1, 10 / trajectory.steps.length);

    return avgReward * 0.8 + lengthFactor * 0.2;
  }

  private checkLearningTrigger(): void {
    const completedCount = Array.from(this.trajectories.values())
      .filter(t => t.isComplete).length;

    const utilization = completedCount / this.config.trajectoryCapacity;

    // Trigger learning at 80% utilization
    if (utilization >= 0.8) {
      this.triggerLearning('capacity_threshold');
    }
  }

  private pruneTrajectories(): void {
    const completed = Array.from(this.trajectories.entries())
      .filter(([_, t]) => t.isComplete)
      .sort((a, b) => a[1].qualityScore - b[1].qualityScore);

    // Remove lowest quality trajectories if over capacity
    const toRemove = completed.length - Math.floor(this.config.trajectoryCapacity * 0.5);

    if (toRemove > 0) {
      for (let i = 0; i < toRemove && i < completed.length; i++) {
        this.trajectories.delete(completed[i][0]);
      }
    }
  }

  private trackLatency(latencyMs: number): void {
    this.operationCount++;
    this.totalLatencyMs += latencyMs;
  }

  private emitEvent(event: NeuralEvent): void {
    for (const listener of this.eventListeners) {
      try {
        listener(event);
      } catch (error) {
        console.error('Error in neural event listener:', error);
      }
    }
  }

  private createInitialStats(): NeuralStats {
    return {
      trajectories: {
        total: 0,
        active: 0,
        completed: 0,
        utilization: 0,
      },
      performance: {
        avgQualityScore: 0,
        opsPerSecond: 0,
        learningCycles: 0,
        avgLatencyMs: 0,
      },
      patterns: {
        totalPatterns: 0,
        avgMatchTime: 0,
        cacheHitRate: 0,
        evolutionCount: 0,
      },
      memory: {
        usedMb: 0,
        budgetMb: this.config.memoryBudgetMb,
        trajectoryBytes: 0,
        patternBytes: 0,
      },
      config: {
        mode: this.currentMode,
        loraRank: this.config.loraRank,
        learningRate: this.config.learningRate,
        algorithm: 'ppo',
      },
    };
  }

  private updateStats(): void {
    const now = Date.now();
    const elapsed = (now - this.lastStatsUpdate) / 1000;

    const trajectoryArray = Array.from(this.trajectories.values());
    const completed = trajectoryArray.filter(t => t.isComplete);

    this.stats = {
      trajectories: {
        total: trajectoryArray.length,
        active: trajectoryArray.filter(t => !t.isComplete).length,
        completed: completed.length,
        utilization: trajectoryArray.length / this.config.trajectoryCapacity,
      },
      performance: {
        avgQualityScore: completed.length > 0
          ? completed.reduce((sum, t) => sum + t.qualityScore, 0) / completed.length
          : 0,
        opsPerSecond: elapsed > 0 ? this.operationCount / elapsed : 0,
        learningCycles: this.learningCycles,
        avgLatencyMs: this.operationCount > 0
          ? this.totalLatencyMs / this.operationCount
          : 0,
      },
      patterns: {
        totalPatterns: this.patterns.size,
        avgMatchTime: 0, // Updated by mode implementation
        cacheHitRate: 0, // Updated by mode implementation
        evolutionCount: Array.from(this.patterns.values())
          .reduce((sum, p) => sum + p.evolutionHistory.length, 0),
      },
      memory: {
        usedMb: this.estimateMemoryUsage(),
        budgetMb: this.config.memoryBudgetMb,
        trajectoryBytes: this.estimateTrajectoryBytes(),
        patternBytes: this.estimatePatternBytes(),
      },
      config: {
        mode: this.currentMode,
        loraRank: this.config.loraRank,
        learningRate: this.config.learningRate,
        algorithm: 'ppo',
      },
    };

    this.lastStatsUpdate = now;
    this.operationCount = 0;
    this.totalLatencyMs = 0;
  }

  private estimateMemoryUsage(): number {
    // Rough estimation in MB
    return (this.estimateTrajectoryBytes() + this.estimatePatternBytes()) / (1024 * 1024);
  }

  private estimateTrajectoryBytes(): number {
    let bytes = 0;
    for (const trajectory of this.trajectories.values()) {
      bytes += 200; // Base trajectory overhead
      bytes += trajectory.context.length * 2;
      bytes += trajectory.steps.length * (64 + 4 * 768 * 4); // Step overhead + embeddings
    }
    return bytes;
  }

  private estimatePatternBytes(): number {
    let bytes = 0;
    for (const pattern of this.patterns.values()) {
      bytes += 100; // Base pattern overhead
      bytes += pattern.name.length * 2;
      bytes += pattern.strategy.length * 2;
      bytes += pattern.embedding.byteLength;
      bytes += pattern.qualityHistory.length * 8;
      bytes += pattern.evolutionHistory.length * 100;
    }
    return bytes;
  }
}

/**
 * Factory function for creating SONA manager
 */
export function createSONAManager(mode: SONAMode = 'balanced'): SONAManager {
  return new SONAManager(mode);
}

/**
 * Get default configuration for a mode
 */
export function getModeConfig(mode: SONAMode): SONAModeConfig {
  return { ...MODE_CONFIGS[mode] };
}

/**
 * Get optimizations for a mode
 */
export function getModeOptimizations(mode: SONAMode): ModeOptimizations {
  return { ...MODE_OPTIMIZATIONS[mode] };
}
