import { describe, it, expect, beforeEach } from 'vitest';
import * as retentionService from './retentionCampaignService.ts';

describe('Retention Campaign Service', () => {
  describe('getSegmentPlayers', () => {
    it('should return players for a given segment', async () => {
      const players = await retentionService.getSegmentPlayers('dormant', 10);
      
      expect(players).toBeDefined();
      expect(Array.isArray(players)).toBe(true);
      expect(players.length).toBeLessThanOrEqual(10);
      
      if (players.length > 0) {
        const player = players[0];
        expect(player).toHaveProperty('userId');
        expect(player).toHaveProperty('email');
        expect(player).toHaveProperty('phone');
        expect(player).toHaveProperty('lastActivityDate');
        expect(player).toHaveProperty('lifetimeValue');
        expect(player).toHaveProperty('preferredChannel');
      }
    });

    it('should respect limit parameter', async () => {
      const players = await retentionService.getSegmentPlayers('vip', 5);
      expect(players.length).toBeLessThanOrEqual(5);
    });
  });

  describe('calculateCampaignMetrics', () => {
    it('should calculate correct metrics', async () => {
      const metrics = await retentionService.calculateCampaignMetrics(
        1,
        1000, // sent
        500,  // opened
        250,  // clicked
        100,  // converted
        5000  // revenue
      );

      expect(metrics.openRate).toBe(50); // 500/1000 * 100
      expect(metrics.clickRate).toBe(25); // 250/1000 * 100
      expect(metrics.conversionRate).toBe(10); // 100/1000 * 100
      expect(metrics.revenuePerSent).toBe(5); // 5000/1000
      expect(metrics.roi).toBeGreaterThan(0);
    });

    it('should handle zero sent', async () => {
      const metrics = await retentionService.calculateCampaignMetrics(1, 0, 0, 0, 0, 0);
      
      expect(metrics.openRate).toBe(NaN);
      expect(metrics.clickRate).toBe(NaN);
      expect(metrics.conversionRate).toBe(NaN);
    });
  });

  describe('getCampaignPerformanceByChannel', () => {
    it('should return performance metrics for each channel', async () => {
      const performance = await retentionService.getCampaignPerformanceByChannel(1);

      expect(Array.isArray(performance)).toBe(true);
      expect(performance.length).toBeGreaterThan(0);

      performance.forEach((channel) => {
        expect(channel).toHaveProperty('channel');
        expect(channel).toHaveProperty('sent');
        expect(channel).toHaveProperty('opened');
        expect(channel).toHaveProperty('clicked');
        expect(channel).toHaveProperty('converted');
        expect(channel).toHaveProperty('openRate');
        expect(channel).toHaveProperty('clickRate');
        expect(channel).toHaveProperty('conversionRate');

        // Verify rates are percentages
        expect(channel.openRate).toBeGreaterThanOrEqual(0);
        expect(channel.openRate).toBeLessThanOrEqual(100);
        expect(channel.clickRate).toBeGreaterThanOrEqual(0);
        expect(channel.clickRate).toBeLessThanOrEqual(100);
        expect(channel.conversionRate).toBeGreaterThanOrEqual(0);
        expect(channel.conversionRate).toBeLessThanOrEqual(100);
      });
    });
  });

  describe('pauseCampaign', () => {
    it('should pause a campaign', async () => {
      const result = await retentionService.pauseCampaign(1);
      expect(result).toBe(true);
    });
  });

  describe('resumeCampaign', () => {
    it('should resume a campaign', async () => {
      const result = await retentionService.resumeCampaign(1);
      expect(result).toBe(true);
    });
  });

  describe('cancelCampaign', () => {
    it('should cancel a campaign', async () => {
      const result = await retentionService.cancelCampaign(1);
      expect(result).toBe(true);
    });
  });
});
