import { AnalyticsSnapshot, type SnapshotEntityType, type SnapshotPeriod } from '@core/analytics/domain/entities/AnalyticsSnapshot';

describe('AnalyticsSnapshot', () => {
  const startDate = new Date('2025-01-01T12:00:00.000Z');
  const endDate = new Date('2025-01-02T12:00:00.000Z');

  const validMetrics = {
    pageViews: 10,
    uniqueVisitors: 3,
    avgSessionDuration: 180_000,
    bounceRate: 25,
    engagementScore: 60,
    sponsorClicks: 2,
    sponsorUrlClicks: 1,
    socialShares: 4,
    leagueJoins: 0,
    raceRegistrations: 0,
    exposureValue: 0,
  };

  const createValid = (overrides?: Partial<Parameters<typeof AnalyticsSnapshot.create>[0]>) => {
    return AnalyticsSnapshot.create({
      id: 'snapshot-1',
      entityType: 'league',
      entityId: 'entity_123',
      period: 'monthly',
      startDate,
      endDate,
      metrics: validMetrics,
      ...overrides,
    });
  };

  it('creates a snapshot with trimmed entityId', () => {
    const snapshot = createValid({ entityId: '   entity_456   ' });

    expect(snapshot.entityId).toBe('entity_456');
  });

  it('throws if id is missing', () => {
    expect(() => createValid({ id: '' })).toThrow(Error);
    expect(() => createValid({ id: '   ' })).toThrow(Error);
  });

  it('throws if entityType is missing', () => {
    expect(() => createValid({ entityType: undefined as unknown as SnapshotEntityType })).toThrow(Error);
  });

  it('throws if entityId is missing', () => {
    expect(() => createValid({ entityId: '' })).toThrow(Error);
    expect(() => createValid({ entityId: '   ' })).toThrow(Error);
  });

  it('throws if period is missing', () => {
    expect(() => createValid({ period: undefined as unknown as SnapshotPeriod })).toThrow(Error);
  });

  it('throws if endDate is before startDate', () => {
    expect(() => createValid({ startDate: endDate, endDate: startDate })).toThrow(Error);
  });

  it('createEmpty initializes metrics to zero', () => {
    const snapshot = AnalyticsSnapshot.createEmpty(
      'snapshot-empty',
      'league',
      'entity_1',
      'weekly',
      startDate,
      endDate,
    );

    expect(snapshot.metrics.pageViews).toBe(0);
    expect(snapshot.metrics.uniqueVisitors).toBe(0);
    expect(snapshot.metrics.sponsorClicks).toBe(0);
    expect(snapshot.metrics.sponsorUrlClicks).toBe(0);
    expect(snapshot.metrics.socialShares).toBe(0);
  });

  it('calculates exposure score using weighted metrics', () => {
    const snapshot = createValid({
      metrics: {
        ...validMetrics,
        pageViews: 10,
        uniqueVisitors: 3,
        sponsorClicks: 2,
        sponsorUrlClicks: 1,
        socialShares: 4,
      },
    });

    expect(snapshot.calculateExposureScore()).toBe(81);
  });

  it('returns trust indicator high/medium/low based on thresholds', () => {
    expect(
      createValid({
        metrics: { ...validMetrics, bounceRate: 25, avgSessionDuration: 180_000, engagementScore: 60 },
      }).getTrustIndicator(),
    ).toBe('high');

    expect(
      createValid({
        metrics: { ...validMetrics, bounceRate: 50, avgSessionDuration: 60_000, engagementScore: 30 },
      }).getTrustIndicator(),
    ).toBe('medium');

    expect(
      createValid({
        metrics: { ...validMetrics, bounceRate: 90, avgSessionDuration: 10_000, engagementScore: 0 },
      }).getTrustIndicator(),
    ).toBe('low');
  });

  it('formats period labels (monthly includes year)', () => {
    expect(createValid({ period: 'monthly' }).getPeriodLabel()).toBe('Jan 1, 2025 - Jan 2, 2025');
    expect(createValid({ period: 'weekly' }).getPeriodLabel()).toBe('Jan 1 - Jan 2');
  });
});