/**
 * Push Notification System
 * Manages real-time notifications for prizes, tier promotions, bonuses, and tournaments
 */

export type NotificationType = 
  | 'prize_won'
  | 'tier_promotion'
  | 'bonus_triggered'
  | 'tournament_started'
  | 'tournament_ended'
  | 'leaderboard_rank_change'
  | 'referral_accepted'
  | 'daily_bonus'
  | 'milestone_reached'
  | 'maintenance';

export type NotificationPriority = 'low' | 'normal' | 'high' | 'urgent';

export interface PushNotification {
  id: string;
  userId: number;
  type: NotificationType;
  title: string;
  body: string;
  priority: NotificationPriority;
  data: Record<string, any>;
  imageUrl?: string;
  actionUrl?: string;
  sentAt: Date;
  readAt?: Date;
  deliveredAt?: Date;
  failedAt?: Date;
  retryCount: number;
  maxRetries: number;
}

export interface NotificationPreferences {
  userId: number;
  prizeNotifications: boolean;
  tierPromotionNotifications: boolean;
  bonusNotifications: boolean;
  tournamentNotifications: boolean;
  leaderboardNotifications: boolean;
  referralNotifications: boolean;
  dailyBonusNotifications: boolean;
  quietHours: {
    enabled: boolean;
    startTime: string; // HH:mm
    endTime: string;   // HH:mm
  };
  pushEnabled: boolean;
  emailEnabled: boolean;
  smsEnabled: boolean;
}

/**
 * Create push notification
 */
export function createPushNotification(
  userId: number,
  type: NotificationType,
  title: string,
  body: string,
  data: Record<string, any>,
  priority: NotificationPriority = 'normal',
  imageUrl?: string,
  actionUrl?: string
): PushNotification {
  return {
    id: `notif_${userId}_${type}_${Date.now()}`,
    userId,
    type,
    title,
    body,
    priority,
    data,
    imageUrl,
    actionUrl,
    sentAt: new Date(),
    retryCount: 0,
    maxRetries: 3,
  };
}

/**
 * Prize won notification
 */
export function createPrizeNotification(
  userId: number,
  amount: number,
  rank: number,
  gameId: string
): PushNotification {
  return createPushNotification(
    userId,
    'prize_won',
    `🏆 Prize Won!`,
    `Congratulations! You won $${amount} for rank #${rank}`,
    {
      amount,
      rank,
      gameId,
      type: 'prize_won',
    },
    'high',
    undefined,
    `/leaderboard/${gameId}`
  );
}

/**
 * Tier promotion notification
 */
export function createTierPromotionNotification(
  userId: number,
  newTier: string,
  benefits: string[]
): PushNotification {
  return createPushNotification(
    userId,
    'tier_promotion',
    `🎉 VIP Tier Promotion!`,
    `You've been promoted to ${newTier}! Unlock new benefits.`,
    {
      newTier,
      benefits,
      type: 'tier_promotion',
    },
    'high',
    undefined,
    `/vip`
  );
}

/**
 * Bonus triggered notification
 */
export function createBonusNotification(
  userId: number,
  bonusType: string,
  multiplier: number,
  gameId: string
): PushNotification {
  return createPushNotification(
    userId,
    'bonus_triggered',
    `🎁 Bonus Triggered!`,
    `${bonusType} bonus with ${multiplier}x multiplier!`,
    {
      bonusType,
      multiplier,
      gameId,
      type: 'bonus_triggered',
    },
    'high',
    undefined,
    `/games/${gameId}`
  );
}

/**
 * Tournament started notification
 */
export function createTournamentStartedNotification(
  userId: number,
  tournamentName: string,
  prizePool: number,
  tournamentId: string
): PushNotification {
  return createPushNotification(
    userId,
    'tournament_started',
    `🏁 Tournament Started!`,
    `${tournamentName} has started with $${prizePool} prize pool`,
    {
      tournamentName,
      prizePool,
      tournamentId,
      type: 'tournament_started',
    },
    'normal',
    undefined,
    `/tournaments/${tournamentId}`
  );
}

/**
 * Tournament ended notification
 */
export function createTournamentEndedNotification(
  userId: number,
  tournamentName: string,
  rank: number,
  prize: number,
  tournamentId: string
): PushNotification {
  return createPushNotification(
    userId,
    'tournament_ended',
    `🏆 Tournament Ended!`,
    `You finished rank #${rank} and won $${prize}!`,
    {
      tournamentName,
      rank,
      prize,
      tournamentId,
      type: 'tournament_ended',
    },
    'high',
    undefined,
    `/tournaments/${tournamentId}`
  );
}

/**
 * Leaderboard rank change notification
 */
export function createLeaderboardNotification(
  userId: number,
  gameId: string,
  oldRank: number,
  newRank: number
): PushNotification {
  const isRankUp = newRank < oldRank;
  const emoji = isRankUp ? '📈' : '📉';

  return createPushNotification(
    userId,
    'leaderboard_rank_change',
    `${emoji} Leaderboard Update`,
    `Your rank changed from #${oldRank} to #${newRank}`,
    {
      gameId,
      oldRank,
      newRank,
      isRankUp,
      type: 'leaderboard_rank_change',
    },
    isRankUp ? 'normal' : 'low',
    undefined,
    `/leaderboard/${gameId}`
  );
}

/**
 * Referral accepted notification
 */
export function createReferralNotification(
  userId: number,
  referreeName: string,
  commission: number
): PushNotification {
  return createPushNotification(
    userId,
    'referral_accepted',
    `💰 Referral Accepted!`,
    `${referreeName} joined! You earned $${commission} commission`,
    {
      referreeName,
      commission,
      type: 'referral_accepted',
    },
    'high',
    undefined,
    `/referrals`
  );
}

/**
 * Daily bonus notification
 */
export function createDailyBonusNotification(
  userId: number,
  bonusAmount: number,
  streak: number
): PushNotification {
  return createPushNotification(
    userId,
    'daily_bonus',
    `🎁 Daily Bonus Available!`,
    `Claim your $${bonusAmount} bonus! Streak: ${streak} days`,
    {
      bonusAmount,
      streak,
      type: 'daily_bonus',
    },
    'normal',
    undefined,
    `/daily-bonus`
  );
}

/**
 * Milestone reached notification
 */
export function createMilestoneNotification(
  userId: number,
  milestone: string,
  reward: number
): PushNotification {
  return createPushNotification(
    userId,
    'milestone_reached',
    `🎯 Milestone Reached!`,
    `${milestone}! You earned $${reward}`,
    {
      milestone,
      reward,
      type: 'milestone_reached',
    },
    'normal',
    undefined,
    `/achievements`
  );
}

/**
 * Create default notification preferences
 */
export function createDefaultPreferences(userId: number): NotificationPreferences {
  return {
    userId,
    prizeNotifications: true,
    tierPromotionNotifications: true,
    bonusNotifications: true,
    tournamentNotifications: true,
    leaderboardNotifications: true,
    referralNotifications: true,
    dailyBonusNotifications: true,
    quietHours: {
      enabled: false,
      startTime: '22:00',
      endTime: '08:00',
    },
    pushEnabled: true,
    emailEnabled: false,
    smsEnabled: false,
  };
}

/**
 * Check if notification should be sent based on preferences and quiet hours
 */
export function shouldSendNotification(
  preferences: NotificationPreferences,
  notificationType: NotificationType,
  priority: NotificationPriority
): boolean {
  // Always send urgent notifications
  if (priority === 'urgent') {
    return true;
  }

  // Check type-specific preferences
  switch (notificationType) {
    case 'prize_won':
      return preferences.prizeNotifications;
    case 'tier_promotion':
      return preferences.tierPromotionNotifications;
    case 'bonus_triggered':
      return preferences.bonusNotifications;
    case 'tournament_started':
    case 'tournament_ended':
      return preferences.tournamentNotifications;
    case 'leaderboard_rank_change':
      return preferences.leaderboardNotifications;
    case 'referral_accepted':
      return preferences.referralNotifications;
    case 'daily_bonus':
      return preferences.dailyBonusNotifications;
    default:
      return true;
  }
}

/**
 * Check if current time is within quiet hours
 */
export function isInQuietHours(preferences: NotificationPreferences): boolean {
  if (!preferences.quietHours.enabled) {
    return false;
  }

  const now = new Date();
  const currentTime = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;

  const startTime = preferences.quietHours.startTime;
  const endTime = preferences.quietHours.endTime;

  if (startTime < endTime) {
    return currentTime >= startTime && currentTime < endTime;
  } else {
    return currentTime >= startTime || currentTime < endTime;
  }
}

/**
 * Mark notification as read
 */
export function markNotificationAsRead(notification: PushNotification): void {
  notification.readAt = new Date();
}

/**
 * Mark notification as delivered
 */
export function markNotificationAsDelivered(notification: PushNotification): void {
  notification.deliveredAt = new Date();
}

/**
 * Mark notification as failed and increment retry count
 */
export function markNotificationAsFailed(notification: PushNotification): boolean {
  notification.retryCount++;
  if (notification.retryCount >= notification.maxRetries) {
    notification.failedAt = new Date();
    return false;
  }
  return true;
}

/**
 * Notification statistics
 */
export interface NotificationStats {
  totalSent: number;
  totalDelivered: number;
  totalRead: number;
  totalFailed: number;
  deliveryRate: number;
  readRate: number;
  byType: Record<NotificationType, number>;
}

export function calculateNotificationStats(notifications: PushNotification[]): NotificationStats {
  const stats: NotificationStats = {
    totalSent: notifications.length,
    totalDelivered: notifications.filter((n) => n.deliveredAt).length,
    totalRead: notifications.filter((n) => n.readAt).length,
    totalFailed: notifications.filter((n) => n.failedAt).length,
    deliveryRate: 0,
    readRate: 0,
    byType: {} as Record<NotificationType, number>,
  };

  if (stats.totalSent > 0) {
    stats.deliveryRate = (stats.totalDelivered / stats.totalSent) * 100;
    stats.readRate = (stats.totalRead / stats.totalDelivered) * 100;
  }

  // Count by type
  notifications.forEach((n) => {
    stats.byType[n.type] = (stats.byType[n.type] || 0) + 1;
  });

  return stats;
}

/**
 * Get unread notifications for user
 */
export function getUnreadNotifications(notifications: PushNotification[], userId: number): PushNotification[] {
  return notifications.filter((n) => n.userId === userId && !n.readAt);
}

/**
 * Get notification history for user
 */
export function getNotificationHistory(
  notifications: PushNotification[],
  userId: number,
  limit: number = 50
): PushNotification[] {
  return notifications
    .filter((n) => n.userId === userId)
    .sort((a, b) => b.sentAt.getTime() - a.sentAt.getTime())
    .slice(0, limit);
}
