import { EventEmitter } from 'events';

export type UserSegment = 'all' | 'new_players' | 'vip' | 'inactive' | 'high_spenders' | 'tournament_players';

export interface PushCampaign {
  id: string;
  title: string;
  message: string;
  imageUrl?: string;
  ctaText?: string;
  ctaUrl?: string;
  segment: UserSegment;
  scheduledFor?: Date;
  sentAt?: Date;
  status: 'draft' | 'scheduled' | 'sent' | 'paused' | 'cancelled';
  totalRecipients: number;
  sentCount: number;
  deliveredCount: number;
  openedCount: number;
  clickedCount: number;
  createdAt: Date;
  updatedAt: Date;
  createdBy: string;
}

export interface CampaignTemplate {
  id: string;
  name: string;
  title: string;
  message: string;
  imageUrl?: string;
  ctaText?: string;
  ctaUrl?: string;
  category: 'promotion' | 'announcement' | 'event' | 'reward' | 'engagement';
  createdAt: Date;
}

class PushNotificationCampaignsService extends EventEmitter {
  private campaigns: Map<string, PushCampaign> = new Map();
  private templates: Map<string, CampaignTemplate> = new Map();
  private segmentUserCounts: Map<UserSegment, number> = new Map([
    ['all', 10000],
    ['new_players', 2500],
    ['vip', 500],
    ['inactive', 3000],
    ['high_spenders', 800],
    ['tournament_players', 1200],
  ]);

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

  /**
   * Initialize with default templates
   */
  private initializeDefaultTemplates(): void {
    const templates: CampaignTemplate[] = [
      {
        id: 'template-1',
        name: 'Welcome New Player',
        title: 'Welcome to CoinKrazy!',
        message: 'Get started with 100 free Sweeps Coins and spin our top games. Your first win is just one spin away!',
        category: 'promotion',
        createdAt: new Date(),
      },
      {
        id: 'template-2',
        name: 'Tournament Announcement',
        title: 'New Tournament Live!',
        message: 'Join our latest tournament and compete for massive prize pools. Limited spots available!',
        category: 'event',
        createdAt: new Date(),
      },
      {
        id: 'template-3',
        name: 'VIP Exclusive Offer',
        title: 'VIP Exclusive: 50% Bonus',
        message: 'As a VIP member, enjoy 50% bonus on your next deposit. Offer valid for 24 hours!',
        category: 'promotion',
        createdAt: new Date(),
      },
      {
        id: 'template-4',
        name: 'Win Celebration',
        title: 'You Won Big!',
        message: 'Congratulations on your recent win! Keep the momentum going and play more games.',
        category: 'engagement',
        createdAt: new Date(),
      },
      {
        id: 'template-5',
        name: 'Comeback Offer',
        title: 'We Miss You!',
        message: 'Come back and enjoy 25% bonus on your next game. We have new games waiting for you!',
        category: 'engagement',
        createdAt: new Date(),
      },
    ];

    for (const template of templates) {
      this.templates.set(template.id, template);
    }
  }

  /**
   * Create a new campaign
   */
  createCampaign(
    title: string,
    message: string,
    segment: UserSegment,
    userId: string,
    options?: {
      imageUrl?: string;
      ctaText?: string;
      ctaUrl?: string;
      scheduledFor?: Date;
    }
  ): PushCampaign {
    const id = `campaign-${Date.now()}`;
    const totalRecipients = this.segmentUserCounts.get(segment) || 0;

    const campaign: PushCampaign = {
      id,
      title,
      message,
      imageUrl: options?.imageUrl,
      ctaText: options?.ctaText,
      ctaUrl: options?.ctaUrl,
      segment,
      scheduledFor: options?.scheduledFor,
      status: options?.scheduledFor ? 'scheduled' : 'draft',
      totalRecipients,
      sentCount: 0,
      deliveredCount: 0,
      openedCount: 0,
      clickedCount: 0,
      createdAt: new Date(),
      updatedAt: new Date(),
      createdBy: userId,
    };

    this.campaigns.set(id, campaign);
    this.emit('campaign_created', campaign);

    return campaign;
  }

  /**
   * Send campaign immediately
   */
  sendCampaign(campaignId: string): PushCampaign | null {
    const campaign = this.campaigns.get(campaignId);
    if (!campaign) {
      return null;
    }

    if (campaign.status !== 'draft' && campaign.status !== 'scheduled') {
      throw new Error('Campaign cannot be sent in current status');
    }

    campaign.status = 'sent';
    campaign.sentAt = new Date();
    campaign.sentCount = campaign.totalRecipients;
    campaign.updatedAt = new Date();

    this.emit('campaign_sent', campaign);

    return campaign;
  }

  /**
   * Schedule campaign for later
   */
  scheduleCampaign(campaignId: string, scheduledFor: Date): PushCampaign | null {
    const campaign = this.campaigns.get(campaignId);
    if (!campaign) {
      return null;
    }

    if (campaign.status !== 'draft') {
      throw new Error('Only draft campaigns can be scheduled');
    }

    campaign.scheduledFor = scheduledFor;
    campaign.status = 'scheduled';
    campaign.updatedAt = new Date();

    this.emit('campaign_scheduled', campaign);

    return campaign;
  }

  /**
   * Pause campaign
   */
  pauseCampaign(campaignId: string): PushCampaign | null {
    const campaign = this.campaigns.get(campaignId);
    if (!campaign) {
      return null;
    }

    if (campaign.status !== 'sent') {
      throw new Error('Only sent campaigns can be paused');
    }

    campaign.status = 'paused';
    campaign.updatedAt = new Date();

    this.emit('campaign_paused', campaign);

    return campaign;
  }

  /**
   * Resume campaign
   */
  resumeCampaign(campaignId: string): PushCampaign | null {
    const campaign = this.campaigns.get(campaignId);
    if (!campaign) {
      return null;
    }

    if (campaign.status !== 'paused') {
      throw new Error('Only paused campaigns can be resumed');
    }

    campaign.status = 'sent';
    campaign.updatedAt = new Date();

    this.emit('campaign_resumed', campaign);

    return campaign;
  }

  /**
   * Cancel campaign
   */
  cancelCampaign(campaignId: string): PushCampaign | null {
    const campaign = this.campaigns.get(campaignId);
    if (!campaign) {
      return null;
    }

    if (campaign.status === 'sent' && campaign.sentCount > 0) {
      throw new Error('Cannot cancel a campaign that has already been sent');
    }

    campaign.status = 'cancelled';
    campaign.updatedAt = new Date();

    this.emit('campaign_cancelled', campaign);

    return campaign;
  }

  /**
   * Update campaign
   */
  updateCampaign(campaignId: string, updates: Partial<PushCampaign>): PushCampaign | null {
    const campaign = this.campaigns.get(campaignId);
    if (!campaign) {
      return null;
    }

    if (campaign.status !== 'draft') {
      throw new Error('Only draft campaigns can be updated');
    }

    Object.assign(campaign, updates, { updatedAt: new Date() });

    this.emit('campaign_updated', campaign);

    return campaign;
  }

  /**
   * Get campaign by ID
   */
  getCampaign(campaignId: string): PushCampaign | null {
    return this.campaigns.get(campaignId) || null;
  }

  /**
   * Get all campaigns
   */
  getAllCampaigns(): PushCampaign[] {
    return Array.from(this.campaigns.values()).sort(
      (a, b) => b.createdAt.getTime() - a.createdAt.getTime()
    );
  }

  /**
   * Get campaigns by status
   */
  getCampaignsByStatus(status: PushCampaign['status']): PushCampaign[] {
    return Array.from(this.campaigns.values())
      .filter((c) => c.status === status)
      .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
  }

  /**
   * Get templates
   */
  getTemplates(): CampaignTemplate[] {
    return Array.from(this.templates.values());
  }

  /**
   * Get template by ID
   */
  getTemplate(templateId: string): CampaignTemplate | null {
    return this.templates.get(templateId) || null;
  }

  /**
   * Create template
   */
  createTemplate(
    name: string,
    title: string,
    message: string,
    category: CampaignTemplate['category'],
    options?: {
      imageUrl?: string;
      ctaText?: string;
      ctaUrl?: string;
    }
  ): CampaignTemplate {
    const id = `template-${Date.now()}`;
    const template: CampaignTemplate = {
      id,
      name,
      title,
      message,
      imageUrl: options?.imageUrl,
      ctaText: options?.ctaText,
      ctaUrl: options?.ctaUrl,
      category,
      createdAt: new Date(),
    };

    this.templates.set(id, template);
    this.emit('template_created', template);

    return template;
  }

  /**
   * Get segment user count
   */
  getSegmentUserCount(segment: UserSegment): number {
    return this.segmentUserCounts.get(segment) || 0;
  }

  /**
   * Get campaign statistics
   */
  getCampaignStatistics(campaignId: string): {
    totalRecipients: number;
    sentCount: number;
    deliveryRate: number;
    openRate: number;
    clickRate: number;
  } | null {
    const campaign = this.campaigns.get(campaignId);
    if (!campaign) {
      return null;
    }

    return {
      totalRecipients: campaign.totalRecipients,
      sentCount: campaign.sentCount,
      deliveryRate: campaign.sentCount > 0 ? (campaign.deliveredCount / campaign.sentCount) * 100 : 0,
      openRate: campaign.sentCount > 0 ? (campaign.openedCount / campaign.sentCount) * 100 : 0,
      clickRate: campaign.sentCount > 0 ? (campaign.clickedCount / campaign.sentCount) * 100 : 0,
    };
  }

  /**
   * Get all campaigns statistics
   */
  getAllCampaignsStatistics(): {
    totalCampaigns: number;
    totalSent: number;
    totalDelivered: number;
    totalOpened: number;
    totalClicked: number;
    averageDeliveryRate: number;
    averageOpenRate: number;
    averageClickRate: number;
  } {
    const campaigns = Array.from(this.campaigns.values());
    const sentCampaigns = campaigns.filter((c) => c.status === 'sent');

    let totalSent = 0;
    let totalDelivered = 0;
    let totalOpened = 0;
    let totalClicked = 0;

    for (const campaign of sentCampaigns) {
      totalSent += campaign.sentCount;
      totalDelivered += campaign.deliveredCount;
      totalOpened += campaign.openedCount;
      totalClicked += campaign.clickedCount;
    }

    return {
      totalCampaigns: campaigns.length,
      totalSent,
      totalDelivered,
      totalOpened,
      totalClicked,
      averageDeliveryRate: totalSent > 0 ? (totalDelivered / totalSent) * 100 : 0,
      averageOpenRate: totalSent > 0 ? (totalOpened / totalSent) * 100 : 0,
      averageClickRate: totalSent > 0 ? (totalClicked / totalSent) * 100 : 0,
    };
  }
}

// Export singleton instance
export const pushNotificationCampaignsService = new PushNotificationCampaignsService();

export default PushNotificationCampaignsService;
