/**
 * Revenue Forecasting Service
 * Provides AI-powered revenue predictions using ML models
 */

export interface RevenueForecast {
  forecastDate: Date;
  actualRevenue?: number;
  forecastedRevenue: number;
  confidenceHigh: number;
  confidenceLow: number;
  confidenceLevel: number;
  modelType: 'ml' | 'arima' | 'exponential';
  accuracy: number;
  trend: 'up' | 'down' | 'stable';
}

export interface RevenueMetrics {
  source: string;
  revenue: number;
  percentage: number;
  forecast: number;
}

export interface ForecastInsight {
  insightType: string;
  title: string;
  description: string;
  recommendation: string;
  priority: 'low' | 'medium' | 'high' | 'critical';
}

// Mock historical data for forecasting
const historicalData: Array<{ date: Date; revenue: number }> = [];

// Initialize with mock historical data
for (let i = 90; i >= 0; i--) {
  const date = new Date();
  date.setDate(date.getDate() - i);
  const baseRevenue = 850000;
  const seasonalFactor = 1 + Math.sin(i / 30) * 0.2;
  const noise = (Math.random() - 0.5) * 100000;
  const revenue = baseRevenue * seasonalFactor + noise;
  historicalData.push({ date, revenue: Math.max(0, revenue) });
}

/**
 * Generate revenue forecast for specified period
 */
export async function generateRevenueForecast(
  modelType: 'ml' | 'arima' | 'exponential' = 'ml',
  daysAhead: number = 30
): Promise<RevenueForecast[]> {
  const forecasts: RevenueForecast[] = [];
  
  // Calculate base forecast using selected model
  const baseForecasts = calculateBaseForecasts(modelType, daysAhead);
  
  for (let i = 0; i < daysAhead; i++) {
    const forecastDate = new Date();
    forecastDate.setDate(forecastDate.getDate() + i + 1);
    
    const baseRevenue = baseForecasts[i];
    const confidenceInterval = calculateConfidenceInterval(baseRevenue, modelType);
    
    // Determine trend
    let trend: 'up' | 'down' | 'stable' = 'stable';
    if (i > 0) {
      const change = (baseRevenue - baseForecasts[i - 1]) / baseForecasts[i - 1];
      if (change > 0.05) trend = 'up';
      else if (change < -0.05) trend = 'down';
    }
    
    forecasts.push({
      forecastDate,
      forecastedRevenue: baseRevenue,
      confidenceHigh: confidenceInterval.high,
      confidenceLow: confidenceInterval.low,
      confidenceLevel: 95,
      modelType,
      accuracy: calculateModelAccuracy(modelType),
      trend,
    });
  }
  
  return forecasts;
}

/**
 * Calculate base forecasts using specified model
 */
function calculateBaseForecasts(
  modelType: 'ml' | 'arima' | 'exponential',
  daysAhead: number
): number[] {
  const forecasts: number[] = [];
  
  if (modelType === 'ml') {
    // Simple ML-like forecast using trend and seasonality
    const trend = calculateTrend();
    const seasonality = calculateSeasonality();
    const lastRevenue = historicalData[historicalData.length - 1].revenue;
    
    for (let i = 0; i < daysAhead; i++) {
      const dayOfYear = (new Date().getDate() + i) % 365;
      const seasonal = seasonality[dayOfYear % seasonality.length];
      const forecast = lastRevenue * (1 + trend) * seasonal;
      forecasts.push(forecast);
    }
  } else if (modelType === 'arima') {
    // ARIMA-like forecast
    const lastRevenue = historicalData[historicalData.length - 1].revenue;
    const avgChange = calculateAverageChange();
    
    for (let i = 0; i < daysAhead; i++) {
      const forecast = lastRevenue + (avgChange * (i + 1));
      forecasts.push(Math.max(0, forecast));
    }
  } else {
    // Exponential smoothing
    const alpha = 0.3;
    let lastForecast = historicalData[historicalData.length - 1].revenue;
    
    for (let i = 0; i < daysAhead; i++) {
      const forecast = alpha * lastForecast + (1 - alpha) * historicalData[historicalData.length - 1].revenue;
      forecasts.push(forecast);
      lastForecast = forecast;
    }
  }
  
  return forecasts;
}

/**
 * Calculate confidence interval for forecast
 */
function calculateConfidenceInterval(
  forecast: number,
  modelType: string
): { high: number; low: number } {
  // 95% confidence interval
  const stdDev = forecast * 0.1; // Assume 10% standard deviation
  const zScore = 1.96; // 95% confidence
  const margin = stdDev * zScore;
  
  return {
    high: forecast + margin,
    low: Math.max(0, forecast - margin),
  };
}

/**
 * Calculate model accuracy based on historical performance
 */
function calculateModelAccuracy(modelType: string): number {
  // Mock accuracy scores
  const accuracies: Record<string, number> = {
    ml: 87,
    arima: 82,
    exponential: 79,
  };
  
  return accuracies[modelType] || 80;
}

/**
 * Calculate trend from historical data
 */
function calculateTrend(): number {
  if (historicalData.length < 2) return 0;
  
  const recent = historicalData.slice(-7);
  const older = historicalData.slice(-14, -7);
  
  const recentAvg = recent.reduce((sum, d) => sum + d.revenue, 0) / recent.length;
  const olderAvg = older.reduce((sum, d) => sum + d.revenue, 0) / older.length;
  
  return (recentAvg - olderAvg) / olderAvg;
}

/**
 * Calculate seasonality factors
 */
function calculateSeasonality(): number[] {
  const factors: number[] = [];
  
  for (let i = 0; i < 365; i++) {
    // Simple sine wave seasonality
    const factor = 1 + Math.sin((i / 365) * Math.PI * 2) * 0.15;
    factors.push(factor);
  }
  
  return factors;
}

/**
 * Calculate average daily change
 */
function calculateAverageChange(): number {
  if (historicalData.length < 2) return 0;
  
  let totalChange = 0;
  for (let i = 1; i < historicalData.length; i++) {
    totalChange += historicalData[i].revenue - historicalData[i - 1].revenue;
  }
  
  return totalChange / (historicalData.length - 1);
}

/**
 * Get revenue breakdown by source
 */
export async function getRevenueBySource(): Promise<RevenueMetrics[]> {
  const sources = [
    { name: 'Slot Games', percentage: 45 },
    { name: 'Bingo', percentage: 28 },
    { name: 'Poker', percentage: 12 },
    { name: 'Sports Betting', percentage: 8 },
    { name: 'Mini Games', percentage: 7 },
  ];
  
  const totalRevenue = 920000; // Current monthly revenue
  
  return sources.map((source) => ({
    source: source.name,
    revenue: (totalRevenue * source.percentage) / 100,
    percentage: source.percentage,
    forecast: ((totalRevenue * 1.082) * source.percentage) / 100, // 8.2% growth forecast
  }));
}

/**
 * Generate AI insights from forecast
 */
export async function generateForecastInsights(): Promise<ForecastInsight[]> {
  const insights: ForecastInsight[] = [
    {
      insightType: 'opportunity',
      title: 'Slot Games Opportunity',
      description: 'Slot games are trending up. Consider promoting new slot releases to capitalize on this momentum.',
      recommendation: 'Launch 2-3 new slot games this month and run targeted email campaigns to high-value players.',
      priority: 'high',
    },
    {
      insightType: 'growth',
      title: 'Strong Growth Trajectory',
      description: 'Revenue is forecasted to grow 8.2% month-over-month. Maintain current marketing spend and optimize conversion funnels.',
      recommendation: 'Increase marketing budget by 10% and focus on retention campaigns for dormant players.',
      priority: 'high',
    },
    {
      insightType: 'alert',
      title: 'Bingo Plateau Alert',
      description: 'Bingo revenue is plateauing. Consider launching new bingo room themes or tournaments to re-engage players.',
      recommendation: 'Create 3 new themed bingo rooms and launch weekly bingo tournaments with progressive jackpots.',
      priority: 'medium',
    },
    {
      insightType: 'impact',
      title: 'Retention Campaign Impact',
      description: 'Dormant player reactivation campaigns are expected to add $45K+ revenue. Increase campaign frequency.',
      recommendation: 'Run retention campaigns every 2 weeks instead of monthly to maximize reactivation.',
      priority: 'high',
    },
  ];
  
  return insights;
}

/**
 * Retrain forecast model with new data
 */
export async function retrainForecastModel(
  modelType: 'ml' | 'arima' | 'exponential'
): Promise<{ success: boolean; message: string; accuracy: number }> {
  // In production, this would retrain the ML model with latest data
  const newAccuracy = calculateModelAccuracy(modelType) + Math.random() * 2;
  
  return {
    success: true,
    message: `Model ${modelType} retrained successfully with ${historicalData.length} data points`,
    accuracy: Math.min(newAccuracy, 95),
  };
}

/**
 * Add actual revenue data for comparison
 */
export async function recordActualRevenue(date: Date, revenue: number): Promise<void> {
  // In production, this would update the database
  historicalData.push({ date, revenue });
}

/**
 * Get forecast accuracy metrics
 */
export async function getForecastAccuracyMetrics(): Promise<{
  modelType: string;
  accuracy: number;
  mape: number;
  rmse: number;
  lastUpdated: Date;
}> {
  return {
    modelType: 'ml',
    accuracy: 87,
    mape: 8.5, // Mean Absolute Percentage Error
    rmse: 45000, // Root Mean Square Error
    lastUpdated: new Date(),
  };
}

/**
 * Compare forecast models
 */
export async function compareModels(): Promise<
  Array<{
    modelType: string;
    accuracy: number;
    rmse: number;
    trainingTime: number;
    recommendedFor: string;
  }>
> {
  return [
    {
      modelType: 'ml',
      accuracy: 87,
      rmse: 45000,
      trainingTime: 120,
      recommendedFor: 'Best overall performance',
    },
    {
      modelType: 'arima',
      accuracy: 82,
      rmse: 58000,
      trainingTime: 60,
      recommendedFor: 'Fast training, good for trending data',
    },
    {
      modelType: 'exponential',
      accuracy: 79,
      rmse: 72000,
      trainingTime: 30,
      recommendedFor: 'Fastest training, good for stable data',
    },
  ];
}
