/**
 * Final Systems Tests
 * Comprehensive tests for notification delivery, admin analytics, and chat systems
 */

import { describe, it, expect, beforeEach } from 'vitest';
import {
  createEmailNotification,
  createSMSNotification,
  createWhatsAppNotification,
  markAsDelivered,
  markAsBounced,
  calculateDeliveryStats,
  type EmailNotification,
  type SMSNotification,
  type WhatsAppNotification,
} from './notificationDelivery';
import {
  calculatePlayerMetrics,
  calculateRevenueMetrics,
  calculateGameMetrics,
  calculateFraudMetrics,
  calculateEngagementMetrics,
  generateAdminDashboard,
  detectAnomalies,
  analyzeCohorts,
  generatePerformanceReport,
  type PlayerMetrics,
  type RevenueMetrics,
  type GameMetrics,
} from './adminAnalytics';
import {
  createChatRoom,
  addMemberToChatRoom,
  removeMemberFromChatRoom,
  createChatMessage,
  addMessageToRoom,
  editMessage,
  deleteMessage,
  addReactionToMessage,
  removeReactionFromMessage,
  muteUserInRoom,
  banUserFromRoom,
  calculateChatStats,
  createChatNotification,
  getUnreadNotifications,
  markNotificationAsRead,
  getRoomActivity,
  type ChatRoom,
  type ChatMessage,
} from './chatSystem';

describe('Final Systems', () => {
  describe('Notification Delivery System', () => {
    let emailNotif: EmailNotification;
    let smsNotif: SMSNotification;
    let whatsappNotif: WhatsAppNotification;

    beforeEach(() => {
      emailNotif = createEmailNotification(
        1,
        'user@example.com',
        'Test Subject',
        'Test body',
        '<p>Test HTML</p>'
      );
      smsNotif = createSMSNotification(1, '+1234567890', 'Test SMS message');
      whatsappNotif = createWhatsAppNotification(1, '+1234567890', 'Test WhatsApp message');
    });

    it('should create email notification', () => {
      expect(emailNotif.status).toBe('pending');
      expect(emailNotif.email).toBe('user@example.com');
      expect(emailNotif.retryCount).toBe(0);
    });

    it('should create SMS notification', () => {
      expect(smsNotif.status).toBe('pending');
      expect(smsNotif.phoneNumber).toBe('+1234567890');
      expect(smsNotif.maxRetries).toBe(3);
    });

    it('should create WhatsApp notification', () => {
      expect(whatsappNotif.status).toBe('pending');
      expect(whatsappNotif.phoneNumber).toBe('+1234567890');
    });

    it('should mark notification as delivered', () => {
      markAsDelivered(emailNotif);
      expect(emailNotif.status).toBe('delivered');
      expect(emailNotif.deliveredAt).toBeDefined();
    });

    it('should mark notification as bounced', () => {
      markAsBounced(emailNotif, 'Invalid email address');
      expect(emailNotif.status).toBe('bounced');
      expect(emailNotif.failureReason).toBe('Invalid email address');
    });

    it('should calculate delivery statistics', () => {
      markAsDelivered(emailNotif);
      const smsNotif2 = createSMSNotification(2, '+9876543210', 'Another SMS');
      markAsDelivered(smsNotif2);

      const stats = calculateDeliveryStats([emailNotif], [smsNotif2], []);

      expect(stats.totalSent).toBe(2);
      expect(stats.totalDelivered).toBe(2);
      expect(stats.deliveryRate).toBe(100);
    });
  });

  describe('Admin Analytics System', () => {
    let playerMetrics: PlayerMetrics;
    let revenueMetrics: RevenueMetrics;
    let gameMetrics: GameMetrics;

    beforeEach(() => {
      playerMetrics = calculatePlayerMetrics(
        1000, // totalPlayers
        500, // activePlayers
        50, // newPlayersToday
        200, // newPlayersThisWeek
        500, // newPlayersThisMonth
        100, // churnedPlayers
        5000, // totalSessions
        50000 // totalSessionDuration
      );

      revenueMetrics = calculateRevenueMetrics(
        100000, // totalRevenue
        5000, // dailyRevenue
        35000, // weeklyRevenue
        100000, // monthlyRevenue
        1000, // totalPlayers
        5000, // totalSessions
        50000, // totalDeposits
        10000 // totalWithdrawals
      );

      gameMetrics = calculateGameMetrics(
        'game1',
        'Test Game',
        1000, // totalPlays
        500, // uniquePlayers
        10000, // totalPlayDuration
        50000, // totalWagered
        45000, // totalWon
        400 // playerRetentionCount
      );
    });

    it('should calculate player metrics', () => {
      expect(playerMetrics.totalPlayers).toBe(1000);
      expect(playerMetrics.activePlayers).toBe(500);
      expect(playerMetrics.churnRate).toBe(10);
      expect(playerMetrics.averageSessionDuration).toBeCloseTo(10, 0);
    });

    it('should calculate revenue metrics', () => {
      expect(revenueMetrics.totalRevenue).toBe(100000);
      expect(revenueMetrics.averageRevenuePerUser).toBe(100);
      expect(revenueMetrics.averageRevenuePerSession).toBe(20);
    });

    it('should calculate game metrics', () => {
      expect(gameMetrics.totalPlays).toBe(1000);
      expect(gameMetrics.houseEdge).toBe(10);
      expect(gameMetrics.playerRetentionRate).toBe(80);
    });

    it('should detect anomalies', () => {
      const highChurnMetrics = calculatePlayerMetrics(1000, 500, 50, 200, 500, 200, 5000, 50000);
      const fraudMetrics = calculateFraudMetrics(15, 100, 50, 10, 5, 1000, 5);
      const engagementMetrics = calculateEngagementMetrics(100, 300, 500, 5000, 1000, 500, 200, {});

      const dashboard = generateAdminDashboard(
        highChurnMetrics,
        revenueMetrics,
        [gameMetrics],
        fraudMetrics,
        engagementMetrics,
        [],
        []
      );

      const alerts = detectAnomalies(dashboard);

      expect(alerts.length).toBeGreaterThan(0);
      expect(alerts.some((a) => a.type === 'churn_rate')).toBe(true);
    });

    it('should analyze cohorts', () => {
      const cohort = analyzeCohorts(
        new Date(),
        100, // cohortSize
        90, // day1Retained
        70, // day7Retained
        50, // day30Retained
        5000 // totalLifetimeValue
      );

      expect(cohort.day1Retention).toBe(90);
      expect(cohort.day7Retention).toBe(70);
      expect(cohort.day30Retention).toBe(50);
      expect(cohort.averageLifetimeValue).toBe(50);
    });

    it('should generate performance report', () => {
      const currentDashboard = generateAdminDashboard(
        playerMetrics,
        revenueMetrics,
        [gameMetrics],
        calculateFraudMetrics(5, 50, 20, 2, 2, 1000, 1),
        calculateEngagementMetrics(300, 600, 900, 5000, 1000, 200, 700, {}),
        [],
        []
      );

      const previousDashboard = generateAdminDashboard(
        calculatePlayerMetrics(900, 450, 40, 180, 450, 90, 4500, 45000),
        calculateRevenueMetrics(90000, 4500, 31500, 90000, 900, 4500, 45000, 9000),
        [gameMetrics],
        calculateFraudMetrics(4, 40, 18, 1, 1, 900, 0),
        calculateEngagementMetrics(250, 550, 800, 4500, 900, 150, 630, {}),
        [],
        []
      );

      const report = generatePerformanceReport(currentDashboard, previousDashboard, 'weekly');

      expect(report.period).toBe('weekly');
      expect(report.playerGrowth).toBeGreaterThan(0);
      expect(report.recommendations.length).toBeGreaterThanOrEqual(0);
    });
  });

  describe('Chat System', () => {
    let room: ChatRoom;
    let message1: ChatMessage;
    let message2: ChatMessage;

    beforeEach(() => {
      room = createChatRoom('Tournament Chat', 'tournament', 1);
      message1 = createChatMessage(room.id, 1, 'Player1', 'Hello everyone!');
      message2 = createChatMessage(room.id, 2, 'Player2', 'Hi there!');
    });

    it('should create chat room', () => {
      expect(room.name).toBe('Tournament Chat');
      expect(room.type).toBe('tournament');
      expect(room.members).toContain(1);
    });

    it('should add member to room', () => {
      const success = addMemberToChatRoom(room, 2);
      expect(success).toBe(true);
      expect(room.members).toContain(2);
    });

    it('should prevent duplicate members', () => {
      addMemberToChatRoom(room, 2);
      const success = addMemberToChatRoom(room, 2);
      expect(success).toBe(false);
    });

    it('should remove member from room', () => {
      addMemberToChatRoom(room, 2);
      const success = removeMemberFromChatRoom(room, 2);
      expect(success).toBe(true);
      expect(room.members).not.toContain(2);
    });

    it('should add message to room', () => {
      addMemberToChatRoom(room, 2);
      const success = addMessageToRoom(room, message1);
      expect(success).toBe(true);
      expect(room.messages).toContain(message1);
    });

    it('should prevent messages from non-members', () => {
      const success = addMessageToRoom(room, message2);
      expect(success).toBe(false);
    });

    it('should edit message', () => {
      addMessageToRoom(room, message1);
      editMessage(message1, 'Updated message');
      expect(message1.content).toBe('Updated message');
      expect(message1.edited).toBe(true);
    });

    it('should delete message', () => {
      addMessageToRoom(room, message1);
      const success = deleteMessage(room, message1.id);
      expect(success).toBe(true);
      expect(room.messages).not.toContain(message1);
    });

    it('should add reaction to message', () => {
      addReactionToMessage(message1, '👍');
      addReactionToMessage(message1, '👍');
      addReactionToMessage(message1, '❤️');

      expect(message1.reactions['👍']).toBe(2);
      expect(message1.reactions['❤️']).toBe(1);
    });

    it('should remove reaction from message', () => {
      addReactionToMessage(message1, '👍');
      addReactionToMessage(message1, '👍');
      removeReactionFromMessage(message1, '👍');

      expect(message1.reactions['👍']).toBe(1);
    });

    it('should mute user in room', () => {
      addMemberToChatRoom(room, 2);
      muteUserInRoom(room, 2);
      expect(room.moderation.mutedUsers).toContain(2);
    });

    it('should ban user from room', () => {
      addMemberToChatRoom(room, 2);
      banUserFromRoom(room, 2);
      expect(room.moderation.bannedUsers).toContain(2);
      expect(room.members).not.toContain(2);
    });

    it('should calculate chat statistics', () => {
      addMemberToChatRoom(room, 2);
      addMessageToRoom(room, message1);
      addMessageToRoom(room, message2);

      const stats = calculateChatStats(room);

      expect(stats.totalMessages).toBe(2);
      expect(stats.activeUsers).toBe(2);
      expect(stats.topUsers.length).toBe(2);
    });

    it('should create chat notification', () => {
      const notif = createChatNotification(
        1,
        'mention',
        2,
        'Player2',
        room.id,
        message2.id,
        'You were mentioned'
      );

      expect(notif.type).toBe('mention');
      expect(notif.fromUsername).toBe('Player2');
      expect(notif.read).toBe(false);
    });

    it('should get unread notifications', () => {
      const notif1 = createChatNotification(1, 'mention', 2, 'Player2', room.id, message2.id, 'Mention');
      const notif2 = createChatNotification(1, 'reply', 3, 'Player3', room.id, message1.id, 'Reply');

      const unread = getUnreadNotifications([notif1, notif2], 1);
      expect(unread.length).toBe(2);

      markNotificationAsRead(notif1);
      const unreadAfter = getUnreadNotifications([notif1, notif2], 1);
      expect(unreadAfter.length).toBe(1);
    });

    it('should get room activity', () => {
      addMemberToChatRoom(room, 2);
      addMessageToRoom(room, message1);
      addMessageToRoom(room, message2);

      const activity = getRoomActivity(room);

      expect(activity.roomId).toBe(room.id);
      expect(activity.activeMembers).toBe(2);
      expect(activity.messagesLastHour).toBe(2);
    });
  });

  describe('Cross-System Integration', () => {
    it('should send notifications for chat events', () => {
      const room = createChatRoom('Tournament', 'tournament', 1);
      const message = createChatMessage(room.id, 2, 'Player2', '@Player1 Check this out!');

      const notification = createChatNotification(
        1,
        'mention',
        2,
        'Player2',
        room.id,
        message.id,
        'You were mentioned'
      );

      expect(notification.type).toBe('mention');
      expect(notification.read).toBe(false);
    });

    it('should track chat analytics in admin dashboard', () => {
      const room = createChatRoom('Tournament', 'tournament', 1);
      addMemberToChatRoom(room, 2);
      addMemberToChatRoom(room, 3);

      for (let i = 0; i < 10; i++) {
        const msg = createChatMessage(room.id, (i % 3) + 1, `Player${(i % 3) + 1}`, `Message ${i}`);
        addMessageToRoom(room, msg);
      }

      const stats = calculateChatStats(room);
      expect(stats.totalMessages).toBe(10);
      expect(stats.activeUsers).toBe(3);
      expect(stats.topUsers.length).toBeGreaterThan(0);
    });
  });
});
