/**
 * Referral Analytics System
 * Comprehensive tracking and analytics for referral program
 */

export interface ReferralMetrics {
  totalReferrals: number;
  completedReferrals: number;
  pendingReferrals: number;
  conversionRate: number; // Percentage
  totalEarnings: number;
  averageEarningsPerReferral: number;
  topReferralSource: string;
}

export interface ReferralSource {
  source: string; // email, whatsapp, facebook, twitter, direct, etc.
  count: number;
  conversionRate: number;
  earnings: number;
}

export interface ReferralTrend {
  date: Date;
  referrals: number;
  earnings: number;
  conversionRate: number;
}

export interface ReferralCohort {
  cohortDate: Date; // Week/Month of referral
  referrals: number;
  activeReferees: number; // Still active players
  retentionRate: number; // Percentage
  totalEarnings: number;
}

export interface ReferralROI {
  totalInvestment: number; // Bonuses paid out
  totalRevenue: number; // From referrals
  roi: number; // Percentage
  paybackPeriod: number; // Days
}

/**
 * Calculate referral metrics
 */
export function calculateReferralMetrics(
  totalReferrals: number,
  completedReferrals: number,
  totalEarnings: number
): ReferralMetrics {
  const conversionRate = totalReferrals > 0 ? (completedReferrals / totalReferrals) * 100 : 0;
  const averageEarningsPerReferral = completedReferrals > 0 ? totalEarnings / completedReferrals : 0;

  return {
    totalReferrals,
    completedReferrals,
    pendingReferrals: totalReferrals - completedReferrals,
    conversionRate: Math.round(conversionRate * 100) / 100,
    totalEarnings,
    averageEarningsPerReferral: Math.round(averageEarningsPerReferral * 100) / 100,
    topReferralSource: '', // Would be calculated from data
  };
}

/**
 * Analyze referral sources
 */
export function analyzeReferralSources(
  referrals: Array<{ source: string; completed: boolean; earnings: number }>
): ReferralSource[] {
  const sourceMap = new Map<string, { count: number; completed: number; earnings: number }>();

  referrals.forEach(ref => {
    const existing = sourceMap.get(ref.source) || { count: 0, completed: 0, earnings: 0 };
    sourceMap.set(ref.source, {
      count: existing.count + 1,
      completed: existing.completed + (ref.completed ? 1 : 0),
      earnings: existing.earnings + ref.earnings,
    });
  });

  return Array.from(sourceMap.entries()).map(([source, data]) => ({
    source,
    count: data.count,
    conversionRate: Math.round((data.completed / data.count) * 100 * 100) / 100,
    earnings: data.earnings,
  }));
}

/**
 * Calculate referral trends over time
 */
export function calculateReferralTrends(
  referrals: Array<{ date: Date; completed: boolean; earnings: number }>,
  intervalDays: number = 7
): ReferralTrend[] {
  const trends: Map<string, { referrals: number; completed: number; earnings: number }> = new Map();

  referrals.forEach(ref => {
    const intervalStart = new Date(ref.date);
    intervalStart.setDate(intervalStart.getDate() - (intervalStart.getDate() % intervalDays));
    const key = intervalStart.toISOString().split('T')[0];

    const existing = trends.get(key) || { referrals: 0, completed: 0, earnings: 0 };
    trends.set(key, {
      referrals: existing.referrals + 1,
      completed: existing.completed + (ref.completed ? 1 : 0),
      earnings: existing.earnings + ref.earnings,
    });
  });

  return Array.from(trends.entries())
    .sort(([dateA], [dateB]) => dateA.localeCompare(dateB))
    .map(([dateStr, data]) => ({
      date: new Date(dateStr),
      referrals: data.referrals,
      earnings: data.earnings,
      conversionRate: Math.round((data.completed / data.referrals) * 100 * 100) / 100,
    }));
}

/**
 * Calculate cohort retention
 */
export function calculateCohortRetention(
  referrals: Array<{ cohortDate: Date; active: boolean }>,
  intervalDays: number = 7
): ReferralCohort[] {
  const cohorts: Map<string, { total: number; active: number }> = new Map();

  referrals.forEach(ref => {
    const cohortStart = new Date(ref.cohortDate);
    cohortStart.setDate(cohortStart.getDate() - (cohortStart.getDate() % intervalDays));
    const key = cohortStart.toISOString().split('T')[0];

    const existing = cohorts.get(key) || { total: 0, active: 0 };
    cohorts.set(key, {
      total: existing.total + 1,
      active: existing.active + (ref.active ? 1 : 0),
    });
  });

  return Array.from(cohorts.entries())
    .sort(([dateA], [dateB]) => dateA.localeCompare(dateB))
    .map(([dateStr, data]) => ({
      cohortDate: new Date(dateStr),
      referrals: data.total,
      activeReferees: data.active,
      retentionRate: Math.round((data.active / data.total) * 100 * 100) / 100,
      totalEarnings: 0, // Would be calculated from data
    }));
}

/**
 * Calculate referral ROI
 */
export function calculateReferralROI(
  totalBonusesPaid: number,
  totalRevenueGenerated: number,
  daysActive: number
): ReferralROI {
  const roi = totalBonusesPaid > 0 ? ((totalRevenueGenerated - totalBonusesPaid) / totalBonusesPaid) * 100 : 0;
  const paybackPeriod = totalRevenueGenerated > 0 ? Math.round((totalBonusesPaid / totalRevenueGenerated) * daysActive) : 0;

  return {
    totalInvestment: totalBonusesPaid,
    totalRevenue: totalRevenueGenerated,
    roi: Math.round(roi * 100) / 100,
    paybackPeriod,
  };
}

/**
 * Get top performing referrers
 */
export function getTopReferrers(
  referrers: Array<{ userId: number; referralCount: number; earnings: number }>,
  limit: number = 10
) {
  return referrers
    .sort((a, b) => b.referralCount - a.referralCount)
    .slice(0, limit)
    .map((referrer, index) => ({
      rank: index + 1,
      userId: referrer.userId,
      referrals: referrer.referralCount,
      earnings: referrer.earnings,
    }));
}

/**
 * Calculate referral velocity
 */
export function calculateReferralVelocity(
  referrals: Array<{ date: Date }>,
  windowDays: number = 7
): number {
  const now = new Date();
  const windowStart = new Date(now);
  windowStart.setDate(windowStart.getDate() - windowDays);

  const recentReferrals = referrals.filter(ref => ref.date >= windowStart);
  return Math.round((recentReferrals.length / windowDays) * 100) / 100;
}

/**
 * Predict referral growth
 */
export function predictReferralGrowth(
  historicalData: Array<{ date: Date; count: number }>,
  daysAhead: number = 30
): Array<{ date: Date; predictedCount: number }> {
  if (historicalData.length < 2) return [];

  // Simple linear regression
  const n = historicalData.length;
  const xValues = historicalData.map((_, i) => i);
  const yValues = historicalData.map(d => d.count);

  const xMean = xValues.reduce((a, b) => a + b) / n;
  const yMean = yValues.reduce((a, b) => a + b) / n;

  const numerator = xValues.reduce((sum, x, i) => sum + (x - xMean) * (yValues[i] - yMean), 0);
  const denominator = xValues.reduce((sum, x) => sum + Math.pow(x - xMean, 2), 0);

  const slope = denominator !== 0 ? numerator / denominator : 0;
  const intercept = yMean - slope * xMean;

  const predictions: Array<{ date: Date; predictedCount: number }> = [];
  const lastDate = historicalData[historicalData.length - 1].date;

  for (let i = 1; i <= daysAhead; i++) {
    const futureDate = new Date(lastDate);
    futureDate.setDate(futureDate.getDate() + i);
    const predictedCount = Math.round(slope * (n + i - 1) + intercept);

    predictions.push({
      date: futureDate,
      predictedCount: Math.max(0, predictedCount),
    });
  }

  return predictions;
}

/**
 * Get referral analytics summary
 */
export function getReferralAnalyticsSummary(
  metrics: ReferralMetrics,
  sources: ReferralSource[],
  roi: ReferralROI
) {
  return {
    metrics,
    topSource: sources.sort((a, b) => b.count - a.count)[0] || null,
    roi,
    health: {
      conversionRate: metrics.conversionRate >= 30 ? 'excellent' : metrics.conversionRate >= 20 ? 'good' : 'needs_improvement',
      roi: roi.roi >= 100 ? 'excellent' : roi.roi >= 50 ? 'good' : 'needs_improvement',
    },
  };
}
