import { logger } from './logger';
import { DirtyDataDetector, RiskProfile } from './dirty-data-detector';

export interface ModelRouterOptions {
  /** Force a specific model */
  forceModel?: 'opus-4.6' | 'kimi-k2' | 'sonnet-4';
  /** Override risk level */
  overrideRiskLevel?: 'low' | 'medium' | 'high';
  /** Skip logging */
  skipLogging?: boolean;
  /** Additional metadata for routing decisions */
  metadata?: Record<string, any>;
}

export interface RoutingDecision {
  model: 'opus-4.6' | 'kimi-k2' | 'sonnet-4';
  reason: string;
  riskProfile: RiskProfile;
  timestamp: Date;
  options: ModelRouterOptions;
}

/**
 * Routes requests to appropriate models based on data risk assessment
 */
export class ModelRouter {
  private static routingLog: RoutingDecision[] = [];
  private static readonly MAX_LOG_SIZE = 1000;

  /**
   * Route input data to the appropriate model
   */
  static route(data: string, options: ModelRouterOptions = {}): ModelRoute {
    const startTime = Date.now();
    
    // Check for forced model
    if (options.forceModel) {
      const decision: RoutingDecision = {
        model: options.forceModel,
        reason: 'Model forced by user request',
        riskProfile: {
          level: options.overrideRiskLevel || 'low',
          confidence: 1.0,
          reasons: ['Forced model selection'],
        },
        timestamp: new Date(),
        options,
      };
      
      this.logDecision(decision);
      return {
        model: options.forceModel,
        reason: decision.reason,
      };
    }

    // Analyze data risk
    const riskProfile = DirtyDataDetector.analyze(data, options.metadata);
    
    // Determine model based on risk level
    let model: 'opus-4.6' | 'kimi-k2' | 'sonnet-4';
    let reason: string;

    switch (riskProfile.level) {
      case 'high':
        model = 'opus-4.6';
        reason = `High-risk data detected (${riskProfile.confidence.toFixed(2)} confidence)`;
        break;
      
      case 'medium':
        model = 'sonnet-4';
        reason = `Medium-risk data detected (${riskProfile.confidence.toFixed(2)} confidence)`;
        break;
      
      case 'low':
      default:
        model = 'kimi-k2';
        reason = `Low-risk data detected (${riskProfile.confidence.toFixed(2)} confidence)`;
        break;
    }

    // Special cases
    if (options.metadata?.taskType === 'security-analysis') {
      model = 'opus-4.6';
      reason = 'Security analysis requires highest security model';
    }
    
    if (options.metadata?.taskType === 'creative-writing' && riskProfile.level !== 'high') {
      model = 'sonnet-4';
      reason = 'Creative tasks benefit from Sonnet\'s capabilities';
    }

    const decision: RoutingDecision = {
      model,
      reason,
      riskProfile,
      timestamp: new Date(),
      options,
    };

    this.logDecision(decision);

    if (!options.skipLogging) {
      logger.info('Model routing decision', {
        model,
        reason,
        riskLevel: riskProfile.level,
        confidence: riskProfile.confidence,
        processingTime: Date.now() - startTime,
      });
    }

    return {
      model,
      reason,
    };
  }

  /**
   * Route with session context
   */
  static routeWithSession(
    data: string, 
    sessionId: string, 
    options: ModelRouterOptions = {}
  ): ModelRoute {
    // Check session history for patterns
    const sessionHistory = this.getSessionHistory(sessionId);
    const metadata = {
      ...options.metadata,
      sessionId,
      sessionRiskScore: this.calculateSessionRisk(sessionHistory),
    };

    return this.route(data, { ...options, metadata });
  }

  /**
   * Get routing history
   */
  static getRoutingHistory(limit = 100): RoutingDecision[] {
    return this.routingLog.slice(-limit);
  }

  /**
   * Get routing statistics
   */
  static getStatistics(): Record<string, any> {
    const stats = {
      total: this.routingLog.length,
      byModel: {
        'opus-4.6': 0,
        'kimi-k2': 0,
        'sonnet-4': 0,
      },
      byRiskLevel: {
        high: 0,
        medium: 0,
        low: 0,
      },
      averageConfidence: 0,
    };

    if (this.routingLog.length === 0) {
      return stats;
    }

    let totalConfidence = 0;

    for (const decision of this.routingLog) {
      stats.byModel[decision.model]++;
      stats.byRiskLevel[decision.riskProfile.level]++;
      totalConfidence += decision.riskProfile.confidence;
    }

    stats.averageConfidence = totalConfidence / this.routingLog.length;

    return stats;
  }

  /**
   * Clear routing log
   */
  static clearHistory(): void {
    this.routingLog = [];
    logger.info('Model router history cleared');
  }

  /**
   * Export routing log for review
   */
  static exportLog(): string {
    return JSON.stringify({
      exportDate: new Date().toISOString(),
      decisions: this.routingLog,
      statistics: this.getStatistics(),
    }, null, 2);
  }

  private static logDecision(decision: RoutingDecision): void {
    this.routingLog.push(decision);
    
    // Keep log size manageable
    if (this.routingLog.length > this.MAX_LOG_SIZE) {
      this.routingLog = this.routingLog.slice(-this.MAX_LOG_SIZE);
    }
  }

  private static getSessionHistory(sessionId: string): RoutingDecision[] {
    return this.routingLog.filter(d => d.options.metadata?.sessionId === sessionId);
  }

  private static calculateSessionRisk(history: RoutingDecision[]): number {
    if (history.length === 0) return 0;
    
    const recent = history.slice(-10);
    const highRiskCount = recent.filter(d => d.riskProfile.level === 'high').length;
    
    return highRiskCount / recent.length;
  }
}

/**
 * Convenience function for quick routing
 */
export function routeModel(data: string, options?: ModelRouterOptions): ModelRoute {
  return ModelRouter.route(data, options);
}