/**
 * Alert Configuration and Routing Service
 * Manages SLA thresholds, alert routing, and notification delivery
 */

export interface SLAThresholds {
  latency: {
    warning: number; // ms
    critical: number; // ms
  };
  errorRate: {
    warning: number; // percentage
    critical: number; // percentage
  };
  deliverySuccessRate: {
    email: number; // percentage
    sms: number; // percentage
  };
  forecastAccuracy: {
    minimum: number; // percentage
    degradationThreshold: number; // percentage drop
  };
}

export interface AlertRoute {
  severity: 'low' | 'medium' | 'high' | 'critical';
  channels: ('slack' | 'pagerduty' | 'email')[];
  escalationTime?: number; // minutes
}

export interface AlertConfiguration {
  enabled: boolean;
  slathresholds: SLAThresholds;
  routes: Record<string, AlertRoute>;
  slackWebhook?: string;
  pagerdutyKey?: string;
  emailRecipients?: string[];
}

class AlertConfigService {
  private config: AlertConfiguration = {
    enabled: true,
    slathresholds: {
      latency: {
        warning: 500, // 500ms warning
        critical: 1000, // 1s critical
      },
      errorRate: {
        warning: 5, // 5% warning
        critical: 10, // 10% critical
      },
      deliverySuccessRate: {
        email: 95, // 95% success rate
        sms: 98, // 98% success rate
      },
      forecastAccuracy: {
        minimum: 70, // 70% minimum accuracy
        degradationThreshold: 10, // 10% drop triggers alert
      },
    },
    routes: {
      latency_warning: {
        severity: 'medium',
        channels: ['slack'],
      },
      latency_critical: {
        severity: 'critical',
        channels: ['slack', 'pagerduty', 'email'],
        escalationTime: 15,
      },
      error_rate_warning: {
        severity: 'medium',
        channels: ['slack'],
      },
      error_rate_critical: {
        severity: 'critical',
        channels: ['slack', 'pagerduty', 'email'],
        escalationTime: 10,
      },
      delivery_failure: {
        severity: 'high',
        channels: ['slack', 'email'],
      },
      forecast_accuracy_low: {
        severity: 'medium',
        channels: ['slack'],
      },
      forecast_accuracy_degrading: {
        severity: 'high',
        channels: ['slack', 'email'],
      },
    },
  };

  /**
   * Get current SLA thresholds
   */
  getThresholds(): SLAThresholds {
    return this.config.slathresholds;
  }

  /**
   * Update SLA thresholds
   */
  updateThresholds(thresholds: Partial<SLAThresholds>) {
    this.config.slathresholds = {
      ...this.config.slathresholds,
      ...thresholds,
    };

    console.log('[Alert Config] SLA thresholds updated:', this.config.slathresholds);
  }

  /**
   * Get alert route for specific alert type
   */
  getAlertRoute(alertType: string): AlertRoute | undefined {
    return this.config.routes[alertType];
  }

  /**
   * Update alert route
   */
  updateAlertRoute(alertType: string, route: AlertRoute) {
    this.config.routes[alertType] = route;
    console.log(`[Alert Config] Route updated for ${alertType}:`, route);
  }

  /**
   * Set Slack webhook
   */
  setSlackWebhook(webhook: string) {
    this.config.slackWebhook = webhook;
    console.log('[Alert Config] Slack webhook configured');
  }

  /**
   * Set PagerDuty key
   */
  setPagerDutyKey(key: string) {
    this.config.pagerdutyKey = key;
    console.log('[Alert Config] PagerDuty key configured');
  }

  /**
   * Set email recipients
   */
  setEmailRecipients(recipients: string[]) {
    this.config.emailRecipients = recipients;
    console.log('[Alert Config] Email recipients configured:', recipients);
  }

  /**
   * Check if latency exceeds threshold
   */
  isLatencyCritical(latency: number): boolean {
    return latency > this.config.slathresholds.latency.critical;
  }

  isLatencyWarning(latency: number): boolean {
    return (
      latency > this.config.slathresholds.latency.warning &&
      latency <= this.config.slathresholds.latency.critical
    );
  }

  /**
   * Check if error rate exceeds threshold
   */
  isErrorRateCritical(errorRate: number): boolean {
    return errorRate > this.config.slathresholds.errorRate.critical;
  }

  isErrorRateWarning(errorRate: number): boolean {
    return (
      errorRate > this.config.slathresholds.errorRate.warning &&
      errorRate <= this.config.slathresholds.errorRate.critical
    );
  }

  /**
   * Check if delivery success rate is below threshold
   */
  isEmailDeliveryBelowThreshold(successRate: number): boolean {
    return successRate < this.config.slathresholds.deliverySuccessRate.email;
  }

  isSmsDeliveryBelowThreshold(successRate: number): boolean {
    return successRate < this.config.slathresholds.deliverySuccessRate.sms;
  }

  /**
   * Check if forecast accuracy is below minimum
   */
  isForecastAccuracyLow(accuracy: number): boolean {
    return accuracy < this.config.slathresholds.forecastAccuracy.minimum;
  }

  /**
   * Check if forecast accuracy is degrading
   */
  isForecastAccuracyDegrading(currentAccuracy: number, previousAccuracy: number): boolean {
    const degradation = previousAccuracy - currentAccuracy;
    return degradation > this.config.slathresholds.forecastAccuracy.degradationThreshold;
  }

  /**
   * Get alert severity based on metric
   */
  getLatencySeverity(latency: number): 'low' | 'medium' | 'high' | 'critical' | null {
    if (this.isLatencyCritical(latency)) return 'critical';
    if (this.isLatencyWarning(latency)) return 'medium';
    return null;
  }

  getErrorRateSeverity(errorRate: number): 'low' | 'medium' | 'high' | 'critical' | null {
    if (this.isErrorRateCritical(errorRate)) return 'critical';
    if (this.isErrorRateWarning(errorRate)) return 'medium';
    return null;
  }

  getDeliverySeverity(channel: 'email' | 'sms', successRate: number): 'low' | 'medium' | 'high' | null {
    if (channel === 'email' && this.isEmailDeliveryBelowThreshold(successRate)) return 'high';
    if (channel === 'sms' && this.isSmsDeliveryBelowThreshold(successRate)) return 'high';
    return null;
  }

  getForecastAccuracySeverity(
    accuracy: number,
    previousAccuracy?: number
  ): 'low' | 'medium' | 'high' | null {
    if (this.isForecastAccuracyLow(accuracy)) return 'medium';
    if (previousAccuracy && this.isForecastAccuracyDegrading(accuracy, previousAccuracy)) return 'high';
    return null;
  }

  /**
   * Get notification channels for alert
   */
  getNotificationChannels(alertType: string): ('slack' | 'pagerduty' | 'email')[] {
    const route = this.getAlertRoute(alertType);
    return route?.channels || ['slack'];
  }

  /**
   * Check if alert should be escalated
   */
  shouldEscalate(alertType: string, minutesElapsed: number): boolean {
    const route = this.getAlertRoute(alertType);
    if (!route?.escalationTime) return false;

    return minutesElapsed >= route.escalationTime;
  }

  /**
   * Get all configured thresholds
   */
  getAllConfig(): AlertConfiguration {
    return this.config;
  }

  /**
   * Enable/disable alerting
   */
  setEnabled(enabled: boolean) {
    this.config.enabled = enabled;
    console.log(`[Alert Config] Alerting ${enabled ? 'enabled' : 'disabled'}`);
  }

  /**
   * Check if alerting is enabled
   */
  isEnabled(): boolean {
    return this.config.enabled;
  }

  /**
   * Validate configuration
   */
  validate(): {
    valid: boolean;
    errors: string[];
  } {
    const errors: string[] = [];

    if (!this.config.slathresholds) {
      errors.push('SLA thresholds not configured');
    }

    if (this.config.routes.latency_critical?.channels.includes('pagerduty') && !this.config.pagerdutyKey) {
      errors.push('PagerDuty key required but not configured');
    }

    if (this.config.routes.latency_critical?.channels.includes('slack') && !this.config.slackWebhook) {
      errors.push('Slack webhook required but not configured');
    }

    if (this.config.routes.latency_critical?.channels.includes('email') && !this.config.emailRecipients) {
      errors.push('Email recipients required but not configured');
    }

    return {
      valid: errors.length === 0,
      errors,
    };
  }
}

export const alertConfigService = new AlertConfigService();
