/**
 * Game Performance Alerts Service
 * Monitors game metrics and triggers alerts for performance issues
 */

export interface GameAlert {
  id: string;
  gameId: number;
  gameName: string;
  alertType: 'engagement_decline' | 'rtp_drift' | 'churn_rate' | 'low_plays' | 'high_variance';
  severity: 'low' | 'medium' | 'high' | 'critical';
  message: string;
  metric: string;
  currentValue: number;
  threshold: number;
  createdAt: Date;
  resolvedAt?: Date;
  status: 'active' | 'acknowledged' | 'resolved';
}

export interface GameMetrics {
  gameId: number;
  gameName: string;
  playCount: number;
  playCountChange: number; // percentage change from last period
  avgBet: number;
  totalWins: number;
  totalLosses: number;
  rtp: number;
  rtpChange: number; // percentage change from expected
  churnRate: number; // percentage of players who stopped playing
  playerRetention: number; // percentage of players who returned
  avgSessionLength: number; // in minutes
  lastUpdated: Date;
}

// In-memory alert storage
const alerts = new Map<string, GameAlert>();
const gameMetrics = new Map<number, GameMetrics>();

const ALERT_THRESHOLDS = {
  engagement_decline: -20, // 20% decline
  rtp_drift: 5, // 5% drift from expected
  churn_rate: 30, // 30% churn
  low_plays: 100, // less than 100 plays in period
  high_variance: 15, // 15% variance
};

export async function checkGameMetrics(metrics: GameMetrics): Promise<GameAlert[]> {
  const triggeredAlerts: GameAlert[] = [];

  // Check engagement decline
  if (metrics.playCountChange < ALERT_THRESHOLDS.engagement_decline) {
    triggeredAlerts.push(createAlert(
      metrics.gameId,
      metrics.gameName,
      'engagement_decline',
      'high',
      `Game engagement declined by ${Math.abs(metrics.playCountChange)}%`,
      'playCountChange',
      metrics.playCountChange,
      ALERT_THRESHOLDS.engagement_decline
    ));
  }

  // Check RTP drift
  if (Math.abs(metrics.rtpChange) > ALERT_THRESHOLDS.rtp_drift) {
    triggeredAlerts.push(createAlert(
      metrics.gameId,
      metrics.gameName,
      'rtp_drift',
      'medium',
      `Game RTP drifted by ${metrics.rtpChange}% from expected`,
      'rtpChange',
      metrics.rtpChange,
      ALERT_THRESHOLDS.rtp_drift
    ));
  }

  // Check churn rate
  if (metrics.churnRate > ALERT_THRESHOLDS.churn_rate) {
    triggeredAlerts.push(createAlert(
      metrics.gameId,
      metrics.gameName,
      'churn_rate',
      'critical',
      `High churn rate detected: ${metrics.churnRate}% of players stopped playing`,
      'churnRate',
      metrics.churnRate,
      ALERT_THRESHOLDS.churn_rate
    ));
  }

  // Check low plays
  if (metrics.playCount < ALERT_THRESHOLDS.low_plays) {
    triggeredAlerts.push(createAlert(
      metrics.gameId,
      metrics.gameName,
      'low_plays',
      'low',
      `Game has low play count: ${metrics.playCount} plays`,
      'playCount',
      metrics.playCount,
      ALERT_THRESHOLDS.low_plays
    ));
  }

  // Store metrics
  gameMetrics.set(metrics.gameId, metrics);

  // Store triggered alerts
  for (const alert of triggeredAlerts) {
    alerts.set(alert.id, alert);
  }

  return triggeredAlerts;
}

function createAlert(
  gameId: number,
  gameName: string,
  type: GameAlert['alertType'],
  severity: GameAlert['severity'],
  message: string,
  metric: string,
  currentValue: number,
  threshold: number
): GameAlert {
  return {
    id: `alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
    gameId,
    gameName,
    alertType: type,
    severity,
    message,
    metric,
    currentValue,
    threshold,
    createdAt: new Date(),
    status: 'active',
  };
}

export async function getActiveAlerts(severity?: string): Promise<GameAlert[]> {
  const allAlerts = Array.from(alerts.values()).filter((a) => a.status === 'active');

  if (severity) {
    return allAlerts.filter((a) => a.severity === severity);
  }

  return allAlerts;
}

export async function getGameAlerts(gameId: number): Promise<GameAlert[]> {
  return Array.from(alerts.values()).filter((a) => a.gameId === gameId);
}

export async function acknowledgeAlert(alertId: string): Promise<GameAlert> {
  const alert = alerts.get(alertId);
  if (!alert) throw new Error('Alert not found');

  alert.status = 'acknowledged';
  alerts.set(alertId, alert);
  return alert;
}

export async function resolveAlert(alertId: string): Promise<GameAlert> {
  const alert = alerts.get(alertId);
  if (!alert) throw new Error('Alert not found');

  alert.status = 'resolved';
  alert.resolvedAt = new Date();
  alerts.set(alertId, alert);
  return alert;
}

export async function getAlertStats(): Promise<{
  totalActive: number;
  critical: number;
  high: number;
  medium: number;
  low: number;
  byType: Record<string, number>;
}> {
  const activeAlerts = Array.from(alerts.values()).filter((a) => a.status === 'active');

  const stats = {
    totalActive: activeAlerts.length,
    critical: activeAlerts.filter((a) => a.severity === 'critical').length,
    high: activeAlerts.filter((a) => a.severity === 'high').length,
    medium: activeAlerts.filter((a) => a.severity === 'medium').length,
    low: activeAlerts.filter((a) => a.severity === 'low').length,
    byType: {} as Record<string, number>,
  };

  for (const alert of activeAlerts) {
    stats.byType[alert.alertType] = (stats.byType[alert.alertType] || 0) + 1;
  }

  return stats;
}

export async function getGameMetrics(gameId: number): Promise<GameMetrics | null> {
  return gameMetrics.get(gameId) || null;
}

export async function getTopPerformingGames(limit = 10): Promise<GameMetrics[]> {
  return Array.from(gameMetrics.values())
    .sort((a, b) => b.playCount - a.playCount)
    .slice(0, limit);
}

export async function getBottomPerformingGames(limit = 10): Promise<GameMetrics[]> {
  return Array.from(gameMetrics.values())
    .sort((a, b) => a.playCount - b.playCount)
    .slice(0, limit);
}

export async function getHighRiskGames(): Promise<GameMetrics[]> {
  return Array.from(gameMetrics.values()).filter(
    (m) =>
      m.playCountChange < ALERT_THRESHOLDS.engagement_decline ||
      Math.abs(m.rtpChange) > ALERT_THRESHOLDS.rtp_drift ||
      m.churnRate > ALERT_THRESHOLDS.churn_rate
  );
}
