import { EventEmitter } from 'events';

export type SharePlatform = 'twitter' | 'facebook' | 'discord' | 'link' | 'image';
export type ShareableType = 'achievement' | 'score' | 'milestone' | 'tournament';

export interface ShareEvent {
  userId: string;
  shareableId: string;
  shareableType: ShareableType;
  platform: SharePlatform;
  timestamp: Date;
  clickCount?: number;
  impressions?: number;
}

export interface ShareMetrics {
  totalShares: number;
  uniqueUsers: number;
  platformBreakdown: Record<SharePlatform, number>;
  typeBreakdown: Record<ShareableType, number>;
  averageSharesPerUser: number;
  topSharedItems: Array<{
    id: string;
    type: ShareableType;
    shares: number;
    platforms: Record<SharePlatform, number>;
  }>;
}

export interface ShareCard {
  id: string;
  title: string;
  description: string;
  icon: string;
  backgroundColor: string;
  shareText: string;
  imageUrl?: string;
}

class SocialSharingAnalytics extends EventEmitter {
  private shareEvents: ShareEvent[] = [];
  private shareCards: Map<string, ShareCard> = new Map();
  private clickTracking: Map<string, number> = new Map();
  private impressionTracking: Map<string, number> = new Map();

  /**
   * Record a share event
   */
  recordShare(event: ShareEvent): void {
    this.shareEvents.push({
      ...event,
      timestamp: new Date(),
      clickCount: 0,
      impressions: 0,
    });

    this.emit('share-recorded', event);
  }

  /**
   * Track clicks on shared content
   */
  trackClick(shareableId: string, platform: SharePlatform): void {
    const key = `${shareableId}-${platform}`;
    this.clickTracking.set(key, (this.clickTracking.get(key) || 0) + 1);

    this.emit('click-tracked', { shareableId, platform, timestamp: new Date() });
  }

  /**
   * Track impressions of shared content
   */
  trackImpression(shareableId: string, platform: SharePlatform): void {
    const key = `${shareableId}-${platform}`;
    this.impressionTracking.set(key, (this.impressionTracking.get(key) || 0) + 1);

    this.emit('impression-tracked', { shareableId, platform, timestamp: new Date() });
  }

  /**
   * Get overall sharing metrics
   */
  getMetrics(): ShareMetrics {
    const platformBreakdown: Record<SharePlatform, number> = {
      twitter: 0,
      facebook: 0,
      discord: 0,
      link: 0,
      image: 0,
    };

    const typeBreakdown: Record<ShareableType, number> = {
      achievement: 0,
      score: 0,
      milestone: 0,
      tournament: 0,
    };

    const uniqueUsers = new Set<string>();
    const itemShares: Map<
      string,
      { type: ShareableType; shares: number; platforms: Record<SharePlatform, number> }
    > = new Map();

    for (const event of this.shareEvents) {
      platformBreakdown[event.platform]++;
      typeBreakdown[event.shareableType]++;
      uniqueUsers.add(event.userId);

      const key = event.shareableId;
      if (!itemShares.has(key)) {
        itemShares.set(key, {
          type: event.shareableType,
          shares: 0,
          platforms: {
            twitter: 0,
            facebook: 0,
            discord: 0,
            link: 0,
            image: 0,
          },
        });
      }

      const item = itemShares.get(key)!;
      item.shares++;
      item.platforms[event.platform]++;
    }

    const topSharedItems = Array.from(itemShares.entries())
      .map(([id, data]) => ({
        id,
        ...data,
      }))
      .sort((a, b) => b.shares - a.shares)
      .slice(0, 10);

    return {
      totalShares: this.shareEvents.length,
      uniqueUsers: uniqueUsers.size,
      platformBreakdown,
      typeBreakdown,
      averageSharesPerUser: uniqueUsers.size > 0 ? this.shareEvents.length / uniqueUsers.size : 0,
      topSharedItems,
    };
  }

  /**
   * Get user sharing statistics
   */
  getUserShareStats(userId: string): {
    totalShares: number;
    platformBreakdown: Record<SharePlatform, number>;
    typeBreakdown: Record<ShareableType, number>;
    mostSharedItem?: string;
  } {
    const userEvents = this.shareEvents.filter(e => e.userId === userId);

    const platformBreakdown: Record<SharePlatform, number> = {
      twitter: 0,
      facebook: 0,
      discord: 0,
      link: 0,
      image: 0,
    };

    const typeBreakdown: Record<ShareableType, number> = {
      achievement: 0,
      score: 0,
      milestone: 0,
      tournament: 0,
    };

    const itemCounts: Map<string, number> = new Map();

    for (const event of userEvents) {
      platformBreakdown[event.platform]++;
      typeBreakdown[event.shareableType]++;
      itemCounts.set(event.shareableId, (itemCounts.get(event.shareableId) || 0) + 1);
    }

    let mostSharedItem: string | undefined;
    let maxCount = 0;
    for (const [id, count] of itemCounts.entries()) {
      if (count > maxCount) {
        maxCount = count;
        mostSharedItem = id;
      }
    }

    return {
      totalShares: userEvents.length,
      platformBreakdown,
      typeBreakdown,
      mostSharedItem,
    };
  }

  /**
   * Get platform-specific metrics
   */
  getPlatformMetrics(platform: SharePlatform): {
    totalShares: number;
    uniqueUsers: number;
    typeBreakdown: Record<ShareableType, number>;
    topItems: Array<{ id: string; shares: number }>;
  } {
    const platformEvents = this.shareEvents.filter(e => e.platform === platform);
    const uniqueUsers = new Set(platformEvents.map(e => e.userId));

    const typeBreakdown: Record<ShareableType, number> = {
      achievement: 0,
      score: 0,
      milestone: 0,
      tournament: 0,
    };

    const itemCounts: Map<string, number> = new Map();

    for (const event of platformEvents) {
      typeBreakdown[event.shareableType]++;
      itemCounts.set(event.shareableId, (itemCounts.get(event.shareableId) || 0) + 1);
    }

    const topItems = Array.from(itemCounts.entries())
      .map(([id, shares]) => ({ id, shares }))
      .sort((a, b) => b.shares - a.shares)
      .slice(0, 10);

    return {
      totalShares: platformEvents.length,
      uniqueUsers: uniqueUsers.size,
      typeBreakdown,
      topItems,
    };
  }

  /**
   * Get engagement metrics (clicks and impressions)
   */
  getEngagementMetrics(): {
    totalClicks: number;
    totalImpressions: number;
    clickThroughRate: number;
    topClickedItems: Array<{ id: string; clicks: number; impressions: number; ctr: number }>;
  } {
    let totalClicks = 0;
    let totalImpressions = 0;

    const itemMetrics: Map<
      string,
      { clicks: number; impressions: number }
    > = new Map();

    for (const [key, clicks] of this.clickTracking.entries()) {
      const [id] = key.split('-');
      totalClicks += clicks;
      if (!itemMetrics.has(id)) {
        itemMetrics.set(id, { clicks: 0, impressions: 0 });
      }
      itemMetrics.get(id)!.clicks += clicks;
    }

    for (const [key, impressions] of this.impressionTracking.entries()) {
      const [id] = key.split('-');
      totalImpressions += impressions;
      if (!itemMetrics.has(id)) {
        itemMetrics.set(id, { clicks: 0, impressions: 0 });
      }
      itemMetrics.get(id)!.impressions += impressions;
    }

    const topClickedItems = Array.from(itemMetrics.entries())
      .map(([id, data]) => ({
        id,
        clicks: data.clicks,
        impressions: data.impressions,
        ctr: data.impressions > 0 ? (data.clicks / data.impressions) * 100 : 0,
      }))
      .sort((a, b) => b.clicks - a.clicks)
      .slice(0, 10);

    return {
      totalClicks,
      totalImpressions,
      clickThroughRate: totalImpressions > 0 ? (totalClicks / totalImpressions) * 100 : 0,
      topClickedItems,
    };
  }

  /**
   * Register a share card template
   */
  registerShareCard(card: ShareCard): void {
    this.shareCards.set(card.id, card);
    this.emit('card-registered', card);
  }

  /**
   * Get share card template
   */
  getShareCard(cardId: string): ShareCard | undefined {
    return this.shareCards.get(cardId);
  }

  /**
   * Get all share card templates
   */
  getAllShareCards(): ShareCard[] {
    return Array.from(this.shareCards.values());
  }

  /**
   * Get trending shares (most shared in last 24 hours)
   */
  getTrendingShares(hours: number = 24): Array<{
    id: string;
    type: ShareableType;
    shares: number;
    platforms: Record<SharePlatform, number>;
  }> {
    const cutoffTime = Date.now() - hours * 60 * 60 * 1000;
    const recentEvents = this.shareEvents.filter(e => e.timestamp.getTime() > cutoffTime);

    const itemShares: Map<
      string,
      { type: ShareableType; shares: number; platforms: Record<SharePlatform, number> }
    > = new Map();

    for (const event of recentEvents) {
      const key = event.shareableId;
      if (!itemShares.has(key)) {
        itemShares.set(key, {
          type: event.shareableType,
          shares: 0,
          platforms: {
            twitter: 0,
            facebook: 0,
            discord: 0,
            link: 0,
            image: 0,
          },
        });
      }

      const item = itemShares.get(key)!;
      item.shares++;
      item.platforms[event.platform]++;
    }

    return Array.from(itemShares.entries())
      .map(([id, data]) => ({
        id,
        ...data,
      }))
      .sort((a, b) => b.shares - a.shares)
      .slice(0, 10);
  }

  /**
   * Clear all data (for testing)
   */
  clear(): void {
    this.shareEvents = [];
    this.shareCards.clear();
    this.clickTracking.clear();
    this.impressionTracking.clear();
  }
}

export const socialSharingAnalytics = new SocialSharingAnalytics();
