/**
 * Affiliate System
 * Manages affiliate programs, tracking, and payouts
 */

export type AffiliateStatus = 'pending' | 'active' | 'suspended' | 'inactive';
export type CommissionType = 'percentage' | 'fixed' | 'tiered';

export interface AffiliateAccount {
  id: string;
  userId: number;
  username: string;
  email: string;
  status: AffiliateStatus;
  commissionType: CommissionType;
  commissionRate: number;
  bankAccount?: {
    accountHolder: string;
    accountNumber: string;
    routingNumber: string;
    bankName: string;
  };
  paymentMethod: 'bank_transfer' | 'paypal' | 'crypto' | 'check';
  createdAt: Date;
  approvedAt?: Date;
  suspendedAt?: Date;
  totalReferrals: number;
  totalEarnings: number;
  pendingEarnings: number;
  lastPayoutDate?: Date;
  nextPayoutDate?: Date;
  tier: AffiliateTier;
}

export type AffiliateTier = 'bronze' | 'silver' | 'gold' | 'platinum' | 'diamond';

export interface AffiliateReferral {
  id: string;
  affiliateId: string;
  referredUserId: number;
  referralCode: string;
  referralLink: string;
  status: 'pending' | 'active' | 'converted' | 'churned';
  createdAt: Date;
  convertedAt?: Date;
  firstDepositAmount?: number;
  firstDepositDate?: Date;
  totalReferredSpend: number;
  commission: number;
  commissionPaid: boolean;
  payoutId?: string;
}

export interface AffiliateCommission {
  id: string;
  affiliateId: string;
  referralId: string;
  amount: number;
  rate: number;
  type: CommissionType;
  status: 'pending' | 'approved' | 'paid' | 'reversed';
  createdAt: Date;
  approvedAt?: Date;
  paidAt?: Date;
  payoutId?: string;
}

export interface AffiliatePayout {
  id: string;
  affiliateId: string;
  amount: number;
  status: 'pending' | 'processing' | 'completed' | 'failed';
  paymentMethod: string;
  commissionIds: string[];
  createdAt: Date;
  processedAt?: Date;
  completedAt?: Date;
  failureReason?: string;
  transactionId?: string;
}

export interface AffiliateStats {
  totalReferrals: number;
  activeReferrals: number;
  convertedReferrals: number;
  conversionRate: number;
  totalSpendReferred: number;
  totalEarnings: number;
  pendingEarnings: number;
  averageCommissionPerReferral: number;
  monthlyEarnings: number;
  topPerformingGame: string;
  topPerformingCountry: string;
}

export interface AffiliatePerformance {
  period: 'daily' | 'weekly' | 'monthly';
  referrals: number;
  conversions: number;
  earnings: number;
  topReferrals: AffiliateReferral[];
}

/**
 * Affiliate tier configurations
 */
export const AFFILIATE_TIERS: Record<AffiliateTier, {
  minReferrals: number;
  commissionRate: number;
  bonus: number;
  payoutFrequency: number; // days
}> = {
  bronze: {
    minReferrals: 0,
    commissionRate: 20,
    bonus: 0,
    payoutFrequency: 30,
  },
  silver: {
    minReferrals: 10,
    commissionRate: 25,
    bonus: 50,
    payoutFrequency: 14,
  },
  gold: {
    minReferrals: 50,
    commissionRate: 30,
    bonus: 200,
    payoutFrequency: 7,
  },
  platinum: {
    minReferrals: 100,
    commissionRate: 35,
    bonus: 500,
    payoutFrequency: 7,
  },
  diamond: {
    minReferrals: 250,
    commissionRate: 40,
    bonus: 1000,
    payoutFrequency: 3,
  },
};

/**
 * Create affiliate account
 */
export function createAffiliateAccount(
  userId: number,
  username: string,
  email: string,
  paymentMethod: string
): AffiliateAccount {
  return {
    id: `aff_${userId}_${Date.now()}`,
    userId,
    username,
    email,
    status: 'pending',
    commissionType: 'percentage',
    commissionRate: AFFILIATE_TIERS.bronze.commissionRate,
    paymentMethod: paymentMethod as any,
    createdAt: new Date(),
    totalReferrals: 0,
    totalEarnings: 0,
    pendingEarnings: 0,
    tier: 'bronze',
  };
}

/**
 * Generate referral code
 */
export function generateReferralCode(affiliateId: string): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  let code = '';
  for (let i = 0; i < 8; i++) {
    code += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return `${code}`;
}

/**
 * Create referral
 */
export function createReferral(
  affiliateId: string,
  referredUserId: number,
  baseUrl: string
): AffiliateReferral {
  const referralCode = generateReferralCode(affiliateId);

  return {
    id: `ref_${affiliateId}_${referredUserId}_${Date.now()}`,
    affiliateId,
    referredUserId,
    referralCode,
    referralLink: `${baseUrl}?ref=${referralCode}`,
    status: 'pending',
    createdAt: new Date(),
    totalReferredSpend: 0,
    commission: 0,
    commissionPaid: false,
  };
}

/**
 * Convert referral
 */
export function convertReferral(
  referral: AffiliateReferral,
  firstDepositAmount: number,
  affiliate: AffiliateAccount
): void {
  referral.status = 'converted';
  referral.convertedAt = new Date();
  referral.firstDepositAmount = firstDepositAmount;
  referral.firstDepositDate = new Date();
  referral.totalReferredSpend = firstDepositAmount;

  // Calculate commission
  const commission = (firstDepositAmount * affiliate.commissionRate) / 100;
  referral.commission = commission;

  // Update affiliate stats
  affiliate.totalReferrals++;
  affiliate.pendingEarnings += commission;
}

/**
 * Update referral spend
 */
export function updateReferralSpend(
  referral: AffiliateReferral,
  spendAmount: number,
  affiliate: AffiliateAccount
): void {
  const previousSpend = referral.totalReferredSpend;
  referral.totalReferredSpend += spendAmount;

  // Recalculate commission on total spend
  const newCommission = (referral.totalReferredSpend * affiliate.commissionRate) / 100;
  const commissionDifference = newCommission - referral.commission;

  referral.commission = newCommission;
  affiliate.pendingEarnings += commissionDifference;
}

/**
 * Get affiliate tier based on referrals
 */
export function getAffiliateTier(totalReferrals: number): AffiliateTier {
  if (totalReferrals >= 250) return 'diamond';
  if (totalReferrals >= 100) return 'platinum';
  if (totalReferrals >= 50) return 'gold';
  if (totalReferrals >= 10) return 'silver';
  return 'bronze';
}

/**
 * Update affiliate tier
 */
export function updateAffiliateTier(affiliate: AffiliateAccount): void {
  const newTier = getAffiliateTier(affiliate.totalReferrals);

  if (newTier !== affiliate.tier) {
    const tierConfig = AFFILIATE_TIERS[newTier];
    affiliate.tier = newTier;
    affiliate.commissionRate = tierConfig.commissionRate;

    // Add tier bonus
    if (tierConfig.bonus > 0) {
      affiliate.pendingEarnings += tierConfig.bonus;
    }
  }
}

/**
 * Create payout
 */
export function createPayout(
  affiliate: AffiliateAccount,
  commissionIds: string[],
  totalAmount: number
): AffiliatePayout {
  return {
    id: `payout_${affiliate.id}_${Date.now()}`,
    affiliateId: affiliate.id,
    amount: totalAmount,
    status: 'pending',
    paymentMethod: affiliate.paymentMethod,
    commissionIds,
    createdAt: new Date(),
  };
}

/**
 * Process payout
 */
export function processPayout(payout: AffiliatePayout, affiliate: AffiliateAccount): void {
  payout.status = 'processing';
  payout.processedAt = new Date();

  // Update affiliate
  affiliate.pendingEarnings -= payout.amount;
  affiliate.totalEarnings += payout.amount;
  affiliate.lastPayoutDate = new Date();

  // Calculate next payout date
  const tierConfig = AFFILIATE_TIERS[affiliate.tier];
  affiliate.nextPayoutDate = new Date(Date.now() + tierConfig.payoutFrequency * 24 * 60 * 60 * 1000);
}

/**
 * Complete payout
 */
export function completePayout(payout: AffiliatePayout, transactionId: string): void {
  payout.status = 'completed';
  payout.completedAt = new Date();
  payout.transactionId = transactionId;
}

/**
 * Calculate affiliate statistics
 */
export function calculateAffiliateStats(
  affiliate: AffiliateAccount,
  referrals: AffiliateReferral[]
): AffiliateStats {
  const activeReferrals = referrals.filter((r) => r.status === 'active').length;
  const convertedReferrals = referrals.filter((r) => r.status === 'converted').length;
  const totalSpendReferred = referrals.reduce((sum, r) => sum + r.totalReferredSpend, 0);

  return {
    totalReferrals: affiliate.totalReferrals,
    activeReferrals,
    convertedReferrals,
    conversionRate: affiliate.totalReferrals > 0 ? (convertedReferrals / affiliate.totalReferrals) * 100 : 0,
    totalSpendReferred,
    totalEarnings: affiliate.totalEarnings,
    pendingEarnings: affiliate.pendingEarnings,
    averageCommissionPerReferral: affiliate.totalReferrals > 0 ? affiliate.totalEarnings / affiliate.totalReferrals : 0,
    monthlyEarnings: 0, // Would need historical data
    topPerformingGame: '', // Would need game tracking
    topPerformingCountry: '', // Would need location tracking
  };
}

/**
 * Get top affiliates
 */
export function getTopAffiliates(
  affiliates: AffiliateAccount[],
  limit: number = 10
): AffiliateAccount[] {
  return affiliates
    .filter((a) => a.status === 'active')
    .sort((a, b) => b.totalEarnings - a.totalEarnings)
    .slice(0, limit);
}

/**
 * Get affiliate performance
 */
export function getAffiliatePerformance(
  affiliate: AffiliateAccount,
  referrals: AffiliateReferral[],
  period: 'daily' | 'weekly' | 'monthly'
): AffiliatePerformance {
  const now = new Date();
  let startDate: Date;

  if (period === 'daily') {
    startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000);
  } else if (period === 'weekly') {
    startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
  } else {
    startDate = new Date(now.getFullYear(), now.getMonth(), 1);
  }

  const periodReferrals = referrals.filter((r) => r.createdAt >= startDate);
  const conversions = periodReferrals.filter((r) => r.status === 'converted').length;
  const earnings = periodReferrals.reduce((sum, r) => sum + r.commission, 0);

  return {
    period,
    referrals: periodReferrals.length,
    conversions,
    earnings,
    topReferrals: periodReferrals
      .sort((a, b) => b.commission - a.commission)
      .slice(0, 5),
  };
}

/**
 * Generate affiliate report
 */
export interface AffiliateReport {
  affiliateId: string;
  username: string;
  tier: AffiliateTier;
  status: AffiliateStatus;
  totalReferrals: number;
  totalEarnings: number;
  pendingEarnings: number;
  stats: AffiliateStats;
  performance: {
    daily: AffiliatePerformance;
    weekly: AffiliatePerformance;
    monthly: AffiliatePerformance;
  };
}

export function generateAffiliateReport(
  affiliate: AffiliateAccount,
  referrals: AffiliateReferral[]
): AffiliateReport {
  const stats = calculateAffiliateStats(affiliate, referrals);

  return {
    affiliateId: affiliate.id,
    username: affiliate.username,
    tier: affiliate.tier,
    status: affiliate.status,
    totalReferrals: affiliate.totalReferrals,
    totalEarnings: affiliate.totalEarnings,
    pendingEarnings: affiliate.pendingEarnings,
    stats,
    performance: {
      daily: getAffiliatePerformance(affiliate, referrals, 'daily'),
      weekly: getAffiliatePerformance(affiliate, referrals, 'weekly'),
      monthly: getAffiliatePerformance(affiliate, referrals, 'monthly'),
    },
  };
}
