import { EventEmitter } from 'events';

export interface PopupAnnouncement {
  id: string;
  title: string;
  content: string;
  type: 'info' | 'warning' | 'success' | 'error';
  imageUrl?: string;
  ctaText?: string;
  ctaUrl?: string;
  createdAt: Date;
  expiresAt?: Date;
  targetAudience?: 'all' | 'new_players' | 'vip' | 'inactive';
}

export interface UserPopupState {
  userId: string;
  announcementId: string;
  viewed: boolean;
  viewedAt?: Date;
}

class OneTimePopupService extends EventEmitter {
  private announcements: Map<string, PopupAnnouncement> = new Map();
  private userStates: Map<string, UserPopupState[]> = new Map();

  constructor() {
    super();
    this.initializeDefaultAnnouncements();
  }

  /**
   * Initialize with default announcements
   */
  private initializeDefaultAnnouncements(): void {
    // Add welcome announcement
    this.announcements.set('welcome-001', {
      id: 'welcome-001',
      title: 'Welcome to CoinKrazy!',
      content: 'Enjoy 700+ slot games, tournaments, and exclusive rewards. Start spinning and earning Sweeps Coins today!',
      type: 'success',
      targetAudience: 'new_players',
      createdAt: new Date(),
    });

    // Add feature announcement
    this.announcements.set('feature-001', {
      id: 'feature-001',
      title: 'New Feature: Push Notifications',
      content: 'Stay updated with real-time notifications for wins, tournaments, and rewards. Enable browser notifications in settings.',
      type: 'info',
      targetAudience: 'all',
      createdAt: new Date(),
    });
  }

  /**
   * Create a new announcement
   */
  createAnnouncement(announcement: Omit<PopupAnnouncement, 'id' | 'createdAt'>): PopupAnnouncement {
    const id = `announcement-${Date.now()}`;
    const newAnnouncement: PopupAnnouncement = {
      ...announcement,
      id,
      createdAt: new Date(),
    };

    this.announcements.set(id, newAnnouncement);
    this.emit('announcement_created', newAnnouncement);

    return newAnnouncement;
  }

  /**
   * Get current active announcement for user
   */
  getActiveAnnouncement(userId: string, userTier?: string): PopupAnnouncement | null {
    const userStates = this.userStates.get(userId) || [];
    const viewedIds = new Set(userStates.filter((s) => s.viewed).map((s) => s.announcementId));

    for (const [, announcement] of this.announcements) {
      // Skip if already viewed
      if (viewedIds.has(announcement.id)) {
        continue;
      }

      // Check if expired
      if (announcement.expiresAt && announcement.expiresAt < new Date()) {
        continue;
      }

      // Check audience targeting
      if (announcement.targetAudience === 'vip' && userTier !== 'vip') {
        continue;
      }

      return announcement;
    }

    return null;
  }

  /**
   * Mark announcement as viewed by user
   */
  markAsViewed(userId: string, announcementId: string): boolean {
    const userStates = this.userStates.get(userId) || [];
    const existingState = userStates.find((s) => s.announcementId === announcementId);

    if (existingState) {
      existingState.viewed = true;
      existingState.viewedAt = new Date();
    } else {
      userStates.push({
        userId,
        announcementId,
        viewed: true,
        viewedAt: new Date(),
      });
    }

    this.userStates.set(userId, userStates);
    this.emit('announcement_viewed', { userId, announcementId });

    return true;
  }

  /**
   * Get all announcements (admin)
   */
  getAllAnnouncements(): PopupAnnouncement[] {
    return Array.from(this.announcements.values()).sort(
      (a, b) => b.createdAt.getTime() - a.createdAt.getTime()
    );
  }

  /**
   * Update announcement
   */
  updateAnnouncement(id: string, updates: Partial<PopupAnnouncement>): PopupAnnouncement | null {
    const announcement = this.announcements.get(id);
    if (!announcement) {
      return null;
    }

    const updated = { ...announcement, ...updates, id, createdAt: announcement.createdAt };
    this.announcements.set(id, updated);

    // Reset all user views when announcement is updated
    for (const [userId, states] of this.userStates) {
      const userState = states.find((s) => s.announcementId === id);
      if (userState) {
        userState.viewed = false;
        userState.viewedAt = undefined;
      }
    }

    this.emit('announcement_updated', updated);

    return updated;
  }

  /**
   * Delete announcement
   */
  deleteAnnouncement(id: string): boolean {
    const deleted = this.announcements.delete(id);

    if (deleted) {
      // Clean up user states
      for (const [, states] of this.userStates) {
        const index = states.findIndex((s) => s.announcementId === id);
        if (index !== -1) {
          states.splice(index, 1);
        }
      }

      this.emit('announcement_deleted', id);
    }

    return deleted;
  }

  /**
   * Get user's view history
   */
  getUserViewHistory(userId: string): UserPopupState[] {
    return this.userStates.get(userId) || [];
  }

  /**
   * Get announcement statistics
   */
  getStatistics(): {
    totalAnnouncements: number;
    activeAnnouncements: number;
    totalViews: number;
    viewsByAnnouncement: Record<string, number>;
  } {
    const now = new Date();
    const activeAnnouncements = Array.from(this.announcements.values()).filter(
      (a) => !a.expiresAt || a.expiresAt > now
    );

    let totalViews = 0;
    const viewsByAnnouncement: Record<string, number> = {};

    for (const states of this.userStates.values()) {
      for (const state of states) {
        if (state.viewed) {
          totalViews++;
          viewsByAnnouncement[state.announcementId] =
            (viewsByAnnouncement[state.announcementId] || 0) + 1;
        }
      }
    }

    return {
      totalAnnouncements: this.announcements.size,
      activeAnnouncements: activeAnnouncements.length,
      totalViews,
      viewsByAnnouncement,
    };
  }

  /**
   * Clear old viewed announcements
   */
  clearOldAnnouncements(daysOld: number = 30): number {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - daysOld);

    let deleted = 0;

    for (const [id, announcement] of this.announcements) {
      if (announcement.createdAt < cutoffDate) {
        this.deleteAnnouncement(id);
        deleted++;
      }
    }

    return deleted;
  }
}

// Export singleton instance
export const oneTimePopupService = new OneTimePopupService();

export default OneTimePopupService;
